Объясните Attention как взвешенную сумму. Зачем нужна маска (padding mask) в энкодере?
Краткий тезис
Attention-механизм в энкодере Transformer вычисляет контекстное представление как взвешенную сумму значений (Value), где веса определяются схожестью между запросом (Query) и ключами (Key) с масштабированием. Padding mask — это бинарная маска, которая обнуляет веса внимания для токенов-заполнителей (PAD), предотвращая учёт пустых позиций при агрегации контекста. Без маски модель «внимала» бы «пустоте», искажая скрытые состояния.
2. Взвешенная сумма Value по весам от Query-Key
Результат внимания для одного запроса (q_i) можно записать как:
[ [text](/wiki/text){Attention}(q_i, K, V) = \sum_{j=1}^{m} \alpha_{ij} v_j,\quad \alpha_{ij} = \frac{\exp(q_i \cdot k_j / \sqrt{d_k})}{\sum_{l=1}^{m} \exp(q_i \cdot k_l / \sqrt{d_k})} ]
- (\alpha_{ij}) — вес, с которым значение (v_j) (соответствующее ключу (k_j)) входит в результирующее представление токена (i).
- Сумма весов (\sum_{j} \alpha_{ij} = 1) благодаря softmax.
Таким образом, каждое выходное скрытое состояние есть выпуклая комбинация всех значений (Value). Интуитивно: модель «решает», на какие части последовательности (ключи) нужно опереться, чтобы уточнить представление текущего токена (запроса). Это и есть «взвешенная сумма» — основная идея механизма внимания.
3. Padding mask: обнуляет attention на PAD токенах
В реальных NLP-задачах последовательности имеют разную длину. Для эффективной пакетной обработки (batching) короткие предложения дополняются специальным токеном <PAD> до длины самого длинного в батче.
Padding mask — это бинарная матрица (или тензор) той же формы, что и матрица внимания до softmax. Обычно:
- Для каждой пары (query, key) ставится 1, если key — реальный токен (не PAD), и 0 или (-\infty), если key — PAD.
- На практике маску часто передают как тензор с булевыми значениями:
Trueдля PAD-позиций.
Перед применением softmax к (QK^T) прибавляется маска, где PAD-позициям соответствует очень большое отрицательное число (например, -1e9):
[ \operatorname{Attention}(Q,K,V) = \operatorname{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + [text](/wiki/text){mask}\right) V ]
В результате softmax «обнуляет» вес для этих позиций (экспонента от (-\infty) даёт (0)). Формально:
- Если key — PAD, его вклад в мягкое выравнивание (alignment) становится нулевым.
- Агрегированное представление для любого query не содержит информации от пустых токенов.
Маска обычно имеет размер [batch_size, 1, 1, seq_len] (в многоголовом внимании) и расширяется для всех голов и позиций запросов.
4. Зачем: чтобы контекст не учитывал пустоту
Если не применять padding mask:
- Модель будет «учить» внимать токенам `<PAD>», которые не несут смысловой нагрузки. Это приведёт к размытию контекстных представлений, особенно для коротких предложений, где доля PAD-токенов велика.
- Градиенты «шумные» — модель будет пытаться приписать осмысленную информацию мусорным токенам, ухудшая обобщение.
- В задачах, где важна длина последовательности (например, машинный перевод), модель может «запомнить» фиктивную информацию, что вызовет ошибки на этапе инференса (когда PAD отсутствует).
Пример: Предложение «Я люблю NLP» (4 токена) в батче с предложением «Привет» (2 токена) будет дополнено до 4: [Привет, <PAD>, <PAD>, <PAD>]. Без маски токен «Привет» получит равные веса от всех трёх PAD, и его контекст будет испорчен. С маской веса PAD станут нулевыми, и контекст останется осмысленным.
Маска обязательна в энкодере, если батч содержит последовательности разной длины. В декодере дополнительно используется look-ahead mask (каузальная маска), но padding mask применяется в обоих модулях.
5. Пет-проект для закрепления
Задача: Реализовать простой энкодер Transformer с padding mask в PyTorch и проверить его работу на синтетических данных с разной длиной.
Инструменты:
- Python 3.10+
- PyTorch (≥1.9)
- Jupyter Notebook или скрипт
Шаги:
- Создайте датасет из двух предложений: "кошка сидит на окне" (5 токенов) и "дом" (1 токен). Словарь: {0: PAD, 1: кошка, 2: сидит, 3: на, 4: окне, 5: дом}.
- Преобразуйте в батч тензоров: [[1,2,3,4,0], [5,0,0,0,0]].
- Напишите слой Scaled Dot-Product Attention с поддержкой маски (
key_padding_maskилиattn_mask). - Реализуйте многоголовое внимание и Feed-Forward сеть.
- Сравните выходные векторы для токена "дом" (второй пример) с маской и без маски. Ожидайте, что без маски его представление будет зависеть от нулевых позиций, а с маской — только от самого себя (или других ненулевых, если добавить контекст через самовнимание).
- Визуализируйте (с помощью
[matplotlib](/wiki/Matplotlib)) матрицу внимания до и после маски — убедитесь, что веса на PAD обнулены.
Ожидаемый результат: При обучении даже на простой задаче (например, реконструкция входной последовательности) модель с маской достигнет более низкого loss и не будет пытаться предсказать PAD-токены на выходе.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 276 | Self-Attention и механизмы маскирования (padding & causal) |
Навигация
- Предыдущий: 931
- Следующий: 933
- Индекс: 00. Индекс разборов