TR5 - Transformer的位置编码



前言

在NLP任务中,单词的序列顺序是非常重要的,将单词的顺序重新排列,整个句子的意思可能会发生改变。在RNN循环神经网络中,有着处理序列顺序的内置机制。Transformer通过引入位置编码机制来保存文本中字符的位置信息。

什么是位置编码

1. 定义

位置编码记录了文本中字符的位置信息,它并没有使用单个数字(例如索引值)的形式来记录位置信息。原因主要有:

  1. 对于长序列,索引的大小可能会变得很大,不利于存储。
  2. 将索引值规范化到0-1之间,可能会为可变长度序列带来问题(它们的标准化方式不同)。

Transformer使用智能位置编码方案,第个位置/索引都映射到了一个向量,所以位置编码层的输出明天是一个矩阵,其中矩阵的每一行代表序列中的一个编码对象与其位置信息相加。
将位置信息映射成向量

2. 三角函数

正弦函数的值域为[-1, 1],可以等效地使用正弦函数或余弦函数。
正弦、余弦波形

3. 位置编码公式

假设你有一个长度为L的输入序列,要计算第K个元素的位置编码,可以由不同频率的正弦和余弦函数给出:

P ( k , 2 i ) = s i n ( k n 2 i / d ) P(k, 2i) = sin(\frac k {n^{2i/d}}) P(k,2i)=sin(n2i/dk)

P ( k , 2 i + 1 ) = c o s ( k n 2 i / d ) P(k, 2i + 1) = cos(\frac k {n^{2i/d}}) P(k,2i+1)=cos(n2i/dk)

参数详解:

  • k k k: 对象(也就是句子中的字符)在输入序列中的位置, 0 < = k < L / 2 0<=k<L/2 0<=k<L/2
  • d d d: 输出嵌入空间的维度
  • P ( k , j ) P(k,j) P(k,j): 位置函数,用于映射输入序列中k处的元素到位置矩阵的 ( k , j ) (k, j) (k,j)
  • n n n: 用户定义的标量(论文中作者设置的是10000)
  • i i i: 用于映射到列索引, 0 < = i < d / 2 0<=i<d/2 0<=i<d/2,单个值i映射到正弦和余弦函数

4. 位置编码示例

以"I am a robot"为例,并且设置n=100, d=4,下面是过程,注意仅是位置编码,所以和具体的字符是无关的。使用"You are a doctor"计算完会得到一样的结果。
位置编码示例

可视化理解位置编码

1. 代码实现

import numpy as np
import matplotlib.pyplot as plt

def getPositionalEncoding(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 = getPositionalEncoding(4, 4)
print(P)

打印结果

[[ 0.          1.          0.          1.        ]
 [ 0.84147098  0.54030231  0.00999983  0.99995   ]
 [ 0.90929743 -0.41614684  0.01999867  0.99980001]
 [ 0.14112001 -0.9899925   0.0299955   0.99955003]]

2. 观察不同位置对应的曲线

我们把d和n固定,只改变位置参数k,然后画出不同k对应的图像,观察他们之间的区别

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

fig = plt.figure(figsize=(15, 4))
for i in range(4):
	plt.subplot(1, 4, i + 1)
	plotSinusoid(i*4)

不同位置对应的函数曲线
从图中可以看出,每个位置的曲线都不相同,并且当 i i i固定时,对应的波长为

λ i = 2 π n 2 i / d \lambda_i = 2 \pi n^{2i/d} λi=2πn2i/d

因此,正弦曲线的波长形成几何函数。位置编码方案具有许多优点:

  • 正弦和余弦函数的值在[-1,1]内,这使位置编码矩阵的值保持在归一化范围内
  • 由于每个位置的正弦曲线都不同,因此你可以采用独特的方式对每个位置进行编码
  • 有一种方法可以测量或量化不同位置之间的相似性,从而使你能够对单词的相对位置进行编码

3. 整句话的位置编码可视化

P = getPositionalEncoding(100, 512)
cax = plt.matshow(P)
plt.gcf().colorbar(cax)

整句话的位置编码
transformer中的位置编码层把位置向量和单词编码相加,并输入到后续的层。
位置向量的流动

总结与心得体会

之前看过一些资料说Transformer中的位置编码,但是没有直观的概念一直只停留在利用正弦和余弦曲线进行编码。经过本次学习对编码的过程和原理有了一个形象的概念。通过对位置编码的学习,我感觉它很像傅里叶变换中的一些东西,所以虽然已经身处于深度学习阶段,传统的机器学习方法,甚至是基本的数学方法,仍然能提供一些思路,并解决一些问题,并不能放松对传统方法的学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值