Эпоха 3 · Взрыв deep learning · 2014

21 Seq2Seq

Sequence to Sequence Learning with Neural Networks · Sutskever, Vinyals & Le · NeurIPS
🟧 оригинал выборочно~35–45 миноригинал ↗
Суть за 20 секунд. Два LSTM: энкодер сжимает вход в один вектор, декодер из него генерирует выход слово за словом. Машинный перевод end-to-end без ручного выравнивания. Закрепил парадигму encoder-decoder — но фиксированный вектор стал узким местом, которое чинит attention.

Контекст

Задачи «последовательность → последовательность» (перевод) требовали сложных пайплайнов с ручным выравниванием. Суцкевер, Виньялс, Ле делают это одной нейросетью.

Идея и механизм

Энкодер (LSTM) читает вход и сжимает его в один вектор фиксированной длины — финальное скрытое состояние. Декодер (LSTM) из этого вектора генерирует выход слово за словом: каждое следующее слово — на основе вектора и уже сгенерированного. Обучается на парах (вход, выход) предсказанием следующего токена. Трюк: разворот порядка слов источника заметно поднял качество.

теория вероятностей Авторегрессионная факторизация и узкое место

Модель раскладывает вероятность всей выходной последовательности в произведение пошаговых (цепное правило для вероятностей):

P(y1..T | x) = ∏t=1T P(yt | y1..t−1, c)

где c — вектор-контекст (финальное состояние энкодера). Декодер на каждом шаге берёт c и уже сгенерированное и выдаёт распределение следующего слова.

Узкое место. Весь вход x сжат в один вектор фиксированного размера c. Чем длиннее предложение, тем больше информации надо втиснуть в ту же размерность → потери растут с длиной. Разворот источника помогает оптимизации: первые слова источника и первые слова перевода оказываются близко в графе зависимостей, и градиент короче — отсюда заметный прирост BLEU. Но фундаментальный bottleneck остаётся, и его снимет attention (#22).

PyTorch Энкодер-декодер на LSTM (схема)
def seq2seq(src, tgt, enc, dec, embed):
    _, (h, c) = enc(embed(src))      # сжать вход в контекст (h, c)
    out, _ = dec(embed(tgt), (h, c)) # декодер генерирует из контекста
    return out                       # логиты по словарю на каждом шаге
LSTM LSTM LSTM энкодер c контекст-вектор LSTM LSTM LSTM декодер слова перевода
Энкодер сжимает вход в один вектор c; декодер из него генерирует перевод. Всё, что узнал энкодер, должно поместиться в c — отсюда bottleneck.
Аналогия. Переводчик-синхронист, которому запретили делать пометки: он должен дослушать всю фразу, удержать её целиком в голове (вектор c), и только потом начать переводить. На короткой фразе — нормально, на длинной — что-то забудется. Attention (#22) — это как разрешить ему подглядывать в исходный текст по ходу перевода.

Почему это важно

Закрепил парадигму encoder-decoder, на которой выросли перевод, суммаризация, диалог и позже мультимодальные модели. А его слабое место — фиксированный вектор — напрямую породило следующий шаг, attention, и далее Transformer.

Связи

← опирается на11. LSTM

Оба «кирпича» seq2seq — это LSTM. Способность держать контекст на много шагов (которую дал LSTM) — необходимое условие, чтобы один вектор хоть как-то представлял целое предложение.

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

↔ заменяется32. Transformer

Transformer сохраняет идею encoder-decoder, но выкидывает рекуррентность: вместо последовательного сжатия — параллельное self-attention. Парадигма та же, механизм радикально другой.

Вопросы пытливого ума

Почему разворот источника помогает, а разворот цели — нет?

Разворот источника укорачивает путь между началом входа и началом выхода: первое слово перевода зависит от первых слов оригинала, и теперь они рядом в развёрнутой последовательности → градиент короче, оптимизация легче. Цель генерируется слева направо в любом случае, её разворачивать смысла нет. Это чистый трюк оптимизации, а не лингвистики.

Если узкое место известно, зачем вообще изучать seq2seq, а не сразу attention?

Потому что attention — это надстройка над seq2seq, а не замена: encoder-decoder каркас, авторегрессионная генерация и обучение на парах остались. Понять bottleneck — значит понять, зачем нужно внимание. Без seq2seq attention выглядит произвольным трюком, а не решением конкретной проблемы.

Как декодер вообще «знает», когда остановиться?

В словарь добавляют специальный токен конца последовательности (<EOS>); декодер обучается генерировать его, когда перевод закончен, и генерация останавливается. На инференсе обычно используют beam search — держат несколько лучших гипотез, а не жадно берут самое вероятное слово на каждом шаге.

Что читать в оригинале

Читать ключевое — encoder-decoder каркас и трюк с разворотом; это фундамент, на котором дальше строятся attention и Transformer.