В чем разница между энкодером и декодером в архитектурах нейронных сетей?

«В чем разница между энкодером и декодером в архитектурах нейронных сетей?» — вопрос из категории Нейронные сети и Deep Learning, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Энкодер и декодер — это два симметричных компонента в архитектурах нейронных сетей, которые выполняют противоположные задачи.

Энкодер (Encoder)

  • Задача: Сжать или представить входные данные (изображение, текст, звук) в виде компактного, информативного вектора фиксированной размерности, часто называемого скрытым представлением (latent representation) или контекстом (context).
  • Что делает: Извлекает наиболее значимые признаки (features) из входных данных, отбрасывая несущественную информацию (шум).
  • Аналогия: Создание подробного плана (чертежа) здания.

Декодер (Decoder)

  • Задача: Восстановить или сгенерировать данные на основе скрытого представления, полученного от энкодера.
  • Что делает: "Разворачивает" сжатое представление обратно в данные, похожие на исходные, или в данные целевого формата.
  • Аналогия: Построение здания по его чертежу.

Примеры архитектур

1. Автоэнкодер (Autoencoder) — для сжатия и обучения представлений:

import torch.nn as nn

# Энкодер: 784 пикселя -> 64 -> 32 -> 16 (latent vector)
class Encoder(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 16) # latent_dim = 16
    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        latent = self.fc3(x) # Сжатое представление
        return latent

# Декодер: 16 (latent vector) -> 32 -> 64 -> 784 пикселя
class Decoder(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(16, 32)
        self.fc2 = nn.Linear(32, 64)
        self.fc3 = nn.Linear(64, 784)
    def forward(self, z):
        z = torch.relu(self.fc1(z))
        z = torch.relu(self.fc2(z))
        reconstruction = torch.sigmoid(self.fc3(z)) # Восстановленное изображение
        return reconstruction

2. Seq2Seq (например, для машинного перевода):

  • Энкодер (RNN/LSTM/Transformer): Принимает исходное предложение (например, на английском) и кодирует его в контекстный вектор, который encapsulates смысл всего предложения.
  • Декодер (RNN/LSTM/Transformer): Принимает этот контекстный вектор и генерирует выходную последовательность (например, на французском) по одному токену за раз.

3. Трансформер (Transformer) в чистом виде: В архитектуре типа "энкодер-декодер" (используется в BART, T5):

  • Стек энкодеров: Обрабатывает входную последовательность, создавая обогащенные контекстом представления для каждого входного токена.
  • Стек декодеров: Использует выход энкодера и собственный предыдущий вывод для генерации выходной последовательности авторегрессионно, с механизмом внимания к энкодеру.

Итог: Энкодер анализирует и кодирует информацию, декодер синтезирует и генерирует данные на основе этого кода. Их совместная работа лежит в основе задач перевода, суммирования текста, генерации изображений (VAE), исправления ошибок и многих других.