Изменения

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

Трансформер

436 байт добавлено, 00:17, 11 июня 2022
обновление стилей
==Архитектура трансформера==
[[Файл:TransformerSimpleArchitecture.png|350px|thumb|right|Архитектура трансформера<ref>https://jalammar.github.io/illustrated-transformer/</ref>]]
Устройство трансформера состоит из кодирующего и декодирующего компонентов. На вход принимается некая последовательность, создается ее [[:Векторное_представление_слов|векторное представление]] (англ. ''embedding''), векторизованная последовательность поступает в кодирующий компонент, а затем декодирующий компонент получает на вход часть этой последовательности и выход кодирующего. В результате получается новая выходная последовательность.
==Архитектура трансформера-кодировщика==
[[Файл:TransformerEncoderArchitecture.png|150px|thumb|left|Архитектура трансформера-кодировщика<ref>https://arxiv.org/abs/1706.03762</ref>]]
Рассмотрим последовательно шаг за шагом этапы кодировщика:
3. Полученный вектор <math>h_i</math> подается на вход в блок многомерного самовнимания (англ. ''multi-headed self-attention'').
<math>h^j_i = \mathrm{Attn}(W^j_q h_i, W^j_k H, W^j_v H)</math>, где <math>W</math> {{- --}} обучаемые матрицы, <math>W_q</math> для запроса, <math>W_k</math> для ключа, <math>W_v</math> для значения. Подробное объяснения работы механизма self-attention будет разобрано ниже.
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. Теперь добавим преобразование, которое будет обучаемым {{- --}} полносвязную 2х-слойную двухслойную нейронную сеть: <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 повторяются еще несколько раз, преобразовывая друг за другом из контекста контекст. Тем самым мы обогащаем модель и увеличиваем в ней количество параметров.
===Позиционное кодирование===
[[Файл:PositionalEncoding.png|450px400px|thumb|right|Визуализация работы позиционного кодирования<ref>http://www.machinelearning.ru/wiki/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>
===Self-attention===
Далее считаем важность влияния элемента <math>x_j</math> для кодирования элемента <math>x_i</math>:
<math>w_{ji}=\frac{
\exp\left(\frac{\langle q_i, k_j \rangle}{\sqrt{d}}\right)
}{
\sum_{p=1}^n \exp\left(\frac{\langle q_i, k_p \rangle}{\sqrt{d}}\right)
}</math>,
где <math>d</math> {{- --}} размерность векторов <math>q_i</math> и <math>k_j</math>, а <math>n</math> {{--- }} число элементов во входной последовательности.
Таким образом, новое представление элемента <math>x_i</math> считаем как взвешенную сумму векторов значения: <math>z_i = \mathrm{Attn}(W_q x_i, W_k X, W_v X) = \sum_{p=1}^n w_{p i} v_p</math>, где <math>X = (x_1, x_2, ..., x_n)</math> {{- --}} входные векторы. По итогу мы перемешиваем все входные векторы, чтобы получить новые векторы всех элементов, где каждый элемент зависит от всех входных элементов.
===Multi-headed self-attention===
То есть параллельно независимо несколько раз делаем attention. Потом результат каждого attention по элементам конкатенируем, затем сжимаем получившуюся матрицу и получаем для каждого элемента свой вектор той же размерности.
<math>с^j = \mathrm{Attn}(W^j_q q, W^j_k X, W^j_v X)</math>, где <math>j = 1...J</math>, <math>J</math> {{- количество --}} число разных моделей внимания, <math>X = (x_1, x_2, ..., x_n)</math> {{--- }} входные векторы, а <math>W</math> {{--- }} обучаемые матрицы.
==Архитектура трансформера-декодировщика==
[[Файл:TransformerDecoderArchitecture.png|150px|thumb|left|Архитектура трансформера-декодировщика<ref>https://arxiv.org/abs/1706.03762</ref>]]
На вход декодировщику подается выход кодировщика. Главное отличие архитектуры декодировщика заключается в том, что дополнительно имеется attention к вектору, который получен из последнего блока кодирующего компонента. Компонент декодировщика тоже многослойный и каждому блоку компонента на вход подается вектор именно с последнего блока кодирующего компонента. Разберем по порядку этапы работы декодировщика:
2. Далее идет этап многомерного самовнимания: линейная нормализация и multi-headed self-attention. Особенность в том, что в attention ключи и значения применяются не ко всем векторам, а только к тем, значения которых уже синтезировали (<math>H_t</math>):
<math> h'_t = \mathrm{LN } \circ M H_j \circ \mathrm{Attn}(W^j_q h_t, W^j_k H_t, W^j_v H_t) </math>
3. На следующем этапе мы делаем многомерное внимание на кодировку <math>Z</math>, результат работы компонента кодировщика:
<math> h''_t = \mathrm{LN } \circ M H_j \circ \mathrm{Attn}(W^j_q h_t, W^j_k Z, W^j_v Z) </math>
4. Линейная полносвязная сеть (по аналогии, как и в кодировщике):
<math> y_t = \mathrm{LN } \circ FNN(h''_t) </math>
5. Линейный предсказывающий слой:
<math> p(\tilde w|t) = SoftMax_\mathrm{SoftMax}_{\tilde w}(W_y y_t + b_y) </math>, <math> W_y </math> {{--- }} обучаемая матрица весовых коэффицентов, <math> b_y </math> {{- --}} обучаемый вектор смещения
Последний этап выполняется только после того, когда повторились пункты 1-4 для всех декодировщиков. На выходе получаем вероятности классов, по факту решаем для каждого класса задачу многоклассовой классификации, для того, чтобы понять какие элементы лучше поставить на каждые позиции. В самом конце происходит генерация самих элементов: <math> {\tilde w}_t = \mathrm{arg max_max}_{\tilde w} p(\tilde w|t) </math>, пока не сгенерируется слово обозначающее конец последовательности.
==Источники информации==
23
правки

Навигация