Глава 1.5 — Внимание до трансформеров

Содержание

  1. Проблема, сформулированная точно
  2. Внимание Бахданау: пусть декодировщик оглядывается назад
  3. Как вычисляются и используются оценки выравнивания
  4. Внимание Луонга: более простой и универсальный рецепт
  5. Что внимание изменило, а что нет
  6. Взгляд с точки зрения собеседования
  7. Вопросы для самопроверки
  8. Источники

1. Проблема, сформулированная точно

Глава 1.4 закончилась на конкретном, ощутимом режиме отказа: в модели «последовательность-в-последовательность» кодировщику приходится сжимать всё входное предложение в единственный вектор фиксированного размера ещё до того, как декодировщик начнёт что-либо генерировать, и это сжатие становится информационным узким местом по мере удлинения предложений. Стоит точно понять, почему это именно узкое место, а не просто смутная неэффективность: на каждом отдельном шаге декодирования декодировщик работает с одним и тем же вектором-сводкой, независимо от того, какая часть входного предложения реально релевантна слову, которое он генерирует прямо сейчас. Перевод пятого слова длинного предложения и перевод пятидесятого слова опираются на идентичную, недифференцированную информацию обо всём входе.

Решение, предложенное независимо в очень похожих формах Дмитрием Бахданау (Dzmitry Bahdanau), Кёнхюном Чо (Kyunghyun Cho) и Йошуа Бенджио (Yoshua Bengio), а вскоре после этого — Минь-Тхангом Луонгом (Minh-Thang Luong), Хиеу Фамом (Hieu Pham) и Кристофером Мэннингом (Christopher Manning), состоит в том, чтобы вообще перестать сжимать вход в один вектор. Вместо этого нужно сохранить скрытое состояние кодировщика на каждой входной позиции и позволить декодировщику на каждом шаге генерации вычислять взвешенную комбинацию всех этих скрытых состояний — комбинацию, которая меняется на каждом шаге декодирования, так что декодировщик может «смотреть» на разные части входа в зависимости от того, что он сейчас генерирует. Это и есть внимание (attention), и это самая значимая идея во всей этой книге, потому что механизм, введённый здесь для решения одной конкретной задачи перевода, по своей базовой математике практически без изменений оказывается той самой операцией, из которой целиком построены трансформеры.

2. Внимание Бахданау: пусть декодировщик оглядывается назад

Статья Бахданау и соавторов 2014 года (опубликованная на ICLR 2015) формулирует это решение как «совместное обучение выравниванию и переводу» (jointly learning to align and translate) — слово «выравнивание» (align) в этом названии не случайно. Вместо единственного суммирующего вектора кодировщик (двунаправленная RNN, так что скрытое состояние каждой позиции отражает контекст с обеих сторон) порождает по одному скрытому состоянию на каждый входной токен: \(h_1, h_2, \ldots, h_T\).

На каждом шаге декодирования \(i\) декодировщик не просто потребляет единственный фиксированный контекстный вектор — он вычисляет новый, специфичный именно для этого шага, как взвешенную сумму по всем скрытым состояниям кодировщика:

$$c_i = \sum_{j=1}^{T} \alpha_{ij} h_j$$

Веса \(\alpha_{ij}\) (которые в сумме по \(j\) дают 1, за счёт softmax) — это «веса внимания» (attention weights): насколько сильно шаг декодирования \(i\) должен обращать внимание на входную позицию \(j\). Принципиально важно, что эти веса вычисляются динамически из текущего состояния декодировщика и каждого скрытого состояния кодировщика, а значит, модель в процессе обучения сама выучивает, какие входные позиции важны для каких выходных позиций, — это и есть «выравнивание» (alignment), о котором говорит название статьи, и конкретно для перевода эти выученные выравнивания зачастую поразительно хорошо соответствуют реальным пословным или пофразовым соответствиям между исходным и целевым языками, хотя модели никогда явно не сообщали об этих соответствиях.

3. Как вычисляются и используются оценки выравнивания

