Transformer之Decoder
1. 解码器(Decoder)
1.1 Decoder解码流程
- 输出嵌入的右向偏移
在开始处理输入序列之前,模型对输出嵌入进行向右偏移一个位置,确保在训练阶段,解码器内的每个符号都能正确地获取之前生成符号的上下文信息。 - 位置编码的整合
仿照编码器的设计,模型将位置编码与输出嵌入相结合,以此保留符号的序列顺序信息。 - 带掩码的多头自注意力机制
解码器利用带掩码的多头自注意力机制,专注于输入序列的相关片段以及之前产生的符号。在训练过程中,通过掩码技术,防止模型对未来符号的预知,确保每个符号仅能参考其之前的符号。 - 编码器-解码器注意力交互
除了带掩码的自注意力机制外,解码器还融合了编码器-解码器注意力交互,这使得解码器能够聚焦于输入序列的重要部分,进而生成受输入语境影响的输出符号。 - 基于位置的前馈网络
在自注意力层之后,解码器对每个符号独立施加位置编码的前馈网络。该网络旨在捕捉输入和已生成符号之间的复杂模式与关联,以助力精确输出序列的构建。
Decoder 部分相比于 Encoder ,其结构中增加了一个名为“Mask”的多头注意力子层。与标准的多头注意力机制中的缩放点积注意力不同,Mask-Multi-Head-Attention在应用缩放操作之后引入了一个Mask步骤。
这一操作的必要性源于解码过程中的特性:解码并非一次性完成,而是按时间步逐个生成输出。在生成某个特定时间步的输出时,模型不应访问该时间步之后的信息,因此通过Mask操作来隐藏未来的序列元素,确保解码过程的一致性和正确性。
在解码时的流程为:
- 假设当前已经解码的序列为
s 1 , s 2 , … , s t − 1 s_1,s_2,\ldots,s_{t-1} s1,s2,…,st−1
把该序列做词向量和位置向量嵌入 - 对上述向量做 Masked Multi-Head Attention,把得到的结果作为 Q
- Encoder 端的输出向量看做 K,V
- 结合 Q,K,V 做 Multi-Head Attention 和 Feed-Forward Networks 等操作
- 重复 decoder 部分 的子结构得到输出,而后解码得到输出词的概率
1.2 Decoder子结构
解码器同样采用了6层堆叠的结构,并划分为三个子结构。与编码器相比,解码器主要有以下三个不同点:
子结构-1 实现了“Mask”的多头注意力机制,这是为了防止模型在预测过程中提前“窥视”到未来的数据,从而避免信息泄露。
子结构-2 是一个编码器-解码器多头注意力机制,它负责在编码器的输出和解码器的中间表示之间建立联系。
子结构-3 的输出后面紧接着一个线性层和一个softmax层,它们共同作用,用于预测目标词汇的概率分布。
1.3 Decoder的多头自注意力vs Encoder的多头自注意力
1.3.1 编码器的多头自注意力
功能
输入序列中的信息,通过多头自注意力机制对整个输入序列进行全局依赖建模。这种机制允许每个词自由地关注序列中的任何位置,从而捕捉输入序列中的上下文关系,并形成丰富的上下文表示。
- 想象你是一名厨师,正在尝试理解一份复杂的食谱。编码器的多头自注意力就像是你能够同时关注食谱中的每个食材和步骤,理解它们如何相互作用和结合在一起。例如,在一份意大利面的食谱中,你可能会注意到番茄酱、面条、橄榄油和香草等食材,以及它们混合和烹饪的步骤。
任务
编码器的任务是提取输入序列的全局特征,不受因果顺序的限制,因此不需要遮掩机制。
- 在这个例子中,编码器的任务是理解整个烹饪过程。它需要分析食谱中的每个部分(食材和步骤),并理解它们在整个菜肴中的角色。比如,编码器会注意到番茄酱是调味的关键,面条需要煮熟到适当的硬度,而香草则是用来增加风味。
1.3.2 解码器的多头自注意力
功能
解码器的多头自注意力作用于目标序列(已生成的部分),其功能是生成输出序列的下一个词。为了维持生成过程的因果性,解码器的自注意力加入了掩码机制。
- 现在,假设你是一名食谱作者,你刚刚尝试了那道意大利面,并想要写下自己的食谱。解码器的多头自注意力机制,就如同在编写食谱时,你能够细致地协调各个烹饪步骤,确保它们按照实际操作流程有序且合理地展开。例如,你不会在煮面条之前就写上如何制作番茄酱,而是按照实际烹饪的顺序来撰写。
任务
解码器的任务是预测输出序列的下一个词,这要求它根据已生成的序列部分来预测未来词,同时避免泄露未来信息。
- 解码器的任务是生成食谱。它会根据你作为厨师的经验(编码器的输出),一步步地写出食谱。当你写到一个步骤(比如煮面条),解码器的自注意力会确保接下来的步骤(比如制作番茄酱)是基于前面的步骤完成的。
1.3.3 掩码机制(Masking)
编码器:编码器没有掩码机制,可以自由地处理和理解整个输入序列(食谱的所有步骤)
- 想象你是一名厨师,正在编写一份复杂的食谱。编码器就像是你大脑中的记忆和理解部分,它需要消化和理解整个烹饪过程。
- 这意味着你可以自由地查看和思考整个食谱的所有步骤和食材。比如,你在准备调味料时,可以同时考虑它在烹饪过程中的每一步如何使用,以及它如何与其它食材相互作用。你可以在任何时候访问任何信息,因为编码器的任务是理解整个输入(食谱)的全局依赖关系。
解码器:解码器的自注意力采用因果掩码机制,确保在生成输出序列时,当前词只能与之前的词进行交互,通过将未来词的注意力值设为负无穷大来实现。
- 现在,想象你是另一位厨师,正在根据食谱逐步烹饪。解码器就像是你按照食谱烹饪时的思维过程,它必须按照一定的顺序执行步骤。
- 因果掩码机制确保你在烹饪时只能根据已经完成的步骤来决定下一步做什么。这就像是在烹饪过程中,你只能打开食谱的当前页,而不能偷看后面的步骤。
- 例如,如果你正在炒菜,因果掩码机制会阻止你提前知道最后的调味步骤,直到你完成了炒菜的所有前置步骤。
- 当你到达调味步骤时,你可以参考整个烹饪过程中已经完成的步骤(编码器的输出),但是你仍然不能“预知”未来的步骤,只能根据当前和之前的步骤来决定下一步。
1.3.4 模型结构差异
编码器:编码器的多头自注意力仅依赖于输入序列的信息,不涉及其他模块。
想象你是一名厨师,正在学习如何制作一道复杂的菜肴。编码器就像是你大脑中负责学习和记忆食谱的部分。
- 结构:编码器的结构类似于一个高级的厨房助手,它能够同时观察和理解食谱中的所有食材和步骤。它不关心步骤的执行顺序,而是关注于食材之间的相互作用和步骤之间的依赖关系。
- 例子:在烹饪前,你阅读整个食谱,理解每种食材的特性(如味道、烹饪时间)和每一步的目的(如炒、炖、调味)。
解码器:解码器的多头自注意力除了包含自注意力层外,还额外包含一个交叉注意力层,允许解码器访问编码器编码的输入序列的隐藏表示,以结合输入信息生成输出序列。
解码器则像是你在实际烹饪过程中的大脑,它需要按照食谱的步骤逐步操作。
- 结构:解码器的结构更为复杂,它不仅包含一个类似于编码器的部分(用于理解当前烹饪状态),还包含一个额外的交叉注意力层(类似于参考食谱的提示)。
- 例子:在实际烹饪时,你根据食谱的当前步骤准备食材,但同时也会参考之前学到的知识(编码器的输出)来调整烹饪技巧。
1.3.5训练与生成过程的差异
编码器:在训练和推理阶段,编码器的自注意力处理方式相同,因为它总是可以访问整个输入序列。
- 训练:在训练过程中,编码器可以一次性看到整个食谱的所有信息,并学习如何将这些信息编码成有用的表示。
- 生成:在生成过程中(即实际烹饪),编码器的角色是提供对整个食谱的深入理解,这不会随着烹饪的进行而改变。
解码器:在训练阶段,解码器可以并行处理整个目标序列;而在推理阶段,目标序列是逐步生成的,解码器必须依次计算每个新词的注意力。
- 训练:在训练过程中,解码器可以并行地学习整个烹饪过程,因为它有整个目标序列(即完整的烹饪步骤)作为参考。
- 生成:在生成过程中(实际烹饪时),解码器必须逐个步骤地执行。你无法同时知道所有的下一步,而必须根据当前步骤和之前步骤的结果来决定下一步做什么。
- 例子:在烹饪时,你首先准备食材(第一步),然后根据这一步的结果来决定如何进行烹饪(第二步),依此类推,直到菜肴完成。
2. 掩码(Mask)
2.1 Decoder 为什么要加 Mask?
在解码器(decoder)中使用掩码(mask)的目的是确保当前位置的输出仅仅依赖于其之前的位置,而不是未来的位置。这主要适用于序列生成任务,例如机器翻译、文本生成等。
掩码(mask)的作用:
1. 因果关系(Causality)
在序列生成中,每个输出仅仅应当依赖于之前的输出。例如,生成句子的第四个单词时,我们只能考虑前三个单词,而不能考虑第五个单词。加入掩码确保模型在训练时保持这种因果关系。
2. 训练与推理的一致性
在推理(即实际使用)时,我们通常采用自回归方式生成序列:一次生成一个标记,然后将其作为新输入传递回模型。使用掩码确保模型在训练和推理时的行为是一致的。
3. 避免信息泄露
如果不使用掩码,模型可能会在训练期间“窥视”未来的标记,并过度依赖这些信息。这会导致在推理时性能下降,因为在实际应用中这些未来的标记是不可用的。
在实际操作中,掩码通常是一个上三角形状的矩阵,其中上三角(包括对角线)的部分设为0,其余部分设为负无穷(或非常大的负数)。在应用 softmax 函数计算注意力权重之前,这个掩码会被加到注意力分数上,这样上三角部分的分数在 softmax 后基本上就会变成0,从而实现了掩蔽效果。
2.2 填充(padding)和掩码(masking)机制。
假设训练中最长的句子为10个tokens,那么这两句话:
- “我喜欢猫猫”
- “我喜欢打羽毛球”
为了处理这些句子,我们需要将它们转换为模型可以理解的格式。
首先,我们将每个中文字符视为一个token,然后按照以下步骤操作:
步骤 1:Tokenization 我们将每个句子分词,得到以下token序列:
- “我” “喜” “欢” “猫” “猫”
- “我” “喜” “欢” “打” “羽” “毛” “球”
步骤 2:Padding 由于训练集中最长的句子长度为10个tokens,我们需要对这两个句子进行填充,使它们的长度都达到10个tokens。通常使用一个特殊的填充token(例如"")来实现这一点:
- “我” “喜” “欢” “猫” “猫” “” “” “” “” “”
- “我” “喜” “欢” “打” “羽” “毛” “球” “” “” “”
步骤 3:Masking 现在,模型需要知道哪些是真正的token,哪些是填充的token。这是通过创建一个掩码矩阵来实现的,掩码矩阵与输入序列的长度相同。在这个掩码矩阵中,真实token的位置用0表示,填充token的位置用1表示:
- 掩码:[0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
- 掩码:[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]
步骤 4:应用掩码 在模型的注意力机制中,特别是在计算softmax之前,我们会将这些掩码应用到模型中。具体来说,我们会在掩码为1的位置上加上一个非常大的负数(例如负无穷),这样在经过softmax操作后,这些位置的值将接近0,从而不会对全局概率预测产生影响。
通过这种方式,模型在计算注意力权重时,会忽略填充token,确保只关注实际的内容token。这样,模型就能够正确地学习序列数据,而不会被填充token所干扰。
掩码存在的三个位置:
2.3 Mask-Multi-Head-Attention
Mask 的目的是防止 Decoder “seeing the future”,就像防止考生偷看考试答案一样。这里mask是一个下三角矩阵,对角线以及对角线左下都是1,其余都是0。下面是个10维度的下三角矩阵
# 下三角矩阵
tensor([[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]], dtype=torch.uint8)
2.4 Linear 和 Softmax 来生成输出概率
在解码器的最终阶段,其输出将通过一个线性层进行转换,该层的作用是将解码器的输出映射到与词汇表大小相匹配的维度。随后,应用softmax函数将这些数值转换成概率分布,其中每个词汇对应一个概率值。在这一过程中,概率最高的词汇被选为预测的下一个词。
2.4.1 预测过程
(1)初始步骤:
输入准备:在这个例子中,编码器处理的是一篇文章的全文,而解码器的初始输入同样包括编码器的编码结果和一个开始符号""。
(2)生成序列:
- 预测第一个单词:解码器基于编码器的输出和开始符号来预测摘要的第一个单词。例如,这可能是摘要中的第一个词,如"Summary"。
- 迭代生成:
- 第二步,输入"Summary",解码器可能会预测下一个单词"of"。
- 第三步,输入"Summary of",解码器接着预测"the"。
- 逐步构建:在每个步骤中,解码器的输出通过线性层调整维度,并通过softmax函数转换为概率分布,选择概率最高的单词作为预测结果。
(3)结束条件:
序列终止:生成过程持续进行,直到解码器预测出序列结束的标记"“。
(4)完整示例:
假设我们正在生成文章的摘要:
第一步,输入”“,输出"Summary”。
第二步,输入"Summary",输出"of"。
第三步,输入"Summary of",输出"the"。
第四步,输入"Summary of the",输出"key"。
第五步,输入"Summary of the key",输出"points"。
最后,输入"Summary of the key points",输出"",表示摘要生成完毕。
2.4.2 训练过程
模型没有收敛得很好时,Decoder预测产生的词很可能不是我们想要的。这个时候如果再把错误的数据再输给Decoder,就会越跑越偏。这个时候怎么办?
(1)在训练过程中可以使用 “teacher forcing”。因为我们知道应该预测的word是什么,那么可以给Decoder喂一个正确的结果作为输入。
(2)除了选择最高概率的词 (greedy search),还可以选择是比如 “Beam Search”,保留top-K个预测的word。 Beam Search 方法不再是只得到一个输出放到下一步去训练了,我们可以设定一个值,拿多个值放到下一步去训练,这条路径的概率等于每一步输出的概率的乘积。
2.4.3 训练和损失函数
在训练过程中,我们使用损失函数(例如交叉熵损失)将生成的输出概率分布与目标序列进行比较。概率分布给出了每个单词出现在该位置的概率。
如上图所示,假设我们的目标词汇表只包含四个单词。我们的目标是生成一个与预期目标序列“De nada END”相匹配的概率分布。
这意味着第一个单词位置的概率分布中“De”的概率应该为 1,而词汇表中所有其他单词的概率为 0。类似地,“nada”和“END”在第二个和第三个单词位置的概率分别应该为 1。
与往常一样,损失用于计算梯度,以通过反向传播来训练 Transformer。
3. Decoder在不同阶段的信息传递机制
3.1 预测阶段
在预测阶段,解码器直接将前一个时间单元的输出(即预测值)作为输入传递给下一个时间单元。
Decoder的输入选择:
- 穷举法
softmax对所有候选词预测概率,然后使用所有的排列组合找出输出条件概率最大的序列,作为decoder的输出,可以保证全局最优,但是计算复杂度非常高
- 贪心搜索:
使用softmax对所有候选词预测概率,选概率最大的词作为当前单元的输**出,保证每一步输出最优解,但满足局部最优策略期望未必产生全局最优解
- 束搜索(Beam search):
在贪心搜索上做了个优化,设置一个束宽beam size,然后softmax预测出来的候选词概率选取概率最大的beam size个词输入下一个单元,比如下面这个例子,beam size设置为2,每个时间单元会从候选词中选择概率值最大的两个词,然后输入到下一个时间单元,在计算条件概率,然后再去最大的前两个,以此类推
3.2 训练阶段
在训练阶段采用了一种称为计划采样(scheduled sampling)的策略。使用目标文本的“标准答案”作为Decoder的输入。
首先,让我们区分两种传统模式:
(1)自由运行(Free Running)模式:
在训练阶段,解码器使用上一个时间单元的预测值作为下一个时间单元的输入。这种方法的缺点是,如果模型在某一步预测错误,那么这个错误会随着时间单元的推进而累积,导致预测结果越来越偏离正确轨迹,从而增加了训练的难度。
(2)教师强制(Teacher Forcing)模式:
为了克服自由运行模式的缺点,Teacher Forcing模式在训练时使用真实的标签(label)作为输入,而不是模型的预测值。这样,即使模型在前一个时间单元预测错误,它仍然可以在下一个时间单元接收到正确的信息,从而更容易地学习和收敛。但是,这种方法的局限性在于,它在训练和预测阶段存在不一致性,因为在实际预测时,我们无法获得真实的标签。
为了结合这两种方法的优点,计划采样(Scheduled Sampling)应运而生。这种方法的核心思想是在训练过程中动态地结合真实标签和模型的预测。
具体做法:
是设定一个概率值p,以p的概率,使用上一个时间单元的预测值作为输入,以1-p的概率,使用真实的标签作为输入。这样,解码器在训练时既能得到真实标签的适当指导,又能逐渐学会依赖自己的预测,从而提高了模型在预测阶段的稳健性和一致性。
小故事讲解:
假设你正在学习做一道复杂的菜,比如意大利千层面,而你有一个厨师朋友愿意指导你。
为了让你更好地掌握烹饪技巧,你的朋友采取了一种特别的训练方法:
有时候,比如70%的情况下(概率 p = 0.7),你的朋友会让你根据自己上一步的做法来决定下一步做什么。
比如,如果你觉得自己下一步应该开始铺面条,那么你就按照自己的想法去做。
在其余30%的情况下(概率 1 - p = 0.3),你的朋友会直接告诉你下一步应该做什么。比如,他可能会指出,实际上下一步应该是加肉酱。
通过这种方式,你在学习烹饪的过程中既能够获得实际操作的反馈,也能够在一定程度上依靠自己的判断来练习。
这样,你不仅学会了按照食谱做菜,还学会了如何根据实际情况调整烹饪步骤,最终提高了你独立烹饪复杂菜肴的能力。
3.3 如何评估模型预测出的整个句子的质量
每个单元预测出来的每个词会和真实 label 比较计算 loss 更新预测效果,但是模型预测出来的整个句子是长短不一的,我们如何判断翻译出来的整句话的效果好坏呢?
小故事讲解
想象一下,我们有一道标准食谱(参考翻译),而多位厨师(模型)根据这个食谱制作菜肴(翻译句子)。BLEU评分系统会这样评估:
- 精确度:比较预测句子中的n-gram(连续的词组)与参考句子中的n-gram的匹配程度。
- 短句惩罚:如果预测的句子比参考句子短很多,BLEU会施加惩罚,因为过短的翻译可能丢失信息。
- 最终评分:BLEU分数越高,表示预测句子与参考句子越接近,质量通常认为越好。
如果菜品的配料和步骤匹配度很高,那么这表明烹饪者的技艺更加精湛,因此评分会更高。简而言之,评分系统会通过一个“惩罚-奖励”机制来确保评分的公正性,即对于短句子(菜品分量不足)进行惩罚,而对于长句子(菜品完整且匹配度高)则给予更高的权重。
3.4 Teacher forcing
“教师强制”这一术语的灵感来源于将 RNN 比作参加多部分考试的人类学生,其中每个部分的答案(例如数学计算)都取决于前一部分的答案。在这个类比中,教师不会在最后给每个答案打分,因为学生可能会在第一部分犯错,但每个部分都失败,而会记录每个部分的分数,然后告诉学生正确答案,以便在下一部分中使用。
RNN 存在两种训练模式(mode):
- free-running 模式: 上一个时间单元的预测值作为下一个时间单元的输入。
- teacher-forcing 模式: 使用来自先验时间步长的输出作为输入。
3.4.1 teacher forcing要解决什么问题?
常见的训练RNN网络的方式是free-running mode,即将上一个时间步的输出作为下一个时间步的输入。可能导致的问题:
- 梯度消失或爆炸
- 误差累积
- 训练效率低下
训练迭代过程早期的RNN预测能力非常弱,几乎不能给出好的生成结果。如果某一个unit产生了垃圾结果,必然会影响后面一片unit的学习。
错误结果会导致后续的学习都受到不好的影响,导致学习速度变慢,难以收敛。teacher forcing最初的动机就是解决这个问题的。
使用teacher-forcing,在训练过程中,模型会有较好的效果,但是在测试的时候因为不能得到标准答案“ground truth”的支持,存在训练测试偏差,模型会变得脆弱。
3.4.2 teacher forcing的工作原理
teacher-forcing 在训练网络过程中,每次不使用上一个时间单元的预测值作为下一个时间单元的输入,而是直接使用训练数据的标准答案(ground truth)的对应上一项作为下一个时间状态的输入。
Teacher Forcing工作原理: 在训练过程的 t 时刻,使用训练数据集的期望输出或实际输出: y(t), 作为下一时间步骤的输入: x(t+1),而不是使用模型生成的输出h(t)。
一个例子:训练这样一个模型,在给定序列中前一个单词的情况下生成序列中的下一个单词。
No. | Free-running:X | Free-running:y^ | teach-forcing:X | teacher-forcing:y^ | teacher-forcing:Ground truth |
---|---|---|---|---|---|
1 | “[START]” | “put” | “[START]” | “put” | “Tom” |
2 | “[START]”,“put” | ? | “[START]”, “Tom” | ? | “put” |
3 | … | … | “[START]”, “Tom”, “put” | ? | “an” |
4 | “[START]”, “Tom”, “put”, “an” | ? | “apple” | ||
5 | … | … | … |
free-running 下如果一开始生成"an",之后作为输入来生成下一个单词,模型就偏离正轨。因为生成的错误结果,会导致后续的学习都受到不好的影响,导致学习速度变慢,模型也变得不稳定。
而使用teacher-forcing,模型生成一个"an",可以在计算了error之后,丢弃这个输出,把" Tom "作为后续的输入。该模型将更正模型训练过程中的统计属性,更快地学会生成正确的序列。
4. 模型的训练与评估
训练Transformer模型涉及优化其参数以最小化损失函数,通常使用梯度下降和反向传播。一旦训练完成,就会使用各种指标评估模型的性能,以评估其解决目标任务的有效性。
训练过程
(1) 梯度下降和反向传播:
- 在训练期间,将输入序列输入模型,并生成输出序列。
- 将模型的预测与地面真相进行比较,涉及使用损失函数(例如交叉熵损失)来衡量预测值与实际值之间的差异。
- 梯度下降用于更新模型的参数,使损失最小化的方向。
- 优化器根据这些梯度调整参数,迭代更新它们以提高模型性能。
(2) 学习率调度:
- 可以应用学习率调度技术来动态调整训练期间的学习率。
- 常见策略包括热身计划,其中学习率从低开始逐渐增加,以及衰减计划,其中学习率随时间降低。
评估指标
(1) 困惑度(perplexity):
- 困惑度是用于评估语言模型性能的常见指标,包括Transformer。
- 它衡量模型对给定标记序列的预测能力。
- 较低的困惑度值表示更好的性能,理想值接近词汇量大小。
(2) BLEU分数:
- BLEU(双语评估研究)分数通常用于评估机器翻译文本的质量。
- 它将生成的翻译与一个或多个由人类翻译人员提供的参考翻译进行比较。
- BLEU分数范围从0到1,较高的分数表示更好的翻译质量。
四、高级主题和应用
4.1 BERT(来自 Transformers 的双向编码器表示)
BERT 是一个具有里程碑意义的基于 Transformer 的模型,在 NLP 领域产生了深远影响。它通过掩码语言建模和下一句预测等目标,在大规模文本语料库上进行预训练。BERT 学习了单词的深层上下文表示,捕捉双向上下文,使其在广泛的下游 NLP 任务中表现良好。
from transformers import BertModel, BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
inputs = tokenizer("Hello, world!", return_tensors="pt")
outputs = model(**inputs)
print(outputs)
4.2 GPT(生成式预训练 Transformer)
GPT 是一个基于 Transformer 的模型,以其生成能力而闻名。与双向的 BERT 不同,GPT 采用仅解码器的架构和自回归训练来生成连贯且上下文相关的文本。研究人员和开发人员已经成功地将 GPT 应用于各种任务,如文本完成、摘要、对话生成等。
from transformers import GPT2LMHeadModel, GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')
input_text = "Once upon a time, "
inputs=tokenizer(input_text,return_tensors='pt')
output=tokenizer.decode(
model.generate(
**inputs,
max_new_tokens=100,
)[0],
skip_special_tokens=True
)
input_ids = tokenizer(input_text, return_tensors='pt')
print(output)