Transformer中的位置编码详解

什么是位置编码

  1. 位置编码概述 位置编码的目的是为了补充序列的位置信息,这是因为自注意力机制本身不包含位置的概念(例如顺序信息)。位置编码的具体作用是,对于不同的输入序列成分,赋予其不同的位置标识,确保序列信息在不同的上下文中仍然,即使是相同的文本序列也因位置不同而有不同的含义。

Transformers 使用的位置编码方法,其中每个位置/词素都被分配一个编号。到此,位置编码的输出是一个矩阵,其中每行的每一行代表序列中的一个特定词素与其位置信息相结合。下图演示了一个较小的位置编码矩阵示例的构成方式。

位置编码矩阵

位置编码矩阵示例 - 序列 ‘I am a robot’

三角函数 

  1. 三角函数 三角函数是数学中的基本概念,不仅可以表达周期性的现象,还能描述波动的基本特性。这些函数的图像通常在[-1, 1]的区间内。三角函数的一般形式包括正弦和余弦两种,它们的周期性是函数的重要特性。以下表格列出了几种常见的三角函数形式及其特性:

位置编码公式 

位置编码的数学公式用于为每一个位置(即序列中的词素)分配一个独特的编码,以使其能够在不同的上下文中区别对待。位置编码使用下述公式来生成位置编码矩阵:

\begin{aligned}&P(k,2i)=\sin\left(\frac k{n^{2i/d}}\right)\text{(1)}\\&P(k,2i+1)=\cos\left(\frac k{n^{2i/d}}\right)\text{(2)}\end{aligned}

其中:

  • k:词素(即序列中的某个元素)的索引位置的值,0≤k<L/2
  • d:编码矩阵的维度
  • P(k,j):位置编码,用于给定词素 k 的频率编码的 (k, j) 处的值
  • n:用户定义的常数(例如,"Attention Is All You Need" 论文中的常数为 10,000)
  • i:用于确定频率的位置,0≤i<d/2,相当于确定位置编码矩阵中的行

位置编码示例

通过具体例子理解位置编码。以序列 “I am a robot” 为例,设定 n = 100, d = 4。在这个例子中,我们计算了 n = 100 和 d = 4 的序列的位置编码,位置编码的计算结果如下表:

位置编码矩阵示例 - 序列 ‘I am a robot’ 

Python实现位置编码 

使用 NumPy 库进行矩阵和数学运算以及 Matplotlib 库进行图形绘制,下面是 Python 代码示例以及其输出结果。

import numpy as np
import matplotlib.pyplot as plt

def getPositionEncoding(seq_len, d, n=10000):
    P = np.zeros((seq_len, d))
    for k in range(seq_len):
        for i in np.arange(int(d/2)):
            denominator = np.power(n, 2*i/d)
            P[k, 2*i] = np.sin(k/denominator)
            P[k, 2*i+1] = np.cos(k/denominator)
    return P

P = getPositionEncoding(seq_len=4, d=4, n=100)
print(P)

单个序列的可视化 

使用 Matplotlib 库绘制不同位置的三角函数图,下面是 Python 代码示例以及其生成的图形。

import numpy as np
import matplotlib.pyplot as plt

def getPositionEncoding(seq_len, d, n=10000):
    P = np.zeros((seq_len, d))
    for k in range(seq_len):
        for i in np.arange(int(d/2)):
            denominator = np.power(n, 2*i/d)
            P[k, 2*i] = np.sin(k/denominator)
            P[k, 2*i+1] = np.cos(k/denominator)
    return P

def plotSinusoid(k, d, n):
    x = np.arange(0, 100, 1)
    denominator = np.power(n, 2*k/d)
    y = np.sin(x/denominator)
    plt.plot(x, y)
    plt.title('k = ' + str(k))

# 使用长序列和较大维度的参数
seq_len = 100
d = 512
n = 10000
P = getPositionEncoding(seq_len, d, n)
# 正弦波绘图
fig = plt.figure(figsize=(15, 4))
for i in range(4):
    plt.subplot(1, 4, i + 1)
    plotSinusoid(i*4, d, n)  # 确保传入函数的参数和生成P矩阵时的参数一致
plt.show()

下图是四个不同 k 值的正弦波形图。可以看到,随着 k 值的增大,波形周期发生了变化。

可视化结果:四个不同 k 值的正弦波形图,分别对应 k=0, k=4, k=8, 和 k=12 的情况。随着 k 值的增大,波形周期发生变化,显示了不同频率和波长的正弦波。

热图可视化编码矩阵 

使用 Python 的 Matplotlib 库的 matshow() 函数,可以将位置编码矩阵以热图的形式可视化。热图可以直观地展示不同位置编码的值的大小。下面是 Python 代码示例以及热图的输出结果。

# 热图绘图
fig2 = plt.figure(figsize=(15, 4))
cax = plt.matshow(P, aspect='auto')  # aspect='auto'保证热图在x轴和y轴方向拉伸以填满画布
plt.colorbar(cax)
plt.show()

  

热图结果:展示了一个长为 100,宽为 512 的位置编码矩阵的热图。热图中的颜色变化表示不同位置编码值的大小,可以看到随着位置的变化,颜色也呈现出周期性的变化模式。

位置编码的整体流程 

Transformer模型的位置编码过程包括将词汇转换为向量,然后与位置编码相加,以保持位置信息。以下是该过程的详细描述:
 

  • 输入序列(Input sequence): I, am, a, Robot
  • 词向量嵌入(Word embedding): 将每个输入词转换为一个嵌入向量(embedding vector)。
    • v0​ 是 "I" 的嵌入向量
    • v1​ 是 "am" 的嵌入向量
    • v2​ 是 "a" 的嵌入向量
    • v3​ 是 "Robot" 的嵌入向量
  • 位置编码矩阵(Positional Encoding Matrix): 计算序列中每个词的位置编码向量。
    • P0​ 是 "I" 的位置编码向量
    • P1​ 是 "am" 的位置编码向量
    • P2​ 是 "a" 的位置编码向量
    • P3​ 是 "Robot" 的位置编码向量
  • 位置编码层的输出(Output of positional encoding layer): 词向量和位置编码向量相加,得到最终的编码向量。
    • y0​ 是 "I" 的位置编码
    • y1​ 是 "am" 的位置编码
    • y2​ 是 "a" 的位置编码
    • y3​ 是 "Robot" 的位置编码
  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值