Веса \(\alpha_{ij}\) получаются нормализацией набора сырых оценок выравнивания \(e_{ij}\), по одной на каждую позицию кодировщика, вычисляемых сравнением текущего состояния декодировщика с каждым скрытым состоянием кодировщика:

$$\alpha_{ij} = \frac{\exp(e_{ij})}{\sum_{k=1}^{T} \exp(e_{ik})}, \qquad e_{ij} = a(s_{i-1}, h_j)$$

где \(s_{i-1}\) — скрытое состояние декодировщика с предыдущего шага, а \(a\) — небольшая обучаемая функция (в исходной формулировке Бахданау — прямая сеть с одним скрытым слоем), оценивающая, насколько хорошо позиция кодировщика \(j\) соответствует тому, что сейчас нужно декодировщику. Это стоит разобрать подробно, потому что именно эта трёхчастная структура — вычислить оценку совместимости между «запросом» (query, текущее состояние декодировщика) и набором «ключей» (keys, состояния кодировщика), нормализовать эти оценки с помощью softmax и использовать результат для взвешивания набора «значений» (values, снова состояния кодировщика) — это в точности структура механизма внимания внутри каждого трансформера, обсуждаемого далее в этой книге. Терминология «запрос/ключ/значение» (query/key/value) в 2014 году ещё не была введена, а функция оценки была сложнее той, что появилась позже, но базовая операция — дифференцируемый, обучаемый, взвешенный softmax'ом поиск по набору векторов — идентична.

Контекстный вектор \(c_i\), полученный таким образом, затем комбинируется с собственным состоянием декодировщика для получения фактического предсказания на выходе для шага \(i\). Всё целиком — кодировщик, вычисление оценок выравнивания, взвешенная комбинация, декодировщик — обучается end-to-end обычным обратным распространением ошибки, точно так же, как и остальные модели в этой книге; ничто в весах внимания не задаётся вручную и не обучается отдельно с учителем.

4. Внимание Луонга: более простой и универсальный рецепт

Статья Луонга, Фама и Мэннинга 2015 года пришла к очень похожей идее через несколько иную, более систематическую формулировку, и её основным вкладом стало упрощение и обобщение функции оценки \(a(s, h)\), а также предложение вариантов «глобального» (global) и «локального» (local) внимания (обращать внимание на всю входную последовательность или на ограниченное окно вокруг предсказанной позиции).

Вместо небольшой прямой сети Бахданау, Луонг с соавторами предложили и сравнили несколько более простых функций оценки, в первую очередь скалярное произведение состояний декодировщика и кодировщика (\(s^\top h\)) и «общую» билинейную форму (\(s^\top W h\)) с обучаемой матрицей весов \(W\). Вариант со скалярным произведением особенно значим далеко за пределами этой главы: он, с точностью до масштабирующего множителя, в точности является функцией совместимости, используемой внутри масштабированного скалярного внимания (scaled dot-product attention) в трансформере — \(\frac{QK^\top}{\sqrt{d_k}}\), где масштабирующий множитель \(\sqrt{d_k}\) добавлен по соображениям численной устойчивости, которые подробно разбираются в главе 2.1. Статья Луонга также прояснила архитектурную деталь, широко перенятую последующими работами: вычислять контекстный вектор внимания и объединять его со скрытым состоянием декодировщика перед тем, как делать предсказание на выходе для этого шага, а не встраивать внимание в саму рекуррентность, — это упростило рассуждение о механизме и его встраивание в различные конструкции декодировщика.

Практический результат обеих статей был одинаков: существенно улучшенное качество машинного перевода, особенно на длинных предложениях, именно потому что узкое место кодировщика-декодировщика исчезло — декодировщик теперь всегда мог обратиться к тем конкретным входным позициям, которые были релевантны тому, что он генерировал, вместо того чтобы работать с одной сжатой сводкой всего предложения.

5. Что внимание изменило, а что нет

Стоит точно понимать масштаб того, что внимание исправило на этом этапе истории книги, потому что скачок следующей главы больше, чем просто «внимание, но лучше», и понимание границы здесь делает этот скачок более ясным.

