? ? ? ?
?
? ? ? ?首先,我得回顧一下Transformer的基本結構,確保自己沒有記錯。Transformer由編碼器和解碼器組成,每個編碼器層包含多頭自注意力機制和前饋網絡,解碼器層則還有編碼器-解碼器注意力。
接下來,用戶需要的是手把手的代碼解讀,所以必須詳細,每一步都不能遺漏。可能需要從數據預處理開始,比如詞嵌入、位置編碼。然后逐步構建各個組件:自注意力、多頭注意力、編碼器層、解碼器層,最后整合成完整的Transformer模型。
要注意用戶提到的系統級指令,特別是LaTeX格式的要求。所有數學公式都要用$...$或者$$...$$,比如自注意力的計算公式$Attention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})V$,這里要檢查是否正確使用括號和符號。
另外,用戶要求結構清晰,分步驟講解。可能需要分成幾個部分:嵌入層、位置編碼、多頭注意力、前饋網絡、編碼器、解碼器,然后是整體模型和訓練過程。每個部分都要解釋代碼的邏輯,比如在PyTorch中如何繼承nn.Module,如何初始化參數,前向傳播的實現。
需要確保代碼示例正確,比如在實現多頭注意力時,是否正確地分割了張量,是否計算了注意力分數,并應用了mask。可能還要解釋為什么使用縮放點積注意力,以及如何實現殘差連接和層歸一化。
還要考慮用戶可能遇到的常見問題,比如維度不匹配,如何處理mask,訓練時的損失函數選擇,優化器的設置等。可能需要給出一個簡單的示例,說明如何使用構建好的Transformer模型進行訓練和推理。
最后,檢查是否符合中文回答的要求,避免使用專業術語時直接使用英文而不加解釋。比如,提到“embedding”時要翻譯為“嵌入”或者“詞嵌入”。同時,確保LaTeX語法正確,沒有遺漏$符號或者錯誤使用括號。
以下是用PyTorch實現Transformer模型的詳細分步指南,包含關鍵代碼解讀:
一、Transformer核心結構
Transformer由編碼器(Encoder)和解碼器(Decoder)組成,核心公式:
$$ \text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$
二、實現步驟分解
1. 導入基礎模塊
python
import torch
import torch.nn as nn
import torch.nn.functional as F
?2. 位置編碼(Positional Encoding)
解決序列順序信息的關鍵:
$$ PE_{(pos,2i)} = \sin(pos/10000^{2i/d_{model}}) $$
$$ PE_{(pos,2i+1)} = \cos(pos/10000^{2i/d_{model}}) $$
?
代碼實現:
python
class PositionalEncoding(nn.Module):
? ? def __init__(self, d_model, max_len=5000):
? ? ? ? super().__init__()
? ? ? ? pe = torch.zeros(max_len, d_model)
? ? ? ? position = torch.arange(0, max_len).unsqueeze(1)
? ? ? ? div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0)/d_model))
? ? ? ? pe[:, 0::2] = torch.sin(position * div_term)
? ? ? ? pe[:, 1::2] = torch.cos(position * div_term)
? ? ? ? self.register_buffer('pe', pe)
? ? ? ??
? ? def forward(self, x):
? ? ? ? return x + self.pe[:x.size(1)]
3. 多頭注意力機制(Multi-Head Attention)
關鍵步驟:
1. 線性投影分割頭
2. 計算縮放點積注意力
3. 合并多頭輸出
?
代碼實現:
python
class MultiHeadAttention(nn.Module):
? ? def __init__(self, d_model, num_heads):
? ? ? ? super().__init__()
? ? ? ? self.d_model = d_model
? ? ? ? self.num_heads = num_heads
? ? ? ? self.d_k = d_model // num_heads
? ? ? ??
? ? ? ? self.Wq = nn.Linear(d_model, d_model)
? ? ? ? self.Wk = nn.Linear(d_model, d_model)
? ? ? ? self.Wv = nn.Linear(d_model, d_model)
? ? ? ? self.out = nn.Linear(d_model, d_model)
? ? ? ??
? ? def forward(self, q, k, v, mask=None):
? ? ? ? batch_size = q.size(0)
? ? ? ??
? ? ? ? # 線性投影并分頭 [B, L, D] -> [B, L, H, D_k]
? ? ? ? q = self.Wq(q).view(batch_size, -1, self.num_heads, self.d_k)
? ? ? ? k = self.Wk(k).view(batch_size, -1, self.num_heads, self.d_k)
? ? ? ? v = self.Wv(v).view(batch_size, -1, self.num_heads, self.d_k)
? ? ? ??
? ? ? ? # 計算注意力得分
? ? ? ? scores = torch.matmul(q.transpose(1,2), k.transpose(1,2).transpose(2,3))?
? ? ? ? scores = scores / math.sqrt(self.d_k)
? ? ? ??
? ? ? ? if mask is not None:
? ? ? ? ? ? scores = scores.masked_fill(mask == 0, -1e9)
? ? ? ??
? ? ? ? # Softmax歸一化
? ? ? ? attn = F.softmax(scores, dim=-1)
? ? ? ??
? ? ? ? # 上下文向量計算
? ? ? ? context = torch.matmul(attn, v.transpose(1,2))
? ? ? ? context = context.transpose(1,2).contiguous().view(batch_size, -1, self.d_model)
? ? ? ??
? ? ? ? return self.out(context)
4. 前饋網絡(Position-wise FFN)
$$ \text{FFN}(x) = \text{ReLU}(xW_1 + b_1)W_2 + b_2 $$
?
代碼實現:
```python
class FeedForward(nn.Module):
? ? def __init__(self, d_model, d_ff=2048):
? ? ? ? super().__init__()
? ? ? ? self.linear1 = nn.Linear(d_model, d_ff)
? ? ? ? self.linear2 = nn.Linear(d_ff, d_model)
? ? ? ??
? ? def forward(self, x):
? ? ? ? return self.linear2(F.relu(self.linear1(x)))
?5. 編碼器層完整實現
python
class EncoderLayer(nn.Module):
? ? def __init__(self, d_model, num_heads, dropout=0.1):
? ? ? ? super().__init__()
? ? ? ? self.self_attn = MultiHeadAttention(d_model, num_heads)
? ? ? ? self.ffn = FeedForward(d_model)
? ? ? ? self.norm1 = nn.LayerNorm(d_model)
? ? ? ? self.norm2 = nn.LayerNorm(d_model)
? ? ? ? self.dropout = nn.Dropout(dropout)
? ? ? ??
? ? def forward(self, x, mask):
? ? ? ? # 殘差連接+層歸一化
? ? ? ? attn_output = self.self_attn(x, x, x, mask)
? ? ? ? x = self.norm1(x + self.dropout(attn_output))
? ? ? ??
? ? ? ? ffn_output = self.ffn(x)
? ? ? ? x = self.norm2(x + self.dropout(ffn_output))
? ? ? ? return x
?6. 解碼器層實現(含Encoder-Decoder Attention)
```python
class DecoderLayer(nn.Module):
? ? def __init__(self, d_model, num_heads, dropout=0.1):
? ? ? ? super().__init__()
? ? ? ? self.self_attn = MultiHeadAttention(d_model, num_heads)
? ? ? ? self.cross_attn = MultiHeadAttention(d_model, num_heads)
? ? ? ? self.ffn = FeedForward(d_model)
? ? ? ? self.norm1 = nn.LayerNorm(d_model)
? ? ? ? self.norm2 = nn.LayerNorm(d_model)
? ? ? ? self.norm3 = nn.LayerNorm(d_model)
? ? ? ? self.dropout = nn.Dropout(dropout)
? ? ? ??
? ? def forward(self, x, encoder_output, src_mask, tgt_mask):
? ? ? ? # 自注意力
? ? ? ? attn_output = self.self_attn(x, x, x, tgt_mask)
? ? ? ? x = self.norm1(x + self.dropout(attn_output))
? ? ? ??
? ? ? ? # 編碼器-解碼器注意力
? ? ? ? attn_output = self.cross_attn(x, encoder_output, encoder_output, src_mask)
? ? ? ? x = self.norm2(x + self.dropout(attn_output))
? ? ? ??
? ? ? ? # 前饋網絡
? ? ? ? ffn_output = self.ffn(x)
? ? ? ? x = self.norm3(x + self.dropout(ffn_output))
? ? ? ? return x
?三、完整Transformer組裝
```python
class Transformer(nn.Module):
? ? def __init__(self, src_vocab_size, tgt_vocab_size, d_model=512, num_heads=8,?
? ? ? ? ? ? ? ? num_layers=6, dropout=0.1):
? ? ? ? super().__init__()
? ? ? ? self.encoder_embed = nn.Embedding(src_vocab_size, d_model)
? ? ? ? self.decoder_embed = nn.Embedding(tgt_vocab_size, d_model)
? ? ? ? self.pos_encoding = PositionalEncoding(d_model)
? ? ? ??
? ? ? ? self.encoder_layers = nn.ModuleList(
? ? ? ? ? ? [EncoderLayer(d_model, num_heads, dropout) for _ in range(num_layers)])
? ? ? ? self.decoder_layers = nn.ModuleList(
? ? ? ? ? ? [DecoderLayer(d_model, num_heads, dropout) for _ in range(num_layers)])
? ? ? ??
? ? ? ? self.final_out = nn.Linear(d_model, tgt_vocab_size)
? ??
? ? def forward(self, src, tgt, src_mask, tgt_mask):
? ? ? ? # 編碼器
? ? ? ? src_emb = self.pos_encoding(self.encoder_embed(src))
? ? ? ? for layer in self.encoder_layers:
? ? ? ? ? ? src_emb = layer(src_emb, src_mask)
? ? ? ??
? ? ? ? # 解碼器
? ? ? ? tgt_emb = self.pos_encoding(self.decoder_embed(tgt))
? ? ? ? for layer in self.decoder_layers:
? ? ? ? ? ? tgt_emb = layer(tgt_emb, src_emb, src_mask, tgt_mask)
? ? ? ? ? ??
? ? ? ? return self.final_out(tgt_emb)
```
?
四、訓練關鍵點
1. **Mask生成**:實現padding mask和look-ahead mask
2. **學習率調度**:使用warmup策略
3. **標簽平滑**:提升模型泛化能力
4. **批處理**:利用GPU并行計算
?
示例訓練循環:
```python
model = Transformer(src_vocab_size=10000, tgt_vocab_size=8000)
criterion = nn.CrossEntropyLoss(ignore_index=0)
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
?
for epoch in range(100):
? ? for batch in dataloader:
? ? ? ? src, tgt_in, tgt_out = batch
? ? ? ? src_mask = (src != 0).unsqueeze(1)
? ? ? ? tgt_mask = (tgt_in != 0).unsqueeze(1)
? ? ? ??
? ? ? ? outputs = model(src, tgt_in, src_mask, tgt_mask)
? ? ? ? loss = criterion(outputs.view(-1, outputs.size(-1)), tgt_out.view(-1))
? ? ? ??
? ? ? ? optimizer.zero_grad()
? ? ? ? loss.backward()
? ? ? ? optimizer.step()
```
?
五、常見問題解決
1. **維度不匹配**:檢查各層輸入輸出維度是否一致
2. **梯度消失**:合理使用殘差連接和層歸一化
3. **過擬合**:增加dropout率或使用權重衰減
4. **訓練效率**:采用混合精度訓練和梯度累積
?
建議通過可視化注意力權重來理解模型的決策過程。完整實現約500行代碼,建議從簡單任務(如數字加法)開始驗證模型有效性。