Изменения

Перейти к: навигация, поиск

Трансформер

1086 байт добавлено, 19:11, 4 сентября 2022
м
rollbackEdits.php mass rollback
==Архитектура трансформера==
[[Файл:TransformerSimpleArchitecture.png|350px400px|thumb|right|Архитектура трансформера<ref>https://jalammar.github.io/illustrated-transformer/</ref>]]Устройство трансформера состоит из кодирующего и декодирующего компонентов. На вход принимается некая последовательность, создается ее [[:Векторное_представление_слов|векторное представление]] (англ. ''embedding''), векторизованная последовательность прибавляется вектор позиционного кодирования, после чего набор элементов без учета порядка в последовательности поступает в кодирующий компонент(параллельная обработка), а затем декодирующий компонент получает на вход часть этой последовательности и выход кодирующего. В результате получается новая выходная последовательность.  Кодирующий компонент {{---}} это стек кодировщиков (англ. ''encoders''), а декодирующий компонент {{---}} это стек декодировщиков (англ. ''decoders''). Каждый кодировщики последовательно передает результат своей работы следующему кодировщику на вход. Декодировщики последовательно передают друг другу на вход результат работы вместе с результатом кодирующего компонента.
Внутри кодирующего и декодирующего компонента нет рекуррентности. Кодирующий компонент состоит из кодировщиков, которые повторяются несколько раз, аналогично устроен декодирующий компонент. Трансформер {{---}} это поставленные друг за другом модели внимания, которые позволяют исходную последовательность векторов перевести в новую последовательность векторов, которые кодируют информацию о контексте каждого элемента. Трансформер-кодировщик переводит исходные векторы в скрытые, которые правильно сохраняют в себе информацию о контексте каждого элемента. Далее трансформер-декодировщик декодирует результат кодировщика в новую последовательность, которая состоит из эмбедингов элементов выходного языка. После по эмбедингам генерируются сами итоговые элементы с помощью вероятностной языковой модели.
Ниже рассмотрим архитектуру кодировщика и декодировщика подробнее.
==Архитектура трансформера-кодировщика==
[[Файл:TransformerEncoderArchitecture.png|150px|thumb|left|Архитектура трансформера-кодировщика<ref>https://arxiv.org/abs/1706.03762</ref>]]
Рассмотрим последовательно шаг за шагом этапы работы кодировщика:
1. На вход поступает последовательность элементов <math>w_i</math>, по ней создается последовательность эмбедингов, где каждый <math>x_i</math> это векторное представление элемента <math>w_i</math>.
4. Затем необходима конкатенация, чтобы вернуться в исходную размерность: <math> h'_i = M H_j (h^j_i) = [h^1_i...h^J_i] </math>
5. Добавим сквозные связи (англ. ''skip connection'') {{---}} по факту просто добавление из входного вектора к выходному (<math>h'_i + h_i</math>). После делаем нормировку уровня нормализацию слоя (англ. ''layer normalization''): <math>h''_i = \mathrm{LN}(h'_i + h_i; \mu_1, \sigma_1)</math>. У нее два обучаемых параметра, для каждой размерности вектора вычисляется среднее и дисперсия.
6. Теперь добавим преобразование, которое будет обучаемым {{---}} полносвязную двухслойную нейронную сеть:
<math> h'''_i = W_2 \mathrm{ReLU} (W_1 h''_i + b_1) + b_2 </math>
7. Повторим пункт 5 еще раз: добавим сквозную связь и нормировку уровнянормализацию слоя: <math>z_i = \mathrm{LN}(h'''_i + h''_i; \mu_2, \sigma_2)</math>
После, в кодирующем компоненте пункты кодировщика 3--7 повторяются еще несколько раз, преобразовывая друг за другом из контекста контекст. Тем самым мы обогащаем модель и увеличиваем в ней количество параметров.
===Позиционное кодирование===
[[Файл:PositionalEncodingPositionalEncodingNew.png|400px|thumb|right|Визуализация работы позиционного кодирования<ref>httphttps://wwwkazemnejad.machinelearning.rucom/blog/wikitransformer_architecture_positional_encoding/index.php</ref>]]Так как в архитектуре трансформер обработка последовательности заменяется на обработку множества мы теряем информацию о порядке элементов последовательности. Чтобы отобразить информацию о позиции элемента в исходной последовательности мы используем позиционное кодирование. Позиционное кодирование (англ. ''positional encoding'') {{---}} позволяет модели получить информацию о порядке элементов в последовательности путем прибавления специальных меток к вектору входных элементов. Позиции элементов <math>i</math> кодируются векторами <math>p_i</math>, <math>i = 1, 2, ..., n</math>, так, что чем больше <math>|i - j|</math>, тем больше <math>||p_i - p_j||</math>, и <math>n</math> не ограничено. Пример такого кодирования:<math>p_{(i, s)} = \sin \left(i \cdot 10000^{\frac{-2s}{d_{model}}}\right)</math>,<math>p_{(i, s + \frac{d}{2})} = \cos \left(i \cdot 10000^{\frac{-2s}{d_{model}}}\right)</math>
По сути мы свели задачу обработки последовательности <math> p_{(''seq''i, s) к множеству } = \begin{cases} \sin \left(''set''i \cdot 10000^{\frac{-2k}{d_{model}}}\right). & \quad \text{если } s=2k\\ \cos \left(i \cdot 10000^{\frac{-2k}{d_{model}}}\right) & \quad \text{если } s=2k+1 \end{cases}</math>
===Self-attention===
* Значение (''value'') <math>v_i = V x_i</math>
Векторы <math>q_i</math> и <math>k_i</math> будем использовать, что чтобы посчитать важность элемента <math>x_j</math> для элемента <math>x_i</math>. Чтобы понять, насколько для пересчета вектора элемента <math>x_i</math> важен элемент <math>x_j</math> мы берем <math>k_j</math> (вектор ключа элемента <math>x_j</math>) и умножаем на <math>q_i</math> (вектор запроса элемента <math>x_i</math>). Так мы скалярно перемножаем вектор запроса на все векторы ключей, тем самым понимаем, насколько каждый входной элемент нам нужен, чтобы пересчитать вектор элемента <math>x_i</math>.
Далее считаем важность влияния элемента <math>x_j</math> для кодирования элемента <math>x_i</math>:
<math>w_{ji}=\frac{
\exp \left(\frac{\langle q_i, k_j \rangle}{\sqrt{d}} \right)
<math> h''_t = \mathrm{LN} \circ M H_j \circ \mathrm{Attn}(Q^j h_t, K^j Z, V^j Z) </math>
4. Линейная полносвязная сеть (по аналогии, как и в кодировщикес кодировщиком):
<math> y_t = \mathrm{LN} \circ FNN(h''_t) </math>
5. Линейный предсказывающий слойВ самом конце мы хотим получить вероятностную порождающую модель для элементов. Результат (индекс слова с наибольшей вероятностью):<math> p(\tilde w|t) = \mathrm{Soft-argmax}_{\tilde wSoftArgMax}(W_y y_t + b_y) </math>, где <math> W_y </math>, <math> b_y </math> {{---}} обучаемые параметры линейного преобразования. Для каждой позиции <math>t</math> выходной последовательности мы строим вероятностную модель языка, то есть все элементы из выходного словаря получают значение вероятности. Эти значения как раз получаются из векторов <math>y_t</math> из предыдущего пункта, которые мы берем с последнего блока трансформера-декодировщика. Последний этап выполняется только после того, когда повторились пункты 1-4 для всех декодировщиков. На выходе получаем вероятности классов, по факту решаем для каждого класса задачу многоклассовой классификации, для того, чтобы понять какие элементы лучше поставить на каждые позиции.
В самом конце мы имеем вероятностную порождающую модель Последний этап выполняется только после того, когда повторились пункты 1--4 для элементов и остается только породить эти элементывсех декодировщиков. Для простоты мы будем считатьНа выходе получаем вероятности классов, что по факту для каждой позиции просто выбирается самый вероятный элемент. Генерация самих элементов: <math> {\tilde w}_t = \mathrm{arg max}_{\tilde w} p(\tilde w|t) </math>решаем задачу многоклассовой классификации, для того, пока не сгенерируется слово обозначающее конец последовательностичтобы понять какие элементы лучше поставить на каждые позиции.
==Источники информации==
1632
правки

Навигация