Что внимание исправило: конкретно узкое место кодировщика-декодировщика. Декодировщику больше не нужно пропускать всё необходимое через единственный вектор фиксированного размера; он может динамически извлекать информацию из любой части входной последовательности, релевантной текущему шагу генерации.

Чего внимание не исправило в этих формулировках 2014–2015 годов: базовая архитектура по-прежнему строилась на RNN. Кодировщик по-прежнему обрабатывал вход по одному токену последовательно, а значит, обучение всё ещё нельзя было распараллелить по позициям внутри последовательности, а связанные с затухающим градиентом трудности очень длинных последовательностей (глава 1.4) были смягчены, но не устранены, поскольку сама рекуррентность оставалась нетронутой — внимание добавило способ дотянуться до любой позиции кодировщика, но вычисление самих этих позиций кодировщика по-прежнему требовало пошагового прохода по последовательности.

Формулировки Бахданау и Луонга наиболее важны для прослеживания прямой линии к трансформерам, но они были лишь первым ходом в гораздо более широком семействе вариантов внимания — разные функции оценки, внимание над банками памяти, а не только над состояниями кодировщика, иерархическое внимание сперва над словами, а затем над предложениями, — расцветшем в исследованиях NLP середины 2010-х; обзор Galassi с соавторами — хорошая карта этого более широкого ландшафта, если она вам нужна, хотя сквозной линии этой книги достаточно двух разобранных выше формулировок.

Это подводит ровно к тому вопросу, на который отвечает следующая глава: что, если рекуррентность вообще не нужна? Что, если внимание — механизм, вычисляющий взвешенную комбинацию по набору векторов на основе обучаемых оценок совместимости, — можно использовать не только для того, чтобы декодировщик оглядывался на кодировщик, а как весь целиком механизм, посредством которого модель строит контекстуальные представления последовательности, полностью отбросив рекуррентность? Этот вопрос и ответ на него — «Attention Is All You Need» («Внимание — это всё, что вам нужно») — название статьи, открывающей часть II этой книги, и это не случайное эхо того, что вы только что прочитали.

6. Взгляд с точки зрения собеседования

Эта глава — любимая для проверки того, понимает ли кандидат внимание как идею, а не просто как «то, что внутри трансформеров»:

  • «Какую конкретно проблему решает внимание и какой механизм оно заменило?» — ожидаемый ответ прямо называет узкое место кодировщика-декодировщика, а не расплывчатое «внимание позволяет модели фокусироваться на важном».
  • «Проведите меня по шагам, как на самом деле вычисляется вес внимания» — это проверка того, можете ли вы конкретно изложить конвейер запрос/оценка совместимости/softmax/взвешенная сумма, в идеале используя терминологию запрос-ключ-значение даже для версии до трансформеров.
  • «В чём разница между вниманием Бахданау и вниманием Луонга?» — сильный ответ определяет функцию оценки (прямая сеть против скалярного произведения/билинейной формы) как главное различие и может объяснить, почему вариант со скалярным произведением предвосхищает масштабированное скалярное внимание.
  • «Почему RNN плюс внимание оказалось недостаточно — почему область перешла к архитектуре, полностью основанной на внимании?» — ожидаемый ответ касается параллелизма и эффективности обучения в большом масштабе, а не только качества моделирования; это прямой мостик к главе 2.1.

7. Вопросы для самопроверки

  1. Точно опишите узкое место кодировщика-декодировщика из главы 1.4 и объясните, что именно внимание меняет в доступе декодировщика к информации кодировщика.
  2. Запишите уравнение для контекстного вектора \(c_i\) как взвешенной суммы скрытых состояний кодировщика и объясните, откуда берутся веса \(\alpha_{ij}\).
  3. Каковы три компонента общего паттерна внимания (как его позже назовут: запрос, ключ, значение) и как они соотносятся с состоянием декодировщика Бахданау, состояниями кодировщика и снова состояниями кодировщика?
  4. Сравните функцию оценки на основе прямой сети у Бахданау с функцией оценки на основе скалярного произведения у Луонга. Почему вариант со скалярным произведением важнее для остальной части этой книги?
  5. Что внимание (в его форме на основе RNN 2014–2015 годов) не смогло исправить в базовой архитектуре? Будьте конкретны в том, что по-прежнему требовало последовательных вычислений.
  6. Почему «отбросить рекуррентность и оставить только механизм внимания» — это логичный следующий шаг, а не несвязанная новая идея? Постарайтесь сформулировать в одном-двух предложениях, что, по вашим ожиданиям, потребуется добавить полностью основанной на внимании архитектуре, чтобы заменить то, что раньше обеспечивала рекуррентность.

