Seq2Seq и механизм внимания

алгоритм

Это 24-й день моего участия в августовском испытании обновлений. Ознакомьтесь с подробностями мероприятия: Испытание августовского обновления

В моделях языка на основе слов мы используем рекуррентные нейронные сети. Его вход представляет собой последовательность неопределенной длины, а выход имеет фиксированную длину, например, вход: Они есть, а выход может быть наблюдающим или спящим. Однако результатом многих задач является последовательность неопределенной длины. Возьмем в качестве примера машинный перевод: входные данные представляют собой абзац английского языка, выходные данные представляют собой абзац французского языка, а ввод и вывод имеют переменную длину, например.

Английский: наблюдают

Французский: lls уважительно

Когда входные и выходные последовательности имеют переменную длину, мы можем использовать кодировщик-декодер или seq2seq. Они основаны на двух работах 2014 года:

  • Cho et al., Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation
  • Sutskever et al., Sequence to Sequence Leaerning with Neural Networks

Две вышеупомянутые работы по существу используют две структуры рекуррентной нейронной сети, называемые кодировщиком и декодером соответственно. Кодер соответствует входной последовательности, а декодер соответствует выходной последовательности.

кодер-декодер

Кодер и декодер соответствуют двум рекуррентным нейронным сетям входной последовательности и выходной последовательности соответственно. Обычно мы добавляем специальный символ '' (конец последовательности) к входной последовательности и выходной последовательности, чтобы указать конец последовательности. При тестировании модели завершите текущую выходную последовательность, как только будет выведено «».

Кодер

Роль кодировщика заключается в преобразовании входной последовательности переменной длины в вектор фонового слова фиксированной длины.c\boldsymbol{c}. Вектор фонового слова содержит информацию о входной последовательности. Обычно используемые кодировщики представляют собой рекуррентные нейронные сети.

Сначала просмотрите знания о следующей рекуррентной нейронной сети. Предположим, что единицей рекуррентной нейронной сети являетсяff,существуетttВвод времениxt,t=1,...,Tx_t,t=1,...,T. Предположениеxt\boldsymbol{x}_tявляется результатом одного вывода на уровне внедрения, например.xt\boldsymbol{x}_tСоответствующий горячий векторoеRx\boldsymbol{o}\in \mathbb{R}^xс матрицей параметров слоя внедренияEеRx×h\boldsymbol{E}\in \mathbb{R}^{x\times h}продуктoE\boldsymbol{o}^\top\boldsymbol{E}. скрытая переменная слоя

ht=f(xt,ht1)\boldsymbol{h}_t = f(\boldsymbol{x}_t, \boldsymbol{h}_{t-1})

Вектор фона кодировщика

c=q(h1,,hT)\boldsymbol{c} = q(\boldsymbol{h}_1, \ldots, \boldsymbol{h}_T)

Простой фоновый вектор можно рассматривать как переменную скрытого слоя в конце сети.hT\boldsymbol{h}_T. Мы называем здесь рекуррентную нейронную сеть кодировщиком.

Двунаправленная рекуррентная нейронная сеть

Вход в кодировщик может быть как прямым, так и обратным проходом. Если входная последовательностьx1,x2,...,xT\boldsymbol{x}_1,\boldsymbol{x}_2,...,\boldsymbol{x}_T, в прямом проходе переменная скрытого слоя

ht=f(xt,ht1)\overrightarrow {\boldsymbol{h}}_t = f(\boldsymbol{x}_t,\overrightarrow {\boldsymbol{h}}_{t-1})

В процессе обратного переноса вычисление переменных скрытого слоя становится

ht=f(xt,ht1)\overleftarrow {\boldsymbol{h}}_t = f(\boldsymbol{x}_t,\overleftarrow {\boldsymbol{h}}_{t-1})

