返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

我这样读懂了Transformer中的位置编码

[复制链接]
链载Ai 显示全部楼层 发表于 10 小时前 |阅读模式 打印 上一主题 下一主题
在自然语言处理 (NLP) 领域中,Transformer 模型从根本上重塑了我们处理序列到序列任务的方法。然而,与传统的递归神经网络 (RNN) 或卷积神经网络 (CNN) 不同,Transformer 缺乏对令牌顺序的固有感知。在本篇文章中,我们将了解到位置编码(Positional Encoding)在Transformer 模型中的重要性,它是把序列顺序嵌入 Transformer 模型的关键技术。

01
位置编码的由来


什么是位置编码,在模型的输入输出时,为什么我们首先需要它呢?

首先,我们明白单词的位置和顺序是任何语言的重要组成部分。它们定义了句子的语法,从而定义了句子的实际语义。递归神经网络 (RNN)本质上会考虑单词的顺序,他们按顺序逐字解析句子。这会将单词的顺序集成到 RNN 的主干中。

但是 Transformer 架构放弃了递归机制,转而采用多头自注意力机制。避免 RNN 的递归方法将导致训练时间的大幅加快。从理论上讲,它可以在句子中捕获更长的依赖项。

由于句子中的每个单词同时流经 Transformer 的编码器/解码器堆栈,因此模型本身对每个单词没有任何位置和顺序感。因此,仍然需要一种方法将单词的顺序合并到我们的模型中。位置编码的引入就是为了解决这个问题,它为每个词加入位置信息,让模型知道每个词在句子中的位置。


02
作用


让我们通过一个简单的例子来说明Transformer框架中位置编码的作用:

假设我们有一个英文句子:"The cat sat on the mat",并且我们使用Transformer模型来处理这个句子。Transformer模型的输入是一个词嵌入(word embedding)的序列,其中每个词都被转换成了一个固定维度的向量。如果没有位置编码,模型将无法区分这些词的顺序,因为它的自注意力机制在理论上是无序的。

步骤1:词嵌入

首先,我们将句子中的每个词转换成词嵌入向量。假设每个词嵌入的维度是4维(实际中通常是几百维),我们得到以下6个词嵌入向量(每个词一个):

The:[0.25,0.50,0.75,1.00]cat:[0.60,0.40,0.20,0.00]sat:[0.90,0.10,0.30,0.70]on:[0.45,0.55,0.65,0.35]the:[0.25,0.50,0.75,1.00]mat:[0.80,0.20,0.10,0.90]


步骤2:添加位置编码

接下来,我们为每个词嵌入向量添加位置编码。假设我们使用正弦/余弦位置编码,对于4维的词嵌入,我们可能得到以下位置编码:

Position1:[0.000,0.100,0.200,0.300](The的位置编码)Position2:[0.100,0.200,0.000,0.100](cat的位置编码)Position3:[0.200,0.000,0.100,0.200](sat的位置编码)Position4:[0.300,0.100,0.200,0.000](on的位置编码)Position5:[0.400,0.000,0.300,0.100](the的位置编码)Position6:[0.500,0.100,0.000,0.300](mat的位置编码)


步骤3:结合词嵌入和位置编码

我们将每个词嵌入与其对应的位置编码相加,得到最终的输入向量:

The:[0.25+0.000,0.50+0.100,0.75+0.200,1.00+0.300]=[0.25,0.60,0.95,1.30]cat:[0.60+0.100,0.40+0.200,0.20+0.000,0.00+0.100]=[0.70,0.60,0.20,0.10]sat:[0.90+0.200,0.10+0.000,0.30+0.100,0.70+0.200]=[1.10,0.10,0.40,0.90]on:[0.45+0.300,0.55+0.100,0.65+0.200,0.35+0.000]=[0.75,0.65,0.85,0.35]the:[0.25+0.400,0.50+0.000,0.75+0.300,1.00+0.100]=[0.65,0.50,1.05,1.10]mat:[0.80+0.500,0.20+0.100,0.10+0.000,0.90+0.300]=[1.30,0.30,0.10,1.20]


步骤4:自注意力机制

在自注意力机制中,模型会计算每个词与其他所有词的注意力分数。由于我们已经为每个词添加了位置编码,模型现在可以区分不同词的位置,并据此计算注意力分数。例如,"cat"这个词的编码会告诉模型它紧随"The"之后,而"sat"则在"cat"之后,这种顺序信息对于理解句子结构至关重要。

步骤5:输出

经过多层Transformer处理后,模型最终输出每个词的表示,这些表示包含了词义和它们在句子中的位置信息,这对于后续的任务(如翻译、文本摘要等)是非常重要的。

通过以上例子,我们可以看到位置编码在Transformer模型中的作用是为模型提供词序信息,使得模型能够捕捉到句子的结构和语义,这对于处理序列数据是非常关键的。


03
如何构建


以下是使用PyTorch创建Transformer模型中的位置编码的代码示例。这里我们将使用正弦和余弦函数来生成位置编码。
import torchimport torch.nnas nnimport mathclass PositionalEncoding(nn.Module):  def__init__(self, d_model, max_len=5000):   super(PositionalEncoding, self).__init__()       # 创建一个足够大的位置编码矩阵,以避免位置超出范围    pe = torch.zeros(max_len, d_model)    position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)    div_term = torch.exp(torch.arange(0, d_model,2).float() * (-math.log(10000.0) / d_model))    pe[:,0::2] = torch.sin(position * div_term)    pe[:,1::2] = torch.cos(position * div_term)    pe = pe.unsqueeze(0).transpose(0,1)       # 将位置编码矩阵注册为模型的缓冲区,这样它就不会被视为模型参数    self.register_buffer('pe', pe)   defforward(self, x):    # 将位置编码添加到输入的嵌入向量中    x = x + self.pe[:x.size(0), :]    return x
# 假设我们的词嵌入维度是512,最大序列长度是100d_model =512max_len =100positional_encoding =PositionalEncoding(d_model, max_len)
# 假设我们有一个随机生成的词嵌入张量,形状为[seq_len, batch_size, d_model]seq_len, batch_size =60,32x = torch.randn(seq_len, batch_size, d_model)
# 将位置编码添加到词嵌入中x =positional_encoding(x)print(x.shape) # 输出的形状应该是[seq_len, batch_size, d_model]

在这段代码中,我们定义了一个`PositionalEncoding`类,它继承自`nn.Module`。这个类的构造函数接受模型的维度`d_model`和最大序列长度`max_len`。在`forward`方法中,我们将位置编码添加到输入的词嵌入张量`x`中。

请注意,这个位置编码是可学习的,但在实际的Transformer模型中,位置编码通常是固定的,不参与训练。这里为了简化,我们将位置编码作为模型的一部分,但在实际应用中,你可能会将位置编码作为一个固定的张量添加到词嵌入中。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