8. Источники

  • Bahdanau, D., Cho, K., & Bengio, Y. (2014/2015). Neural Machine Translation by Jointly Learning to Align and Translate. ICLR 2015. arXiv:1409.0473
  • Luong, M.-T., Pham, H., & Manning, C. D. (2015). Effective Approaches to Attention-based Neural Machine Translation. EMNLP 2015. arXiv:1508.04025
  • Galassi, A., Lippi, M., & Torroni, P. (2020). Attention in Natural Language Processing. IEEE Transactions on Neural Networks and Learning Systems. arXiv:1902.02181

Тест для самопроверки

Проверьте понимание главы с помощью короткого теста — вопросы по теории и небольшие расчёты.

Какую конкретную проблему решает внимание (Бахданау/Луонг) в seq2seq-модели на RNN?

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

Как функция оценки на основе скалярного произведения из статьи Луонга соотносится с тем, что появится позже в книге?

Объяснение: Оценка скалярного произведения Луонга s·h предвосхищает член QKᵀ в масштабированном скалярном внимании — та же базовая операция, только без масштабирования на √d_k и без обучаемых проекций Q/K/V.

Что внимание (в его форме на RNN 2014–2015 годов) не смогло исправить в базовой архитектуре?

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

В терминах запрос/ключ/значение, применённых задним числом к вниманию Бахданау, что играет роль «запроса»?

Объяснение: Состояние декодировщика — это то, что «ищет» релевантную информацию, то есть запрос, а скрытые состояния кодировщика служат одновременно и ключами (для оценки), и значениями (для взвешенной суммы).

Даны скрытые состояния кодировщика (в виде скаляров для простоты) $h_1 = 2$, $h_2 = 4$, $h_3 = 6$ и веса внимания $\alpha_{i1} = 0.1$, $\alpha_{i2} = 0.3$, $\alpha_{i3} = 0.6$. Вычислите контекстный вектор $c_i = \sum_j \alpha_{ij} h_j$.

Объяснение: c_i = 0.1(2) + 0.3(4) + 0.6(6) = 0.2 + 1.2 + 3.6 = 5.0.

Сырые оценки выравнивания для трёх позиций кодировщика: $e_{i1} = 1$, $e_{i2} = 2$, $e_{i3} = 3$. После применения softmax из формулы весов внимания, чему равно $\alpha_{i3}$ (вес третьей позиции)? (Округлите до 2 знаков после запятой.)

Объяснение: softmax(1,2,3) = (e^1, e^2, e^3) / (e^1+e^2+e^3) ≈ (2.72, 7.39, 20.09) / 30.19, поэтому α_{i3} ≈ 20.09/30.19 ≈ 0.67.

Используя функцию оценки Луонга на основе скалярного произведения $s^\top h$, при состоянии декодировщика $s = (1, 2, 3)$ и скрытом состоянии кодировщика $h = (4, 0, 1)$, чему равна сырая оценка выравнивания?

Объяснение: s·h = 1(4) + 2(0) + 3(1) = 4 + 0 + 3 = 7.

Используя «общую» билинейную функцию оценки Луонга $s^\top W h$, при $s = (1, 1)$, $h = (2, 1)$ и $W = \begin{pmatrix} 2 & 0 \\ 0 & 3 \end{pmatrix}$, вычислите оценку.

Объяснение: Wh = (2(2)+0(1), 0(2)+3(1)) = (4, 3). Тогда s·(Wh) = 1(4) + 1(3) = 7.