Мы можем использовать двунаправленную рекуррентную нейронную сеть, когда хотим, чтобы вход кодировщика содержал информацию как о прямом, так и о обратном проходе. Например, если задана входная последовательностьx1,x2,...,xT\boldsymbol{x}_1,\boldsymbol{x}_2,...,\boldsymbol{x}_T, согласно прямому проходу, их переменные скрытого слоя в рекуррентной нейронной сети соответственноh1,h2,...,hT\vec {\boldsymbol{h}}_1,\vec {\boldsymbol{h}}_2,...,\vec {\boldsymbol{h}}_T; согласно обратному распространению, их переменные скрытого слоя в рекуррентной нейронной сети соответственноh1,h2,...,hT\overleftarrow{\boldsymbol{h}}_1,\overleftarrow{\boldsymbol{h}}_2,...,\overleftarrow{\boldsymbol{h}}_T. В двунаправленной рекуррентной нейронной сети моментiiПеременная скрытого слоя — этоhi\vec{\boldsymbol{h}}_iиhi\overleftarrow{\boldsymbol{h}}_iсоединены вместе, напр.

import numpy as np
h_forward = np.array([1, 2])
h_backward = np.array([3, 4])
h_bi = np.concat(h_forward, h_backward, dim=0)
# [1, 2, 3, 4]

декодер

Кодер наконец выводит фоновый векторc\boldsymbol{c}, фоновый вектор интегрирует входную последовательностьx1,x2,...,xT\boldsymbol{x}_1,\boldsymbol{x}_2,...,\boldsymbol{x}_T

Предположим, что выходная последовательность в обучающих данных равнаy1,y2,...,yT'\boldsymbol{y}_1,\boldsymbol{y}_2,...,\boldsymbol{y}_{T'}, мы хотим представить каждыйt't'Выходной вектор в данный момент зависит как от предыдущего вывода, так и от фонового вектора. Потому что мы можем максимизировать совместную вероятность выходной последовательности

P(y1,y2,...,yT')=t'=1T'P(yt'y1,...,yt'1,c)P(\boldsymbol{y}_1,\boldsymbol{y}_2,...,\boldsymbol{y}_{T'})=\prod_{t'=1}^{T'}P(\boldsymbol{y}_{t'}\mid \boldsymbol{y}_1,...,\boldsymbol{y}_{t'-1},\boldsymbol{c})

и получить функцию потерь для этой выходной последовательности

logP(y1,...,yT')-\log P(\boldsymbol{y}_1,...,\boldsymbol{y}_{T'})

Для этого в качестве декодера используем другую рекуррентную нейронную сеть. Функция использования декодераppдля представления одного выходаyt'\boldsymbol{y}_{t'}Вероятность

P(yt'y1,...,yt'1,c)=p(yt'1,st',c)P(\boldsymbol{y}_{t'}\mid \boldsymbol{y}_1,...,\boldsymbol{y}_{t'-1},\boldsymbol{c})=p(\boldsymbol{y}_{t'-1},\boldsymbol{s}_{t'},\boldsymbol{c})

один из нихst'\boldsymbol{s}_{t'}заt't'Скрытая переменная слоя декодера на данный момент. Переменная скрытого слоя

st'=g(yt'1,c,st'1)\boldsymbol{s}_{t'}=g(\boldsymbol{y}_{t'-1},\boldsymbol{c},\boldsymbol{s}_{t'-1})

где функция g — единица рекуррентной нейронной сети

Важно отметить, что кодеры и декодеры обычно используютМногослойная рекуррентная нейронная сеть

механизм внимания

В приведенном выше дизайне декодера в каждый момент используется один и тот же фоновый вектор.c\boldsymbol{c}. Что, если бы в разные моменты работы декодера можно было бы использовать разные векторы фона?

Взяв в качестве примера англо-французский перевод, учитывая пару входной последовательности «Они смотрят» и выходной последовательности «lls resent», декодер может использовать больше фоновых векторов, кодирующих информацию «Они» в момент времени 1, для генерации «lls», в то время как время от времени еще 2 фоновых вектора, кодирующие «наблюдаемую» информацию, могут использоваться для генерации «регардента». Это выглядит так, как будто декодер уделяет разное внимание разным моментам во входной последовательности в каждый момент времени. Это также источник механизма внимания.

Теперь небольшая модификация приведенного выше декодера. мы предполагаем моментt't'Фоновый векторct'\boldsymbol{c}_{t'}. то декодер на данный моментt't'Скрытая переменная слоя

st'=g(yt'1,ct',st'1)\boldsymbol{s}_{t'}=g(\boldsymbol{y}_{t'-1},\boldsymbol{c}_{t'},\boldsymbol{s}_{t'-1})

