赞
踩
Transformer模型自2017年提出以来,已经彻底改变了自然语言处理(NLP)领域。与传统的循环神经网络(RNN)和长短期记忆网络(LSTM)不同,Transformer完全依赖于注意力机制来处理序列数据,这使得它在处理长文本时更加高效和准确。然而,注意力机制本身不考虑序列中元素的位置,这就需要一个额外的组件来引入这种顺序信息——位置编码。
位置编码的目的是向模型提供每个词在序列中位置的信息,这对于理解语言结构和意义至关重要。在没有位置信息的情况下,模型将无法区分“John loves Mary”和“Mary loves John”之间的差异,因为仅从词的角度看,这两个句子是相同的。位置编码通过向每个词的嵌入向量添加唯一的位置向量来解决这个问题,确保即使是相同的词,在不同位置时它们的表示也是不同的。
位置编码通过向模型提供关于序列中每个元素位置的信息,使得基于注意力的架构能够有效地处理语言等顺序数据。
Transformer模型中使用的位置编码是通过一组正弦和余弦函数生成的,这些函数具有不同的频率。对于每个维度,位置
的编码由以下公式给出:
其中,是词汇在序列中的位置,
是维度的索引,而
是模型中嵌入向量的维度。这种编码方式的选择是为了让模型能够通过位置编码来学习和利用位置信息。正弦和余弦函数被选用是因为它们能够在整个模型中提供连续的、相对的位置信号,且对于任何固定的偏移
,
可以被表示为
的线性函数,这使得模型能够很好地学习到位置间的相对关系。
在实际应用中,位置编码通过简单地将它们加到输入嵌入向量上来应用。这个操作使得每个词的最终向量既包含了它的语义信息(来自词嵌入),也包含了它在序列中位置的信息(来自位置编码),为模型提供了处理序列任务所需的全部必要信息。
下面通过一段代码,演示了如何生成位置编码,并进行可视化输出,直观地理解不同位置的编码是如何变化的。
- import numpy as np
- import matplotlib.pyplot as plt
-
-
- # 根据给定的最大序列长度和嵌入维度生成位置编码。
- def get_positional_encoding(max_seq_len, embed_size):
- positional_encoding = np.array([
- [pos / np.power(10000, 2 * (i // 2) / embed_size) for i in range(embed_size)]
- for pos in range(max_seq_len)])
- positional_encoding[:, 0::2] = np.sin(positional_encoding[:, 0::2]) # 偶数索引列
- positional_encoding[:, 1::2] = np.cos(positional_encoding[:, 1::2]) # 奇数索引列
-
- # 添加批次维度(Batch size)
- positional_encoding = positional_encoding[np.newaxis, ...]
-
- return positional_encoding
-
-
- if __name__ == '__main__':
- # 参数设置
- max_seq_len = 100 # 序列的最大长度
- embed_size = 512 # 嵌入向量的维度
-
- # 生成位置编码
- pos_encoding = get_positional_encoding(max_seq_len, embed_size)
- plt.figure(figsize=(10, 10))
- plt.imshow(pos_encoding[0], cmap='coolwarm')
- plt.title("Positional Encoding")
- plt.xlabel("Embedding Dimensions")
- plt.ylabel("Sequence Position")
- plt.colorbar()
- plt.show()
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
运行结果:![]()
Positional Encoding(位置编码)和Embedding(嵌入)在初学阶段,我一度将这两者混淆。虽然两者都是在处理自然语言处理(NLP)任务时使用的技术,尤其是在Transformer模型中,但服务于不同的目的,并通过不同的方式影响模型的理解和生成文本的能力。
1. 定义与目的:Embedding是一种将离散变量(如单词、字符或标签)映射到连续向量空间的技术。在自然语言处理中,词嵌入将单词转换为固定长度的稠密向量,这些向量能够捕获单词的语义信息和上下文关系。嵌入的主要目的是将文本数据转化为模型可以处理的数值形式,同时保留和传达单词之间的语义关系。
2. 工作原理:通常,词嵌入是通过训练得到的,例如使用Word2Vec、GloVe或直接在模型(如Transformer)中作为参数训练。每个单词都被映射到高维空间中的一个点,相似的单词在这个空间中彼此接近。Transformer中,embedding步骤如下:
词嵌入矩阵:,其中
是词汇表的大小,是嵌入维度。
词汇索引:给定一个词汇,首先将其转换为一个唯一的索引,
。
向量查找:嵌入向量是通过从嵌入矩阵
中查找索引为
的行得到的:
虽然嵌入过程的直接操作是简单的索引查找,但背后的嵌入矩阵是通过优化过程学习得到的。对于给定的NLP任务,模型会通过反向传播和梯度下降等优化算法调整
中的值,以最小化任务的损失函数。在学习过程中,模型会尝试将语义相似或功能相似的词汇映射到嵌入空间中相近的点。
3. 例子:词汇表大小为,目标嵌入维度为
。对于词汇"cat",假设它在词汇表中的索引为
。"cat"的嵌入向量
就是嵌入矩阵
中第150行的向量。
1. 定义与目的:Positional Encoding是一种向模型提供每个单词在句子中位置信息的技术。由于Transformer模型基于自注意力机制,缺乏处理序列数据时天然的顺序感知能力,位置编码确保了模型能够考虑到单词的顺序,这对于理解文本结构和生成连贯文本至关重要。
2. 工作原理:位置编码通常通过为每个位置生成一个唯一的向量,并将这个向量加到对应位置的词嵌入向量上,来实现。Transformer模型中使用的是一种固定的、基于正弦和余弦函数的编码方案,该方案允许模型捕获单词间的相对和绝对位置关系。
3. 代码示例:现在,我们将为序列中的两个位置( 和
)计算位置编码
- import numpy as np
-
-
- if __name__ == '__main__':
- # 定义序列长度L和嵌入维度D
- L, D = 2, 4
-
- # 初始化位置编码矩阵
- PE = np.zeros((L, D))
-
- # 计算位置编码
- for pos in range(L):
- for i in range(D // 2):
- div_term = np.exp(i * -np.log(10000.0) / (D // 2))
- PE[pos, 2 * i] = np.sin(pos * div_term)
- PE[pos, 2 * i + 1] = np.cos(pos * div_term)
-
- print(f'位置编码矩阵:\n{PE}')
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
位置编码矩阵:
[[0. 1. 0. 1. ]
[0.84147098 0.54030231 0.00999983 0.99995 ]]
1. 作用对象:Embedding针对的是单词本身的表示,旨在捕获和表达单词的语义信息;而Positional Encoding关注的是单词在句子中的位置信息。
2. 目的和功能:词嵌入使模型能够理解单词和它们之间的语义关系,Positional Encoding则使模型能够理解单词的顺序和位置关系。
3. 实现方法:词嵌入通常是通过学习得到的,可以是预训练的(如使用Word2Vec或GloVe)或在特定任务中与模型一起训练得到;而位置编码可以是固定的(如Transformer中的正弦余弦编码)或通过模型学习得到。
位置编码是Transformer模型理解序列数据的一个关键组成部分。通过向模型提供关于序列中每个元素位置的信息,位置编码使得基于注意力的架构能够有效地处理语言等顺序数据。尽管其设计简单,位置编码却极大地增强了Transformer模型的能力,使其在多个自然语言处理任务中取得了前所未有的成功。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。