Transformer 架构测试(下)
1 课程概览
本课讲解 Transformer 架构的测试(下)。构建测试输入数据(源序列和目标序列),初始化掩码(source_mask 和 target_mask),执行前向传播,验证输出形状为 [2, 4, 1000]。
2 核心概念与定义
- 测试输入数据:源序列(source_x)和目标序列(target_y)。
- 掩码:source_mask(填充掩码)和 target_mask(序列掩码)。
- 前向传播:通过 Transformer 模型进行前向传播。
- 输出形状:[2, 4, 1000](2 个句子,每个句子 4 个单词,每个单词是 1000 个词的概率)。
3 模型与算法详解
测试流程
1. 构建测试输入数据(源序列)
2. 构建测试输入数据(目标序列)
3. 初始化掩码(source_mask, target_mask)
4. 执行前向传播
5. 验证输出形状
输入数据
| 数据 | 形状 | 说明 |
|---|---|---|
| source_x | [2, 4] | 源序列(2 个句子,每个句子 4 个单词) |
| target_y | [2, 4] | 目标序列(2 个句子,每个句子 4 个单词) |
| source_mask | [4, 4] | 填充掩码 |
| target_mask | [4, 4] | 序列掩码 |
输出数据
| 数据 | 形状 | 说明 |
|---|---|---|
| result | [2, 4, 1000] | 概率分布 |
掩码说明
source_mask(填充掩码):防止填充的 pad 值影响注意力计算结果。
target_mask(序列掩码):防止未来的信息被提前利用(防止偷看未来的词)。
target_mask(下三角矩阵):
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
4 数学原理与推导
前向传播
$$\text{result} = \text{Transformer}(\text{source_x}, \text{target_y}, \text{source_mask}, \text{target_mask})$$
输出形状
$$\text{result.shape} = [\text{batch_size}, \text{seq_len}, \text{vocab_size}] = [2, 4, 1000]$$
5 代码示例
import torch
import torch.nn as nn
def test_transformer():
"""测试 Transformer 架构"""
print("=== Transformer 架构测试(下)===")
# 假设 make_model 函数已定义
# from transformer import make_model
source_vocab = 1000
target_vocab = 1000
# 构建 Transformer 模型
# my_transformer = make_model(source_vocab, target_vocab, N=6, d_model=512, num_heads=8)
# 使用 PyTorch 内置的 Transformer
my_transformer = nn.Transformer(
d_model=512,
nhead=8,
num_encoder_layers=6,
num_decoder_layers=6,
dim_feedforward=2048,
dropout=0.1,
batch_first=True
)
print(f"Transformer 模型创建成功")
# 1. 构建测试输入数据(源序列)
# 2 个句子,每个句子 4 个单词
source_x = torch.tensor([
[1, 2, 3, 4],
[5, 6, 7, 8]
]) # [2, 4]
print(f"\n1. 源序列形状: {source_x.shape}")
# 2. 构建测试输入数据(目标序列)
# 2 个句子,每个句子 4 个单词
target_y = torch.tensor([
[3, 8, 6, 4],
[9, 6, 2, 6]
]) # [2, 4]
print(f"2. 目标序列形状: {target_y.shape}")
# 3. 初始化掩码
# 实际开发要根据序列长度动态生成
# 这里直接写死
source_mask = torch.zeros(4, 4) # [4, 4]
target_mask = torch.zeros(4, 4) # [4, 4]
print(f"3. 掩码形状: {source_mask.shape}")
# 4. 执行前向传播
# 注意:PyTorch 内置的 Transformer 需要词嵌入
# 这里简化测试,直接使用随机数据
batch_size = 2
seq_len = 4
d_model = 512
source_embedded = torch.randn(batch_size, seq_len, d_model) # [2, 4, 512]
target_embedded = torch.randn(batch_size, seq_len, d_model) # [2, 4, 512]
result = my_transformer(source_embedded, target_embedded, source_mask, target_mask)
print(f"\n4. 前向传播完成")
print(f" Transformer 输出结果: {result.shape}") # [2, 4, 512]
# 5. 验证输出形状
print(f"\n5. 验证输出形状:")
print(f" batch_size: {result.shape[0]}") # 2
print(f" seq_len: {result.shape[1]}") # 4
print(f" d_model: {result.shape[2]}") # 512
# 6. 如果有输出生成器
generator = nn.Linear(d_model, target_vocab)
output = generator(result)
print(f"\n6. 输出生成器输出形状: {output.shape}") # [2, 4, 1000]
# 7. 应用 LogSoftmax
output = nn.LogSoftmax(dim=-1)(output)
print(f"7. LogSoftmax 输出形状: {output.shape}") # [2, 4, 1000]
# 8. 验证概率和为 1
probs = torch.exp(output)
prob_sum = probs[0, 0, :].sum().item()
print(f"\n8. 第一个样本第一个词的概率和: {prob_sum:.4f}") # 应该接近 1
# 测试
if __name__ == "__main__":
test_transformer()
代码说明
| 代码 | 说明 |
|---|---|
torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) | 源序列 |
torch.tensor([[3, 8, 6, 4], [9, 6, 2, 6]]) | 目标序列 |
torch.zeros(4, 4) | 掩码 |
my_transformer(source_embedded, target_embedded, source_mask, target_mask) | 前向传播 |
nn.Linear(d_model, target_vocab) | 输出生成器 |
nn.LogSoftmax(dim=-1) | LogSoftmax |
6 重难点与易错提醒
- ❗重点:测试输入数据是源序列和目标序列。
- ❗重点:掩码要根据序列长度动态生成。
- ❗重点:输出形状为 [2, 4, 1000]。
- ⚠️易错:实际开发中掩码需要动态生成,不能写死。
- 💡技巧:使用
torch.exp(output)验证概率和为 1。
7 课堂问答精选
Q1:测试输入数据有哪些?
A:测试输入数据包括源序列(source_x)和目标序列(target_y),形状都是 [2, 4]。
Q2:掩码如何生成?
A:实际开发中要根据序列长度动态生成,测试时可以直接写死。
Q3:输出形状 [2, 4, 1000] 表示什么?
A:表示 2 个句子,每个句子 4 个单词,每个单词是 1000 个词中的概率分布。
8 本课小结
- 测试流程:构建测试输入数据 → 初始化掩码 → 执行前向传播 → 验证输出形状。
- 测试输入数据:源序列(source_x)和目标序列(target_y)。
- 掩码:source_mask(填充掩码)和 target_mask(序列掩码)。
- 输出形状为 [2, 4, 1000]。
9 延伸思考
- 如何使用 Transformer 进行机器翻译?
- 如何训练 Transformer 模型?
- 如何优化 Transformer 模型的性能?