Transformer的PyTorch实现之若干问题探讨(一)

Transformer的PyTorch实现》这篇博文以一个机器翻译任务非常优雅简介的阐述了Transformer结构。在阅读时存在一些小困惑,此处权当一个记录。

1.自定义数据中enc_input、dec_input及dec_output的区别

博文中给出了两对德语翻译成英语的例子:

python 复制代码
# S: decoding input 的起始符
# E: decoding output 的结束符
# P:意为padding,如果当前句子短于本batch的最长句子,那么用这个符号填补缺失的单词
sentence = [
    # enc_input   dec_input    dec_output
    ['ich mochte ein bier P','S i want a beer .', 'i want a beer . E'],
    ['ich mochte ein cola P','S i want a coke .', 'i want a coke . E'],
]

初看会对这其中的enc_input、dec_input及dec_output三个句子的作用不太理解,此处作详细解释:
-enc_input 是模型需要翻译的输入句子,
-dec_input 是用于指导模型开始翻译过程的信号
-dec_output 是模型训练时的目标输出,模型的目标是使其产生的输出尽可能接近dec_output,即为翻译真实标签。他们在transformer block中的位置如下:

在使用Transformer进行翻译的时候,需要在Encoder端输入enc_input编码的向量,在decoder端最初只输入起始符S,然后让Transformer网络预测下一个token。

我们知道Transformer架构在进行预测时,每次推理时会获得下一个token,因此推理不是并行的,需要输出多少个token,理论上就要推理多少次。那么,在训练阶段,也需要像预测那样根据之前的输出预测下一个token,然而再所引出dec_output中对应的token做损失吗?实际并不是这样,如果真是这样做,就没有办法并行训练了。

实际我认为Transformer的并行应该是有两个层次:

(1)不同batch在训练和推理时是否可以实现并行?

(2)一个batch是否能并行得把所有的token推理出来?

Tranformer在训练时实现了上述的(1)(2),而推理时(1)(2)都没有实现。Transformer的推理似乎很难实现并行,原因是如果一次性推理两句话,那么如何保证这两句话一样长?难道有一句已经结束了,另一句没有结束,需要不断的把结束符E送入继续预测下一个结束符吗?此外,Transformer在预测下一个token时必须前面的token已经预测出来了,如果第i-1个token都没有,是无法得到第i个token。因此推理的时候都是逐句话预测,逐token预测。这儿实际也是我认为是transformer结构需要改进的地方。这样才可以提高transformer的推理效率。

2.Transformer的训练流程

此处给出博文中附带的非常简洁的Transformer训练代码:

python 复制代码
from torch import optim
from model import *

model = Transformer().cuda()
model.train()
# 损失函数,忽略为0的类别不对其计算loss(因为是padding无意义)
criterion = nn.CrossEntropyLoss(ignore_index=0)
optimizer = optim.SGD(model.parameters(), lr=1e-3, momentum=0.99)

# 训练开始
for epoch in range(1000):
    for enc_inputs, dec_inputs, dec_outputs in loader:
        '''
        enc_inputs: [batch_size, src_len] [2,5]
        dec_inputs: [batch_size, tgt_len] [2,6]
        dec_outputs: [batch_size, tgt_len] [2,6]
        '''
        enc_inputs, dec_inputs, dec_outputs = enc_inputs.cuda(), dec_inputs.cuda(), dec_outputs.cuda() # [2, 6], [2, 6], [2, 6]
        outputs = model(enc_inputs, dec_inputs) # outputs: [batch_size * tgt_len, tgt_vocab_size]
        loss = criterion(outputs, dec_outputs.view(-1))  # 将dec_outputs展平成一维张量

        # 更新权重
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        print(f'Epoch [{epoch + 1}/1000], Loss: {loss.item()}')
torch.save(model, f'MyTransformer_temp.pth')

这段代码非常简洁,可以看到输入的是batch为2的样本,送入Transformer网络中直接logits算损失。Transformer在训练时实际上使用了一个策略叫teacher forcing。要解释这个策略的意义,以本博文给出的样本为例,对于输入的样本:

bash 复制代码
ich mochte ein bier

在进行训练时,当我们给出起始符S,接下来应该预测出:

bash 复制代码
I

那训练时,有了SI后,则应该预测出

bash 复制代码
want

那么问题来了,如I 就预测错了,假如预测成了a ,那么在预测want 时,还应该使用Sa 来预测吗?当然不是,即使预测错了,也应该用对应位置正确的tokenSI去预测下一个token,这就是teacher forcing。

那么transformer是如何实现这样一个teacher forcing的机制的呢?且听下回分解。

相关推荐
麻瓜生活睁不开眼1 分钟前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
workflower36 分钟前
装备企业的 AI 路线图
人工智能·深度学习·机器学习·设计模式·机器人
西柚研究生1234564 小时前
创建自己的数据集(GoogLeNet)
深度学习·神经网络·cnn
逻辑君8 小时前
基于 PPO 的双足机器人行走控制
人工智能·深度学习·机器人
美狐美颜SDK开放平台10 小时前
直播APP开发,美颜SDK和相机SDK有什么区别?
android·深度学习·数码相机·ios·直播美颜sdk·视频美颜sdk
逻辑君10 小时前
基于 A2C 算法的双足机器人行走控制
人工智能·深度学习·算法·机器学习·机器人
罗西的思考11 小时前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 — (14)— Teacher
人工智能·笔记·深度学习·算法·机器学习
薛定e的猫咪11 小时前
如何高效构建一个RAG知识库 dify实例与常见问题
人工智能·深度学习
手写码匠12 小时前
华为云Flexus+DeepSeek征文|DeepSeek+RAG知识库实战:基于Flexus X实例与Dify构建企业级智能问答系统
人工智能·深度学习·算法·aigc
bittersuite12 小时前
LeNet,AlexNet
人工智能·深度学习·机器学习