机器翻译是序列到序列学习的经典任务。本课实现一个基于Transformer的翻译系统。
| 时代 | 方法 | 特点 |
|---|---|---|
| 1950s-1990s | 基于规则 | 人工编写翻译规则 |
| 1990s-2015 | 统计机器翻译(SMT) | 从数据中学习翻译概率 |
| 2014-2017 | 神经机器翻译(NMT-RNN) | 端到端Seq2Seq+注意力 |
| 2017-至今 | Transformer | 完全基于注意力 |
BLEU = BP × exp(Σₙ wₙ log pₙ)
pₙ:n-gram精确率
BP:简短惩罚 = min(1, e^(1-r/c))
import torch
import torch.nn as nn
import math
# 机器翻译实现
print("=== Transformer机器翻译 ===")
# 词表
src_vocab_size = 1000
tgt_vocab_size = 800
d_model = 128
nhead = 4
num_layers = 2
# 模拟数据
torch.manual_seed(42)
max_src_len = 15
max_tgt_len = 12
batch_size = 32
X_src = torch.randint(1, src_vocab_size, (batch_size, max_src_len))
X_tgt = torch.randint(1, tgt_vocab_size, (batch_size, max_tgt_len))
# Transformer模型
class TranslationModel(nn.Module):
def __init__(self):
super().__init__()
self.src_embed = nn.Embedding(src_vocab_size, d_model)
self.tgt_embed = nn.Embedding(tgt_vocab_size, d_model)
self.transformer = nn.Transformer(
d_model=d_model, nhead=nhead,
num_encoder_layers=num_layers,
num_decoder_layers=num_layers,
dim_feedforward=d_model*4,
dropout=0.1, batch_first=True
)
self.fc = nn.Linear(d_model, tgt_vocab_size)
def forward(self, src, tgt, tgt_mask=None):
src_emb = self.src_embed(src)
tgt_emb = self.tgt_embed(tgt)
out = self.transformer(src_emb, tgt_emb, tgt_mask=tgt_mask)
return self.fc(out)
model = TranslationModel()
params = sum(p.numel() for p in model.parameters())
print(f"模型参数量: {params:,}")
# 生成因果掩码
def generate_causal_mask(sz):
mask = torch.triu(torch.ones(sz, sz), diagonal=1).bool()
return mask
tgt_mask = generate_causal_mask(max_tgt_len)
# 训练
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
loss_fn = nn.CrossEntropyLoss(ignore_index=0)
for epoch in range(0, 51, 10):
optimizer.zero_grad()
out = model(X_src, X_tgt[:, :-1], tgt_mask=generate_causal_mask(max_tgt_len-1))
loss = loss_fn(out.reshape(-1, tgt_vocab_size), X_tgt[:, 1:].reshape(-1))
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print(f"Epoch {epoch}: loss={loss.item():.4f}")
# BLEU计算
def compute_bleu(reference, hypothesis, max_n=4):
"""简化BLEU计算"""
from collections import Counter
ref_len = len(reference)
hyp_len = len(hypothesis)
if hyp_len == 0:
return 0.0
# BP
bp = min(1.0, math.exp(1 - ref_len / hyp_len)) if hyp_len < ref_len else 1.0
# n-gram精度
precisions = []
for n in range(1, max_n + 1):
ref_ngrams = Counter([tuple(reference[i:i+n]) for i in range(len(reference)-n+1)])
hyp_ngrams = Counter([tuple(hypothesis[i:i+n]) for i in range(len(hypothesis)-n+1)])
clipped = sum(min(count, ref_ngrams[ng]) for ng, count in hyp_ngrams.items())
total = max(sum(hyp_ngrams.values()), 1)
precisions.append(clipped / total)
avg_precision = math.exp(sum(math.log(max(p, 1e-10)) for p in precisions) / max_n)
return bp * avg_precision
# BLEU示例
ref = [1, 2, 3, 4, 5]
hyp1 = [1, 2, 3, 4, 5] # 完全匹配
hyp2 = [1, 2, 3, 6, 7] # 部分匹配
hyp3 = [8, 9, 10, 11, 12] # 完全不匹配
print(f"\nBLEU示例:")
print(f"完全匹配: BLEU={compute_bleu(ref, hyp1):.4f}")
print(f"部分匹配: BLEU={compute_bleu(ref, hyp2):.4f}")
print(f"完全不匹配: BLEU={compute_bleu(ref, hyp3):.4f}")
本课的核心知识点构成了实战项目学习的重要一环。让我们从更高维度审视这些知识之间的关系:
⚠️ 初学者常犯的错误:
💡 最佳实践:
深度学习是一个整体——每一课的知识都不是孤立的:
💡 继续深入的学习路径:
在Multi30k数据集上训练德英翻译模型。
实现长度惩罚和覆盖惩罚的Beam Search。
实现回译(back-translation)增强训练数据。
⚠️ 需要避免的典型错误:
💡 提升模型性能的系统方法:
理解本课内容需要将其置于更大的知识网络中。每个核心概念都不是孤立的,它们相互关联、相互支撑:
建立正确的直觉比记住公式更重要:
1. 维度直觉:高维空间中,数据分布与低维直觉截然不同(维度诅咒)
2. 信息瓶颈:神经网络逐层压缩信息,保留任务相关的、丢弃无关的
3. 流形假设:高维数据实际分布在低维流形上,学习即发现流形结构
4. 偏差-方差权衡:简单模型欠拟合(高偏差),复杂模型过拟合(高方差)
本课作为实战项目阶段的核心内容,与前后课程紧密关联:
| 关联课程 | 关联点 | 协同效应 |
|---|---|---|
| 前序课程 | 提供了本课的基础知识 | 循序渐进的理解 |
| 后续课程 | 本课内容是后续的基础 | 逐步构建能力 |
| 平行课程 | 同一阶段的互补知识 | 多角度深入理解 |
| 实战项目 | 综合运用所有知识 | 理论与实践结合 |
💡 准备面试时,确保能回答以下问题:
掌握本课内容后,可以通过以下方式继续深入:
机器翻译实战——你在连接不同语言!