输出部分 - 代码测试
1 课程概览
本课讲解 Transformer 输出部分的代码测试。获取解码器的输出结果,初始化输出生成器(将 512 维转换为 1000 维),通过生成器获取概率分布,验证输出维度和概率和为 1。
2 核心概念与定义
- 测试流程:获取解码器输出 → 初始化生成器 → 获取概率分布 → 验证输出维度 → 验证概率和为 1。
- Generator:输出生成器,将 512 维转换为 1000 维。
- 概率分布:每个单词是 1000 个词中的概率。
- 概率和为 1:1000 个概率相加和为 1。
3 模型与算法详解
测试流程
1. 获取解码器的输出结果
2. 初始化输出生成器(512 → 1000)
3. 通过生成器获取概率分布
4. 验证输出维度([2, 4, 1000])
5. 验证概率和为 1
输出形状
| 步骤 | 形状 | 说明 |
|---|---|---|
| 解码器输出 | [2, 4, 512] | 解码器的输出 |
| Generator 输出 | [2, 4, 1000] | 概率分布 |
概率验证
验证 1000 个概率相加和为 1。
log_probs = output[0, 0, :] # [1000]
probs = torch.exp(log_probs) # 将对数概率转换为概率
probs.sum() # 应该接近 1
4 数学原理与推导
对数概率
$$\text{log_probs} = \text{LogSoftmax}(\text{Linear}(\text{x}))$$
概率
$$\text{probs} = \exp(\text{log_probs})$$
概率和
$$\sum_{i=1}^{\text{vocab_size}} \text{probs}_i = 1$$
5 代码示例
import torch
import torch.nn as nn
import torch.nn.functional as F
class Generator(nn.Module):
"""Transformer 输出部分"""
def __init__(self, d_model, vocab_size):
super(Generator, self).__init__()
self.linear = nn.Linear(d_model, vocab_size)
def forward(self, x):
return F.log_softmax(self.linear(x), dim=-1)
def use_generator():
"""测试输出部分"""
print("=== 输出部分 - 代码测试 ===")
# 1. 获取解码器的输出结果
# result = use_decoder() # 假设已获取解码器输出
batch_size = 2
seq_len = 4
d_model = 512
vocab_size = 1000
result = torch.randn(batch_size, seq_len, d_model) # [2, 4, 512]
print(f"1. 解码器输出形状: {result.shape}")
# 2. 初始化输出生成器(512 → 1000)
generator = Generator(d_model, vocab_size)
print(f"\n2. 输出生成器:\n{generator}")
# 3. 通过生成器获取概率分布
output = generator(result)
print(f"\n3. 输出形状: {output.shape}") # [2, 4, 1000]
# 4. 验证输出维度
print(f"\n4. 验证输出维度:")
print(f" batch_size: {output.shape[0]}") # 2
print(f" seq_len: {output.shape[1]}") # 4
print(f" vocab_size: {output.shape[2]}") # 1000
# 5. 验证概率和为 1
print(f"\n5. 验证概率和为 1:")
# 5.1 提取第一个样本第一个词的概率
log_probs = output[0, 0, :] # [1000]
print(f" 第一个样本第一个词的对数概率形状: {log_probs.shape}")
# 5.2 将对数概率转换为概率
probs = torch.exp(log_probs) # [1000]
print(f" 概率形状: {probs.shape}")
# 5.3 验证概率和
prob_sum = probs.sum().item()
print(f" 概率和: {prob_sum:.4f}") # 应该接近 1
# 5.4 验证所有样本的概率和
all_probs = torch.exp(output) # [2, 4, 1000]
prob_sums = all_probs.sum(dim=-1) # [2, 4]
print(f"\n 所有样本的概率和:")
print(f" {prob_sums}")
# 6. 查看概率最高的词
print(f"\n6. 查看概率最高的词:")
topv, topi = output[0, 0, :].topk(5)
print(f" 第一个样本第一个词概率最高的 5 个词:")
for i in range(5):
print(f" 词 {topi[i].item()}: {topv[i].item():.4f}")
# 测试
if __name__ == "__main__":
use_generator()
代码说明
| 代码 | 说明 |
|---|---|
Generator(d_model, vocab_size) | 输出生成器 |
generator(result) | 获取概率分布 |
torch.exp(output) | 将对数概率转换为概率 |
probs.sum() | 验证概率和 |
output.topk(5) | 取概率最高的 5 个词 |
6 重难点与易错提醒
- ❗重点:输出形状为 [2, 4, 1000]。
- ❗重点:概率和应该接近 1。
- ❗重点:使用
torch.exp将对数概率转换为概率。 - ⚠️易错:LogSoftmax 输出的是对数概率,需要用
torch.exp转换为概率。
7 课堂问答精选
Q1:如何验证概率和为 1?
A:使用 torch.exp(output) 将对数概率转换为概率,然后求和,应该接近 1。
Q2:输出形状 [2, 4, 1000] 表示什么?
A:表示 2 个句子,每个句子 4 个单词,每个单词是 1000 个词中的概率分布。
Q3:如何查看概率最高的词?
A:使用 output.topk(5) 取概率最高的 5 个词。
8 本课小结
- 测试流程:获取解码器输出 → 初始化生成器 → 获取概率分布 → 验证输出维度 → 验证概率和为 1。
- 输出形状为 [2, 4, 1000]。
- 使用
torch.exp将对数概率转换为概率,概率和应该接近 1。
9 延伸思考
- 如何搭建完整的 Transformer 架构?
- 如何使用 Transformer 进行机器翻译?