位置编码是什么?

位置编码是什么?

位置编码是一种将词汇位置信息注入到转换器架构中的技术。

词序对理解语句语义至关重要。例如"Allen 遛狗"与"狗遛 Allen"虽词汇相同,含义却完全迥异。在使用深度学习神经网络实现自然语言处理 (NLP) 应用时,我们需要创建一种使机器保持词序以生成逻辑输出的机制。 

传统上,循环神经网络 (RNN) 或长短期记忆 (LSTM) 等模型具备内置词序处理机制。RNN 和 LSTM 按顺序处理输入,一次处理一个词元,并记住序列中所有词汇位置。换句话说,n 维向量,也称为“输入向量”,被依次处理,这本身就是一种学习顺序。相比之下,其他利用卷积神经网络 (CNN) 或 转换器 (Vaswani 等人,2017 年) 的架构不保留词序,而是并行处理词元。因此,我们需要实现一种能显式表征序列词序的机制——即位置编码技术。位置编码允许转换器保留词序信息,实现并行化和高效模型训练。您可以经常在 GitHub 上找到位置编码的实现案例。  

专家为您带来最新的 AI 趋势

获取有关最重要且最有趣的 AI 新闻的精选洞察分析。订阅我们的每周 Think 时事通讯。请参阅 IBM 隐私声明

谢谢!您已订阅。

您的订阅将以英语提供。您会在每份时事通讯中找到一个取消订阅链接。您可以在此处管理您的订阅或取消订阅。有关更多信息,请参阅我们的 IBM 隐私声明

为什么位置编码很重要?

在自然语言中,句子或语序中的词序决定了句子的内在含义。此外,对于机器学习来说,词序编码可以提供一本“字典”,让我们知道每个单词应该放在哪里。这些信息在整个转换器模型的训练过程中都会被保留和泛化,从而实现了并行化,并在训练效率上超越 RNN 和 LSTM。  

我们再回顾一下这个示例:

  • “Allen 遛狗”
  • “狗遛 Allen”

这两句含相同三个词元的句子因词序不同而意义迥异。转换器依赖于自注意力多头注意力机制,不具有固有的词序表征,如果未提供显式位置信息,会将序列中各词汇同等处理。我们需要模型理解“谁在遛”与"谁被遛”的关系,这完全取决于位置。 

为了实现这一目标,我们首先将每个词处理为表示其含义的矢量,例如,将“狗”编码为一个高维数组,以表示其概念。用专业术语来说,每个词或子词都会映射到不同长度的输入嵌入。然而,意义向量本身并不能告诉我们“狗”在句子中出现的位置。位置编码会添加第二个向量,即对位置索引进行编码的向量,例如“第一个词”或“第二个词”,依此类推。然后将这两个向量相加,表示词是什么以及词在哪里。由此产生的向量通常称为位置编码向量。   

创建位置编码的方法有很多种。在本文中,我们将探讨使用正弦函数的最著名例子,该函数由《Attention is all you need》1作者引入,用于创建位置编码。

Mixture of Experts | 8 月 28 日,第 70 集

解码 AI:每周新闻摘要

加入我们世界级的专家小组——工程师、研究人员、产品负责人等将为您甄别 AI 领域的真知灼见,带来最新的 AI 资讯与深度解析。

转换器中的位置编码

在 Vaswani 等人 2017 年论文的核心思想是,通过正弦波形函数(特别是正弦函数和余弦函数)为序列中的每个位置生成固定且确定的编码 sin(x)  cos(x) .  

什么是正弦波形函数?

正弦函数是产生平滑波长模式的基础数学概念。特别是,作者在原始转换器函数中使用余弦和正弦函数来帮助位置编码。

如果我们绘制 sin(x) 以及 cos(x) 我们将看到一条曲线在 -1 和 1 之间以重复的周期性模式上升和下降。

正弦波的一些特性使其成为位置编码的强大工具: 

  • 它是周期性的:它在间隔内定期重复,适于表征重复模式。

  • 它是 平滑连续的:输入的微小变化会导致输出的微小变化,这为我们提供了一种可微分空间中的位置表征方法。

  • 通过改变不同维度的波长频率,我们可以创建丰富的多尺度位置表征。 

让我们绘制正弦波和余弦波,直观地了解它们的外观:

import numpy as np 
import matplotlib.pyplot as plt 

# Create an array of 100 x values evenly spaced from 0 to 2π (approx 6.28)
x = np.linspace(0, 2 * np.pi, 100) 

# Compute the sine and cosine of each x value 
sin_values = np.sin(x) 

# Create the plot 
plt.figure(figsize=(5, 2)) 
plt.plot(x, sin_values, label='sin(x)', color='blue') 

# Customize the plot 
plt.title('Sine Function') 
plt.xlabel('x') 
plt.ylabel('Function value') 
plt.axhline(0, color='black', linewidth=0.5) # horizontal line at y=0 
plt.axvline(0, color='black', linewidth=0.5) # vertical line at x=0 
#plt.grid(True, linestyle='--', alpha=0.5) 
plt.legend() 
plt.tight_layout() 

# Show the plot 
plt.show() 

正弦函数

正弦函数图,一条有正负范围的重复曲线。

现在我们来看看如何绘制余弦函数图:

#apply the cosine function to the same array, x
cosine = np.cos(x) 

plt.figure(figsize = (5,2)) 
plt.plot(x, cosine, label = 'cos(x)', color = 'blue') 
plt.title('The Cosine Function') 
plt.xlabel('x') 
plt.ylabel('Function value') 
plt.axhline(0, color='black', linewidth=0.5) # horizontal line at y=0 
plt.axvline(0, color='black', linewidth=0.5) # vertical line at x=0 
#plt.grid(True, linestyle='--', alpha=0.5) 
plt.legend() 
plt.tight_layout() 
余弦函数图,说明其周期性和主要特征。

