.. _sec_encoder-decoder: Архитектура кодировщик–декодировщик =================================== В общем случае для задач преобразования последовательностей в последовательности, таких как машинный перевод (:numref:`sec_machine_translation`), входные и выходные данные имеют переменную длину и не выровнены. Стандартный подход к обработке таких данных заключается в использовании архитектуры *кодировщик–декодировщик* (:numref:`fig_encoder_decoder`), состоящей из двух основных компонентов: *кодировщика*, который принимает на вход последовательность переменной длины, и *декодировщика*, действующего как условная языковая модель. Декодировщик получает закодированный вход и левый контекст целевой последовательности, предсказывая следующий токен в целевой последовательности. .. _fig_encoder_decoder: .. figure:: ../img/encoder-decoder.svg Архитектура кодировщик–декодировщик. Рассмотрим машинный перевод с английского на французский в качестве примера. Для входной последовательности на английском языке: «They», «are», «watching», «.» архитектура кодировщик–декодировщик сначала кодирует входную последовательность переменной длины в состояние, а затем декодирует это состояние, генерируя выходную переведенную последовательность токен за токеном: «Ils», «regardent», «.». Поскольку архитектура кодировщик–декодировщик лежит в основе различных моделей преобразования последовательности в последовательность, рассматриваемых в последующих разделах, в данном разделе мы преобразуем эту архитектуру в интерфейс, который будет реализован позже. .. raw:: latex \diilbookstyleinputcell .. code:: python from torch import nn from d2l import torch as d2l Кодировщик ---------- В интерфейсе кодировщика мы лишь указываем, что кодировщик принимает на вход последовательности переменной длины ``X``. Реализацию предоставит любая модель, наследующая этот базовый класс ``Encoder``. .. raw:: latex \diilbookstyleinputcell .. code:: python class Encoder(nn.Module): #@save """The base encoder interface for the encoder--decoder architecture.""" def __init__(self): super().__init__() # Later there can be additional arguments (e.g., length excluding padding) def forward(self, X, *args): raise NotImplementedError Декодировщик ------------ В следующем интерфейсе декодировщика мы добавляем дополнительный метод ``init_state`` для преобразования вывода кодировщика (``enc_all_outputs``) в закодированное состояние. Обратите внимание, что этот шаг может требовать дополнительных входных данных, таких как допустимая длина ввода, что было объяснено в :numref:`sec_machine_translation`. Для генерации последовательности переменной длины по одному токену за раз декодировщик на каждом временном шаге преобразует входные данные (например, сгенерированный токен на предыдущем временном шаге) и закодированное состояние в выходной токен текущего временного шага. .. raw:: latex \diilbookstyleinputcell .. code:: python class Decoder(nn.Module): #@save """The base decoder interface for the encoder--decoder architecture.""" def __init__(self): super().__init__() # Later there can be additional arguments (e.g., length excluding padding) def init_state(self, enc_all_outputs, *args): raise NotImplementedError def forward(self, X, state): raise NotImplementedError Объединение кодировщика и декодировщика --------------------------------------- В прямом распространении выход кодировщика используется для получения закодированного состояния, которое затем декодировщик использует в качестве одного из своих входных данных. .. raw:: latex \diilbookstyleinputcell .. code:: python class EncoderDecoder(d2l.Classifier): #@save """The base class for the encoder--decoder architecture.""" def __init__(self, encoder, decoder): super().__init__() self.encoder = encoder self.decoder = decoder def forward(self, enc_X, dec_X, *args): enc_all_outputs = self.encoder(enc_X, *args) dec_state = self.decoder.init_state(enc_all_outputs, *args) # Return decoder output only return self.decoder(dec_X, dec_state)[0] В следующем разделе мы рассмотрим, как применить рекуррентные нейронные сети для построения моделей «последовательность-в-последовательность» на основе этой архитектуры кодировщика и декодировщика. Итоги ----- Архитектуры «кодировщик-декодировщик» могут обрабатывать входные и выходные данные, состоящие из последовательностей переменной длины, и поэтому подходят для задач преобразования одной последовательности в другую, таких как машинный перевод. Кодировщик принимает на вход последовательность переменной длины и преобразует её в состояние фиксированной формы. Декодировщик отображает закодированное состояние фиксированной формы в последовательность переменной длины. Упражнения ---------- 1. Предположим, что мы используем нейронные сети для реализации архитектуры кодировщик–декодировщик. Должны ли кодировщик и декодировщик представлять собой нейронные сети одного типа? 2. Помимо машинного перевода, можете ли вы привести другой пример применения архитектуры кодировщик–декодировщик? `Обсуждения `__