10.6. Архитектура кодировщик–декодировщик¶
В общем случае для задач преобразования последовательностей в последовательности, таких как машинный перевод (Section 10.5), входные и выходные данные имеют переменную длину и не выровнены. Стандартный подход к обработке таких данных заключается в использовании архитектуры кодировщик–декодировщик (Fig. 10.6.1), состоящей из двух основных компонентов: кодировщика, который принимает на вход последовательность переменной длины, и декодировщика, действующего как условная языковая модель. Декодировщик получает закодированный вход и левый контекст целевой последовательности, предсказывая следующий токен в целевой последовательности.
Fig. 10.6.1 Архитектура кодировщик–декодировщик.¶
Рассмотрим машинный перевод с английского на французский в качестве примера. Для входной последовательности на английском языке: «They», «are», «watching», «.» архитектура кодировщик–декодировщик сначала кодирует входную последовательность переменной длины в состояние, а затем декодирует это состояние, генерируя выходную переведенную последовательность токен за токеном: «Ils», «regardent», «.». Поскольку архитектура кодировщик–декодировщик лежит в основе различных моделей преобразования последовательности в последовательность, рассматриваемых в последующих разделах, в данном разделе мы преобразуем эту архитектуру в интерфейс, который будет реализован позже.
from torch import nn
from d2l import torch as d2l
10.6.1. Кодировщик¶
В интерфейсе кодировщика мы лишь указываем, что кодировщик принимает на
вход последовательности переменной длины X. Реализацию предоставит
любая модель, наследующая этот базовый класс Encoder.
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
10.6.2. Декодировщик¶
В следующем интерфейсе декодировщика мы добавляем дополнительный метод
init_state для преобразования вывода кодировщика
(enc_all_outputs) в закодированное состояние. Обратите внимание, что
этот шаг может требовать дополнительных входных данных, таких как
допустимая длина ввода, что было объяснено в
Section 10.5. Для генерации последовательности
переменной длины по одному токену за раз декодировщик на каждом
временном шаге преобразует входные данные (например, сгенерированный
токен на предыдущем временном шаге) и закодированное состояние в
выходной токен текущего временного шага.
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
10.6.3. Объединение кодировщика и декодировщика¶
В прямом распространении выход кодировщика используется для получения закодированного состояния, которое затем декодировщик использует в качестве одного из своих входных данных.
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]
В следующем разделе мы рассмотрим, как применить рекуррентные нейронные сети для построения моделей «последовательность-в-последовательность» на основе этой архитектуры кодировщика и декодировщика.
10.6.4. Итоги¶
Архитектуры «кодировщик-декодировщик» могут обрабатывать входные и выходные данные, состоящие из последовательностей переменной длины, и поэтому подходят для задач преобразования одной последовательности в другую, таких как машинный перевод. Кодировщик принимает на вход последовательность переменной длины и преобразует её в состояние фиксированной формы. Декодировщик отображает закодированное состояние фиксированной формы в последовательность переменной длины.
10.6.5. Упражнения¶
Предположим, что мы используем нейронные сети для реализации архитектуры кодировщик–декодировщик. Должны ли кодировщик и декодировщик представлять собой нейронные сети одного типа?
Помимо машинного перевода, можете ли вы привести другой пример применения архитектуры кодировщик–декодировщик?