пусть кодер будетttСкрытая переменная слоя во времяht\boldsymbol{h}_t, декодер находится вt't'Фоновый вектор момента

ct'=t=1Tαt'tht\boldsymbol{c}_{t'}=\sum_{t=1}^{T}\alpha_{t't}\boldsymbol{h}_t

То есть, учитывая текущий момент декодераt't', нам нужно взять средневзвешенное значение переменных скрытого слоя в разное время в кодировщике. Веса также называются весами внимания. Его формула расчета

αt't=exp(et't)k=1Texp(et'k)\alpha_{t' t} = \frac{\exp(e_{t' t})}{ \sum_{k=1}^T \exp(e_{t' k}) }

иet'tеRe_{t' t}\in \mathbb{R}Формула расчета

et't=a(st'1,ht)e_{t' t} = a(\boldsymbol{s}_{t' - 1}, \boldsymbol{h}_t)

где функцияaaСуществует несколько подходов к дизайну. существуетБумага Богдановасередина

et't=vtanh(Wsst'1+Whht),\boldsymbol{e}_{t't} = \boldsymbol{v}^\top \tanh(\boldsymbol{W}_s \boldsymbol{s}_{t'-1} + \boldsymbol{W}_h \boldsymbol{h}_t),

вv\boldsymbol{v},Ws\boldsymbol{W}_s,Wh\boldsymbol{W}_hВеса и смещения, а также параметры слоя встраивания в двух рекуррентных нейронных сетях кодировщика и декодера — все это параметры модели, которые необходимо изучать одновременно.

существуетБумага БогдановаВ статье и энкодер, и декодер используют ГРУ.

В дешифраторе нужно немного изменить конструкцию ГРУ, предположивyt\boldsymbol{y}_tявляется результатом одного вывода на уровне внедрения, например.yt\boldsymbol{y}_tСоответствующий горячий векторoеRy\boldsymbol{o}\in \mathbb{R}^yс матрицей параметров слоя внедренияBеRy×s\boldsymbol{B}\in \mathbb{R}^{y\times s}продуктoB\boldsymbol{o}^\top\boldsymbol{B}. Гипотетический моментt't'Фоновый векторct'\boldsymbol{c}_{t'}. то декодер на данный моментt't'одна скрытая переменная слоя

st'=zt'st'1+(1zt')s~t'\boldsymbol{s}_{t'} = \boldsymbol{z}_{t'} \odot \boldsymbol{s}_{t'-1} + (1 - \boldsymbol{z}_{t'}) \odot \tilde{\boldsymbol{s}}_{t'}

Среди них шлюз сброса, шлюз обновления и скрытое состояние кандидата соответственно.

rt'=о(Wyryt'1+Wsrst'1+Wcrct'+br),zt'=о(Wyzyt'1+Wszst'1+Wczct'+bz),s~t'=tanh(Wysyt'1+Wss(st'1rt')+Wcsct'+bs),\begin{aligned} \boldsymbol{r}_{t'} &= \sigma(\boldsymbol{W}_{yr} \boldsymbol{y}_{t'-1} + \boldsymbol{W}_{sr} \boldsymbol{s}_{t' - 1} + \boldsymbol{W}_{cr} \boldsymbol{c}_{t'} + \boldsymbol{b}_r),\\ \boldsymbol{z}_{t'} &= \sigma(\boldsymbol{W}_{yz} \boldsymbol{y}_{t'-1} + \boldsymbol{W}_{sz} \boldsymbol{s}_{t' - 1} + \boldsymbol{W}_{cz} \boldsymbol{c}_{t'} + \boldsymbol{b}_z),\\ \tilde{\boldsymbol{s}}_{t'} &= \tanh(\boldsymbol{W}_{ys} \boldsymbol{y}_{t'-1} + \boldsymbol{W}_{ss} (\boldsymbol{s}_{t' - 1} \odot \boldsymbol{r}_{t'}) + \boldsymbol{W}_{cs} \boldsymbol{c}_{t'} + \boldsymbol{b}_s), \end{aligned}

Суммировать

  • На вход и на выход кодера-декодера (seq2seq) могут быть как последовательности переменной длины
  • Применение механизма внимания к декодеру позволяет декодеру использовать другой фоновый вектор в каждый момент времени. Каждый фоновый вектор эквивалентен назначению разного внимания разным частям входной последовательности.