Transformer的PE(position embedding),即位置编码理解

背景:

最近要搞理论学习了,先前搞了大半年的工程,又要捡起一些理论原理,现在还是从transformer熟悉理解一下,争取吃透。
关于transformer的经典介绍和资料也一大堆,我就不展开来讲了,碰到了一些一时没太想明白的问题,就记一下,也当是重新理解一遍。

在这里插入图片描述
transformer的输入要么是词向量或是块状处理了的图像,分别用于自然语言处理和计算机视觉领域。
在自然语言处理中,原始的输入肯定是某种文字形式的语言,但是要送进机器处理要先进行编码,一般有word2vec等方式转化为词向量。

词向量之间需要有一个相对位置关系,如果全部不分序输入那处理肯定不方便,不同词之间组合意思也会发生变化,于是就要给词向量加位置信息。

普通的加一个位置信息,词量大时不利于计算,于是transformer里面用了一种位置编码方式,把位置信息作为词向量的一部分输入信息一起送入网络进行处理,而且获得了不错的效果,一开始位置编码也没太看明白,多看了一些资料后也有一些大致了解。

Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。
在这里插入图片描述
这是位置向量函数的定义,经过多番解读,我现在的理解是:

1、表示方法:

假设某种语言的每个单词都可以嵌入成254个长度的向量,即一个单词的长度是254,

假设单词嵌入并且组成batch后,shape为(b,N,254),N是序列最大长度,即最长的一句话包含的单词个数为N,254是每个单词的嵌入向量长度,b是batch,为了便于组成batch(不同训练句子单词个数肯定不一样)进行训练,可以简单统计所有训练句子的单词个数,取最大即可,假设统计后发现待翻译句子最长是10个单词,那么编码器输入是10x254,batch为1 则输入维度是(1,10,254).

因为位置向量长度要和词向量相加,需要长度保持一致,所以位置向量的维度为(1,N,254),N表示N个单词对应的N个位置,每个位置采用254长度向量进行表示。
在这里插入图片描述

2、transformer采用sin-cos函数进行表示:

在这里插入图片描述
其中,pos对应N,范围是0~N,表示词向量长度为N的某个单词的位置
i 表示某个单词的表示向量的最小单位的位置,范围是0-253;d表示长度单词词向量长度的最大值,即254

进行单词表示时,把表示向量的最小单位按位置进行划分,偶数用sin表示,奇数用cos表示,按照位置顺序进行拼接

在这里插入图片描述
如上图,纵向是position,表示一个句子的长度,此处是50,说明该句子包含50个单词,即上面的N;
横向表示每个单词的词向量长度,此处是128,即上文的254. 另1/50的横向条表示一个单词,图中画了3条,对应3个单词。

下面几幅图同理:
在这里插入图片描述
在这里插入图片描述

附上几个有帮助的链接以供参考,是查找过程觉得比较有用的:
https://zhuanlan.zhihu.com/p/338817680
https://zhuanlan.zhihu.com/p/308301901
https://kazemnejad.com/blog/transformer_architecture_positional_encoding/
http://jalammar.github.io/illustrated-transformer/

Transformerembedding部分可以通过以下步骤实现: 1. 首先,将输入序列进行编码。这可以通过将输入序列中的每个元素映射到一个低维的向量表示来完成。常用的方法是使用一个可学习的嵌入层(embedding layer)来实现这一点。 2. 接下来,为输入序列中的每个位置添加位置编码位置编码是一个向量,用于表示输入序列中每个位置的相对位置信息。常用的方法是使用正弦和余弦函数来生成位置编码。 3. 然后,将编码后的输入序列输入到Transformer的多层自注意力机制(multi-head self-attention)中。自注意力机制可以捕捉输入序列中不同位置之间的依赖关系。 4. 在自注意力机制的输出上应用前馈神经网络(feed-forward neural network)进行特征提取和维度变换。 5. 最后,将经过特征提取的输出序列进行池化操作,得到一个固定长度的向量表示。这个向量表示可以用作分类任务的输入。 下面是一个示例代码,演示了如何在Transformer中进行embedding: ```python import torch import torch.nn as nn class TransformerEmbedding(nn.Module): def __init__(self, input_dim, hidden_dim, num_layers, num_heads): super(TransformerEmbedding, self).__init__() self.embedding = nn.Embedding(input_dim, hidden_dim) self.position_encoding = PositionalEncoding(hidden_dim) self.transformer = Transformer(hidden_dim, num_layers, num_heads) self.pooling = nn.AdaptiveAvgPool1d(1) def forward(self, x): embedded = self.embedding(x) encoded = self.position_encoding(embedded) transformed = self.transformer(encoded) pooled = self.pooling(transformed.permute(0, 2, 1)) return pooled.squeeze(2) class PositionalEncoding(nn.Module): def __init__(self, hidden_dim, max_len=5000): super(PositionalEncoding, self).__init__() self.dropout = nn.Dropout(p=0.1) pe = torch.zeros(max_len, hidden_dim) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, hidden_dim, 2).float() * (-math.log(10000.0) / hidden_dim)) 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) def forward(self, x): x = x + self.pe[:x.size(0), :] return self.dropout(x) class Transformer(nn.Module): def __init__(self, hidden_dim, num_layers, num_heads): super(Transformer, self).__init__() self.layers = nn.ModuleList([TransformerLayer(hidden_dim, num_heads) for _ in range(num_layers)]) def forward(self, x): for layer in self.layers: x = layer(x) return x class TransformerLayer(nn.Module): def __init__(self, hidden_dim, num_heads): super(TransformerLayer, self).__init__() self.self_attention = nn.MultiheadAttention(hidden_dim, num_heads) self.feed_forward = nn.Sequential( nn.Linear(hidden_dim, hidden_dim * 4), nn.ReLU(), nn.Linear(hidden_dim * 4, hidden_dim) ) self.layer_norm1 = nn.LayerNorm(hidden_dim) self.layer_norm2 = nn.LayerNorm(hidden_dim) def forward(self, x): attended, _ = self.self_attention(x, x, x) x = x + attended x = self.layer_norm1(x) fed_forward = self.feed_forward(x) x = x + fed_forward x = self.layer_norm2(x) return x ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清梦枕星河~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值