Трансформеры (Transformers)¶
Введение¶
Трансформеры - это архитектура нейронных сетей, основанная на механизме внимания (attention mechanism), которая произвела революцию в обработке естественного языка и других областях.
Почему Transformers?¶
Ограничения RNN/LSTM¶
- Последовательная обработка (медленно)
- Проблемы с длинными зависимостями
- Сложность параллелизации
Преимущества Transformers¶
- Полная параллелизация
- Прямые связи между любыми позициями
- Масштабируемость
Архитектура Transformer¶
Encoder-Decoder структура¶
Вход → [Encoder] → Контекст → [Decoder] → Выход
Encoder¶
Состоит из N идентичных слоев: - Multi-Head Attention - Feed-Forward Network - Layer Normalization - Residual Connections
Decoder¶
Также N слоев плюс: - Masked Multi-Head Attention - Encoder-Decoder Attention
Self-Attention¶
Механизм внимания¶
Attention(Q, K, V) = softmax(QK^T / √d_k) · V
где: - Q (Query) - запрос - K (Key) - ключ - V (Value) - значение - d_k - размерность ключа
Scaled Dot-Product Attention¶
def scaled_dot_product_attention(Q, K, V):
d_k = K.shape[-1]
scores = np.matmul(Q, K.transpose(0, 2, 1))
scores /= np.sqrt(d_k)
weights = softmax(scores)
output = np.matmul(weights, V)
return output, weights
Multi-Head Attention¶
Параллельное применение нескольких heads:
class MultiHeadAttention:
def __init__(self, d_model, num_heads):
self.num_heads = num_heads
self.d_model = d_model
self.d_k = d_model // num_heads
self.W_q = nn.Linear(d_model, d_model)
self.W_k = nn.Linear(d_model, d_model)
self.W_v = nn.Linear(d_model, d_model)
self.W_o = nn.Linear(d_model, d_model)
def forward(self, Q, K, V, mask=None):
batch_size = Q.shape[0]
# Linear projections
q = self.W_q(Q).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
k = self.W_k(K).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
v = self.W_v(V).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
# Attention
scores = torch.matmul(q, k.transpose(-2, -1)) / np.sqrt(self.d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
weights = F.softmax(scores, dim=-1)
output = torch.matmul(weights, v)
# Concatenate heads
output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
return self.W_o(output)
Positional Encoding¶
Добавляет информацию о позиции:
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
def positional_encoding(max_len, d_model):
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len).unsqueeze(1).float()
div_term = torch.exp(torch.arange(0, d_model, 2).float() *
(-np.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
return pe.unsqueeze(0)
Feed-Forward Network¶
Позиционно-поэлементный полносвязный слой:
FFN(x) = max(0, xW_1 + b_1)W_2 + b_2
class PositionwiseFeedForward(nn.Module):
def __init__(self, d_model, d_ff, dropout=0.1):
super().__init__()
self.linear1 = nn.Linear(d_model, d_ff)
self.linear2 = nn.Linear(d_ff, d_model)
self.dropout = nn.Dropout(dropout)
self.activation = nn.ReLU()
def forward(self, x):
return self.linear2(self.dropout(self.activation(self.linear1(x))))
Полный Transformer¶
class Transformer(nn.Module):
def __init__(self, src_vocab, tgt_vocab, d_model=512, num_heads=8,
num_layers=6, d_ff=2048, max_len=5000, dropout=0.1):
super().__init__()
self.embedding_src = nn.Embedding(src_vocab, d_model)
self.embedding_tgt = nn.Embedding(tgt_vocab, d_model)
self.pe = positional_encoding(max_len, d_model)
self.encoder_layers = nn.ModuleList([
EncoderLayer(d_model, num_heads, d_ff, dropout)
for _ in range(num_layers)
])
self.decoder_layers = nn.ModuleList([
DecoderLayer(d_model, num_heads, d_ff, dropout)
for _ in range(num_layers)
])
self.fc_out = nn.Linear(d_model, tgt_vocab)
self.dropout = nn.Dropout(dropout)
def forward(self, src, tgt, src_mask, tgt_mask):
src_embedded = self.dropout(self.embedding_src(src) + self.pe[:, :src.size(1)])
tgt_embedded = self.dropout(self.embedding_tgt(tgt) + self.pe[:, :tgt.size(1)])
enc_output = src_embedded
for layer in self.encoder_layers:
enc_output = layer(enc_output, src_mask)
dec_output = tgt_embedded
for layer in self.decoder_layers:
dec_output = layer(dec_output, enc_output, tgt_mask, src_mask)
return self.fc_out(dec_output)
Варианты архитектуры¶
BERT (Bidirectional Encoder Representations)¶
- Только encoder
- Bidirectional attention
- Предобучение: MLM + NSP
GPT (Generative Pre-trained Transformer)¶
- Только decoder
- Causal (masked) attention
- Авторегрессионная генерация
T5 (Text-to-Text Transfer Transformer)¶
- Encoder-decoder
- Все задачи как text-to-text
Vision Transformer (ViT)¶
- Применение к изображениям
- Patch embeddings вместо токенов
Заключение¶
Transformers стали доминирующей архитектурой в NLP и активно применяются в компьютерном зрении, аудио и других областях.