← Назад к вопросам
В чем разница между энкодером и декодером?
1.7 Middle🔥 81 комментариев
#Глубокое обучение
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между энкодером и декодером
Энкодер и декодер - это два компонента архитектуры нейронных сетей, которые работают вместе в моделях типа "Encoder-Decoder" и Transformer.
Энкодер (Encoder)
Назначение: обработка входных данных и создание представления
- Берет исходные данные (текст, изображение, звук)
- Извлекает признаки и семантику
- Создает плотное представление (embedding/latent space)
- Направлен внутрь (от входа к внутреннему представлению)
import torch
import torch.nn as nn
class SimpleEncoder(nn.Module):
def __init__(self, input_size, hidden_size, latent_size):
super().__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, latent_size)
def forward(self, x):
# x shape: (batch_size, input_size)
h = torch.relu(self.fc1(x))
z = self.fc2(h) # latent representation
return z
# Пример: энкодер берет текст, выдает эмбеддинг
encoder = SimpleEncoder(input_size=768, hidden_size=256, latent_size=128)
text_embedding = encoder(input_text) # (batch_size, 128)
Декодер (Decoder)
Назначение: восстановление или генерация данных из представления
- Берет плотное представление (embedding)
- Восстанавливает исходный формат
- Генерирует выходные данные
- Направлен наружу (от внутреннего представления к выходу)
class SimpleDecoder(nn.Module):
def __init__(self, latent_size, hidden_size, output_size):
super().__init__()
self.fc1 = nn.Linear(latent_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, z):
# z shape: (batch_size, latent_size)
h = torch.relu(self.fc1(z))
x_reconstructed = self.fc2(h) # восстановленные данные
return x_reconstructed
# Пример: декодер берет эмбеддинг, выдает текст
decoder = SimpleDecoder(latent_size=128, hidden_size=256, output_size=768)
reconstructed_text = decoder(text_embedding) # (batch_size, 768)
Полная архитектура Autoencoder
class Autoencoder(nn.Module):
def __init__(self):
super().__init__()
self.encoder = SimpleEncoder(768, 256, 128)
self.decoder = SimpleDecoder(128, 256, 768)
def forward(self, x):
z = self.encoder(x) # Энкодер
x_reconstructed = self.decoder(z) # Декодер
return x_reconstructed, z
# Использование
autoencoder = Autoencoder()
output, latent = autoencoder(input_data)
# Loss function - насколько хорошо восстановили данные
loss = nn.MSELoss()(output, input_data)
Architektura Encoder-Decoder (Seq2Seq)
Энкодер и декодер разделены и могут быть разными:
Вход: "Hello" Выход: "Привет"
|
v
[ЭНКОДЕР] -> скрытый вектор состояния -> [ДЕКОДЕР]
|
v
context
^
|
используется декодером
import torch
import torch.nn as nn
class Seq2SeqEncoder(nn.Module):
def __init__(self, vocab_size, embedding_dim, hidden_dim):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.gru = nn.GRU(embedding_dim, hidden_dim, batch_first=True)
def forward(self, input_ids):
# input_ids: (batch_size, seq_len)
embedded = self.embedding(input_ids) # (batch_size, seq_len, embedding_dim)
_, hidden = self.gru(embedded) # hidden: (1, batch_size, hidden_dim)
return hidden
class Seq2SeqDecoder(nn.Module):
def __init__(self, vocab_size, embedding_dim, hidden_dim):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.gru = nn.GRU(embedding_dim, hidden_dim, batch_first=True)
self.fc = nn.Linear(hidden_dim, vocab_size)
def forward(self, input_ids, hidden):
# input_ids: (batch_size, 1)
# hidden: (1, batch_size, hidden_dim) из энкодера
embedded = self.embedding(input_ids) # (batch_size, 1, embedding_dim)
output, hidden = self.gru(embedded, hidden)
logits = self.fc(output) # (batch_size, 1, vocab_size)
return logits, hidden
# Использование
encoder = Seq2SeqEncoder(vocab_size=5000, embedding_dim=256, hidden_dim=512)
decoder = Seq2SeqDecoder(vocab_size=5000, embedding_dim=256, hidden_dim=512)
input_ids = torch.tensor([[1, 2, 3, 4]]) # "Hello"
encoder_hidden = encoder(input_ids) # Context от энкодера
# Декодер генерирует ответ
output_logits, _ = decoder(torch.tensor([[1]]), encoder_hidden)
Encoder-Decoder в Transformers
BERT - только энкодер:
from transformers import AutoTokenizer, AutoModel
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased") # Только encoder
inputs = tokenizer("Hello world", return_tensors="pt")
outputs = model(**inputs)
embeddings = outputs.last_hidden_state # (1, seq_len, 768)
T5 - энкодер + декодер:
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
tokenizer = AutoTokenizer.from_pretrained("t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("t5-base") # Encoder + Decoder
inputs = tokenizer("translate English to French: Hello", return_tensors="pt")
outputs = model(**inputs)
# Encoder обработает "Hello"
# Decoder сгенерирует перевод
Практический пример: Автоматическое сжатие текста
import torch
import torch.nn as nn
class TextAutoencoder(nn.Module):
def __init__(self, vocab_size, embedding_dim, latent_dim):
super().__init__()
# Энкодер: текст -> сжатое представление
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.encoder_lstm = nn.LSTM(embedding_dim, 256, batch_first=True)
self.fc_latent = nn.Linear(256, latent_dim)
# Декодер: сжатое представление -> текст
self.fc_decode = nn.Linear(latent_dim, 256)
self.decoder_lstm = nn.LSTM(256, 256, batch_first=True)
self.fc_out = nn.Linear(256, vocab_size)
def encode(self, input_ids):
# Энкодер
x = self.embedding(input_ids)
_, (h, c) = self.encoder_lstm(x)
latent = self.fc_latent(h[0])
return latent
def decode(self, latent, seq_len):
# Декодер
x = self.fc_decode(latent).unsqueeze(1)
output, _ = self.decoder_lstm(x.expand(-1, seq_len, -1))
logits = self.fc_out(output)
return logits
def forward(self, input_ids):
latent = self.encode(input_ids)
seq_len = input_ids.size(1)
output = self.decode(latent, seq_len)
return output, latent
# Использование
model = TextAutoencoder(vocab_size=5000, embedding_dim=128, latent_dim=64)
input_text = torch.randint(0, 5000, (2, 50)) # batch_size=2, seq_len=50
reconstructed, compressed = model(input_text)
print(f"Входные данные: {input_text.shape}")
print(f"Сжатое представление: {compressed.shape}") # Намного меньше!
print(f"Восстановленные данные: {reconstructed.shape}")
Таблица сравнения
| Аспект | Энкодер | Декодер |
|---|---|---|
| Направление | Вход → Внутренность | Внутренность → Выход |
| Задача | Извлечение признаков | Генерация/восстановление |
| Вход | Исходные данные | Представление (embedding) |
| Выход | Компактное представление | Данные в исходном формате |
| Пример | текст → вектор | вектор → текст |
Применение в разных задачах
1. Классификация (только энкодер)
embedding = encoder(text)
logits = classifier(embedding)
2. Перевод (энкодер + декодер)
latent = encoder(text_en)
text_ru = decoder(latent)
3. Автоматическое сжатие (энкодер + декодер)
compressed = encoder(image) # Малый размер
restored = decoder(compressed) # Восстановленное
4. Генерация (только декодер)
latent = random_vector()
generated = decoder(latent)
Вывод: Энкодер сжимает информацию, декодер её распаковывает. Вместе они создают мощные архитектуры для трансформации данных.