Transformer模型是自然语言处理(NLP)领域的核心技术之一,因其强大的并行处理能力和自注意力机制而被广泛应用于机器翻译、文本生成等任务。本文将带你从零开始,逐步了解Transformer的原理、训练过程和推理实战。我们以一个简单的英文到中文翻译任务为例,展示如何构建、训练并使用Transformer模型。文中包含完整的代码实现、详细注释以及具体的训练和推理结果。
Transformer模型由Vaswani等人在2017年的论文《Attention is All You Need》中首次提出。与传统的循环神经网络(RNN)不同,Transformer摒弃了序列依赖,完全依赖自注意力机制(Self-Attention Mechanism)处理数据。这种设计使其能够并行处理整个输入序列,大幅提升效率。
生活中的例子:假设你在听朋友说:“我昨天去超市买了苹果。”你会自然关注“超市”和“苹果”,并联想到自己的购物经历。Transformer的自注意力机制就像这样,能快速抓住句子中的关键信息并建立联系。
自注意力机制是Transformer的灵魂。它通过计算输入序列中每个单词与其他单词的相关性(注意力权重),为每个单词生成一个新的表示。这种方式让模型能够同时关注整个序列,而不是逐个处理。
生活中的例子:在超市购物时,看到“苹果”会让你想到“水果”区域。自注意力机制帮助模型在句子中找到类似的关联。
Transformer由两大部分组成:
生活中的例子:编码器像厨师,把原材料(英文句子)加工成半成品(中间表示);解码器像服务员,根据半成品和顾客需求(已翻译的部分),端出最终菜品(中文句子)。
我们将构建一个简单的Transformer模型,实现英文短句到中文的翻译。我们使用一个小数据集,包含4对英文-中文句子对。
确保已安装以下Python库:
pip install torch numpy
我们定义一个简单的数据集,并构建词汇表:
# 英文句子和中文翻译
english_sentences = ["hello", "thank you", "how are you", "I am fine"]
chinese_sentences = ["你好", "谢谢", "你好吗", "我很好"]
# 构建词汇表
english_vocab = {"" : 0, "hello": 1, "thank": 2, "you": 3, "how": 4, "are": 5, "I": 6, "am": 7, "fine": 8}
chinese_vocab = {"" : 0, "" : 1, "" : 2, "你好": 3, "谢谢": 4, "你好吗": 5, "我很好": 6}
reverse_chinese_vocab = {v: k for k, v in chinese_vocab.items()} # 用于推理时映射回中文
以下是用PyTorch实现的简单Transformer模型,包含详细注释:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义Transformer模型
class SimpleTransformer(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim, num_layers):
super(SimpleTransformer, self).__init__()
# 输入和输出的嵌入层
self.input_embedding = nn.Embedding(len(english_vocab), input_dim)
self.output_embedding = nn.Embedding(len(chinese_vocab), output_dim)
# 编码器
self.encoder = nn.TransformerEncoder(
nn.TransformerEncoderLayer(d_model=input_dim, nhead=2, dim_feedforward=hidden_dim),
num_layers=num_layers
)
# 解码器
self.decoder = nn.TransformerDecoder(
nn.TransformerDecoderLayer(d_model=output_dim, nhead=2, dim_feedforward=hidden_dim),
num_layers=num_layers
)
# 输出层:将解码器输出映射到词汇表大小
self.fc = nn.Linear(output_dim, len(chinese_vocab))
def forward(self, src, tgt):
# src:源序列(英文),tgt:目标序列(中文)
src_embed = self.input_embedding(src) # 输入嵌入
tgt_embed = self.output_embedding(tgt) # 输出嵌入
memory = self.encoder(src_embed) # 编码器处理输入
output = self.decoder(tgt_embed, memory) # 解码器生成输出
output = self.fc(output) # 映射到词汇表大小
return output
# 设置参数
input_dim = 10 # 输入嵌入维度
output_dim = 10 # 输出嵌入维度
hidden_dim = 20 # 前馈网络隐藏层维度
num_layers = 2 # 编码器和解码器层数
# 实例化模型
model = SimpleTransformer(input_dim, output_dim, hidden_dim, num_layers)
以下是完整的训练代码,包括数据预处理和训练过程:
# 数据预处理:将句子转为张量
def sentence_to_tensor(sentence, vocab, max_len=3):
words = sentence.split()
indices = [vocab.get(word, 0) for word in words] # 未识别的词用
indices = indices[:max_len] + [0] * (max_len - len(indices)) # 填充或截断
return torch.tensor(indices, dtype=torch.long).unsqueeze(1) # [seq_len, batch_size]
# 准备训练数据
src_data = torch.cat([sentence_to_tensor(sent, english_vocab) for sent in english_sentences], dim=1) # [seq_len, batch_size]
tgt_data = torch.cat([sentence_to_tensor(sent, chinese_vocab) for sent in chinese_sentences], dim=1) # [seq_len, batch_size]
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss(ignore_index=0) # 忽略的损失
learning_rate = 0.001
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练模型
num_epochs = 100 #训练轮数
for epoch in range(num_epochs):
optimizer.zero_grad() # 清零梯度
output = model(src_data, tgt_data) # 前向传播,[seq_len, batch_size, vocab_size]
loss = criterion(output.view(-1, len(chinese_vocab)), tgt_data.view(-1)) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
# 每10轮输出一次
if (epoch + 1) % 10 == 0:
print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}, Learning Rate: {learning_rate}")
训练输出示例:
Epoch [10/100], Loss: 1.7294, Learning Rate: 0.001
Epoch [20/100], Loss: 1.3534, Learning Rate: 0.001
Epoch [30/100], Loss: 1.1513, Learning Rate: 0.001
Epoch [40/100], Loss: 0.9753, Learning Rate: 0.001
Epoch [50/100], Loss: 0.8130, Learning Rate: 0.001
Epoch [60/100], Loss: 0.7358, Learning Rate: 0.001
Epoch [70/100], Loss: 0.6418, Learning Rate: 0.001
Epoch [80/100], Loss: 0.5613, Learning Rate: 0.001
Epoch [90/100], Loss: 0.5246, Learning Rate: 0.001
Epoch [100/100], Loss: 0.4725, Learning Rate: 0.001
解析:
sentence_to_tensor
将句子转为张量,统一长度为3,填充
。训练完成后,我们使用模型对新句子进行推理,并展示完整的翻译过程。
以下是将 “thank you” 翻译为中文的完整示例:
# 将输入句子转为张量
def sentence_to_tensor(sentence, vocab, max_len=3):
words = sentence.split()
indices = [vocab.get(word, 0) for word in words]
indices = indices[:max_len] + [0] * (max_len - len(indices))
return torch.tensor(indices, dtype=torch.long).unsqueeze(1)
# 输入句子
input_sentence = "thank you"
src_tensor = sentence_to_tensor(input_sentence, english_vocab)
# 初始目标序列(从开始)
tgt_tensor = torch.tensor([[1]], dtype=torch.long) #
# 推理
model.eval()
with torch.no_grad():
output = model(src_tensor, tgt_tensor) # [seq_len, batch_size, vocab_size]
predicted_idx = torch.argmax(output[0, 0]).item() # 取最可能的输出索引
translated = reverse_chinese_vocab.get(predicted_idx, "未知")
# 输出结果
print(f"输入英文: {input_sentence}")
print(f"预测中文: {translated}")
输出结果:
输入英文: thank you
预测中文: 谢谢
开始,模拟解码器的逐步生成。argmax
选择最可能的词。注意:这里简化了序列生成逻辑(只预测一个词)。实际中需循环生成直到
。
自注意力机制由nn.TransformerEncoderLayer
和nn.TransformerDecoderLayer
实现,自动计算注意力权重并生成加权表示。
生活中的例子:就像你在超市看到“苹果”会想到“水果”区域,自注意力帮助模型找到句子中的关键联系。
loss.item()
反映预测与目标的差距,类似你在学做菜时,尝到味道与预期有多远。lr=0.001
控制学习步长,像你每次改进厨艺的幅度。通过这篇博客,你从原理到实战完整体验了Transformer模型的构建、训练和推理过程。完整的训练代码展示了如何处理真实数据,推理示例将 “thank you” 翻译为“谢谢”,直观展示了模型能力。在实际项目中,你可以扩展数据集、增加模型复杂度(如更多层或维度),进一步提升性能。希望这篇指南为你的NLP学习和实践提供启发!