由原始转换器论文作者(Vaswani 等人,2017 年)定义的正弦位置编码公式如下所示:

偶数位置:

 PEpos,2i=sin(pos100002i/dmodel) 

奇数位置:

 PEpos,2i+1=cos(pos100002i/dmodel) 

  •  k :词汇在句中的位置(如首词为 0,次词为 1,依此类推。)

  •  i :嵌入向量的维度索引。映射到列索引。2i 表示偶数位置,2i+1 表示奇数位置

  •  dmodel :预定义的词元嵌入维度(如 512)

  •  n :用户定义的标量值(如 10000)

  •  PE :位置函数,将输入序列中位置 k 映射为位置编码的函数

     

 

通过此公式,每个位于 k 位置的词汇将获得基于其位置的嵌入值。以所使用的“Allen 遛狗”为例,我们可以计算各单词的位置嵌入:

-  k1 = "Allen"

-  k2 = "walks"

-  k3 ="dog"

让我们编写一个简单的 Python 函数来计算以下值: PE(k) :

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 

我们调用该函数并输入示例中的相应值后,序列长度为 3,简化维度为 d=4 ,和   n=10000 

P = getPositionEncoding(seq_len=3, d=4, n=10000) 

print(P) 

我们得到如下编码矩阵(也称为张量):

[[ 0.                      1.                      0.                       1.        ]

 [ 0.84147098  0.54030231  0.09983342  0.99500417]

 [ 0.90929743 -0.41614684  0.19866933  0.98006658]]

为了更具体地表示此结果,我们得到

词汇位置Dim 0
sin(pos ÷ 10000^(0 ÷ 4))
Dim 1
cos(pos ÷ 10000^(0 ÷ 4))
Dim 2
sin(pos ÷ 10000^(2 ÷ 4))
Dim 3
cos(pos ÷ 10000^(2 ÷ 4))
“Allen” k = 00.00000.00000.00001.0000
“walks” k = 10.8414710.5403020.0100000.999950
“dog” k = 20.909297-0.4161470.0200000.999800

此处可见各词汇及其对应位置嵌入的具体数值。然而,我们不能直接使用这些词嵌入来解读词序。计算所得值用于向转换器输入向量注入位置信息。由于输入 sin(x)  以及 cos(x) 不同,每个位置  k 将对应不同正弦函数。不同正弦函数的相应位置为我们提供了有关“Allen 遛狗”中词汇的绝对位置与相对位置信息。换句话说,模型可以利用这些信息,学会将这些模式与顺序、间距和结构联系起来。 

现在,让我们执行一个 python 函数,将位置矩阵可视化

import numpy as np 

import matplotlib.pyplot as plt 

  

def get_position_encoding(seq_len, d_model, n=10000): 

    P = np.zeros((seq_len, d_model)) 

    for pos in range(seq_len): 

        for i in range(d_model): 

            angle = pos / np.power(n, (2 * (i // 2)) / d_model) 

            P[pos, i] = np.sin(angle) if i % 2 == 0 else np.cos(angle) 

    return P 

  

# Parameters 

seq_len = 100   # Number of tokens 

d_model = 512   # Embedding dimensions 

  

# Generate positional encoding 

P = get_position_encoding(seq_len, d_model) 

  

# Plot 

plt.figure(figsize=(10, 6)) 

cax = plt.matshow(P, cmap='viridis', aspect='auto') 

plt.title("Sinusoidal Positional Encoding Heatmap") 

plt.xlabel("Embedding Dimension") 

plt.ylabel("Token Position") 

plt.colorbar(cax) 

plt.tight_layout() 

plt.show() 
正弦热图

最后的思考

我们可以看到,频率因 x 的值而异,输入词汇 k 的每个对应位置的差异范围为 [-1.1] —函数范围 sin(x) 。在此基础上,我们基于编码器和解码器的 转换器模型将学习并保留各词汇的不同位置编码,使模型能够保留信息用于训练。编码位置向量在训练过程中保持静态,从而实现并行计算。

相关解决方案
IBM watsonx.ai

使用面向 AI 构建器的新一代企业级开发平台 IBM watsonx.ai,可以训练、验证、调整和部署生成式 AI、基础模型和机器学习功能。使用一小部分数据,即可在很短的时间内构建 AI 应用程序。

了解 watsonx.ai
人工智能 (AI) 解决方案

借助 IBM 业界领先的人工智能专业知识和解决方案组合,让人工智能在您的业务中发挥作用。

深入了解 AI 解决方案
AI 咨询与服务

通过增加 AI 重塑关键工作流程和运营,最大限度提升体验、实时决策和商业价值。

深入了解人工智能服务
采取后续步骤

一站式访问跨越 AI 开发生命周期的功能。利用用户友好型界面、工作流并访问行业标准 API 和 SDK,生成功能强大的 AI 解决方案。

深入了解 watsonx.ai 预约实时演示
脚注

1. “Attention Is All You Need”, Ashish Vaswani et al., Proceedings of the 31st International Conference on Neural Information Processing Systems, arXiv:1706.03762v7, 2023年8月2日修订。

2. “Long Short-Term Memories”, Sepp Hochreiter and Jürgen Schmidhuber. 1997. Long Short-Term Memory. Neural Comput. 9, 8 (November 15, 1997), 1735–1780., 

3. “Foundations of Recurrent Neural Networks (RNNs) and Long Short-Term Memories” Alex Sherstinsky et al., Elsevier “Physica D: Nonlinear Phenomena” journal, Volume 404, March 2020: Special Issue on Machine Learning and Dynamical Systems