|
|
|
@ -16,7 +16,7 @@ WHAT:位置编码是一种向模型输入的每个单词嵌入向量中添加
|
|
|
|
|
|
|
|
|
|
如何设计我们需要考虑几个问题:
|
|
|
|
|
|
|
|
|
|
1. 如果是用整些数值表示,推理时可能会遇到比训练时还要长的序列;而且随着序列长度的增加,位置值会越来越大。
|
|
|
|
|
1. 如果是用整数数值表示,推理时可能会遇到比训练时还要长的序列;而且随着序列长度的增加,位置值会越来越大。
|
|
|
|
|
2. 如果用[-1,+1]之间进行表示,要解决序列长度不同时,能表示token在序列中的绝对位置;而且在序列长度不同时,也要在不同序列中token的相对位置/距离保持一致。
|
|
|
|
|
|
|
|
|
|
所以我们希望:
|
|
|
|
@ -28,7 +28,7 @@ WHAT:位置编码是一种向模型输入的每个单词嵌入向量中添加
|
|
|
|
|
|
|
|
|
|
### 位置编码是怎么算的?
|
|
|
|
|
|
|
|
|
|
在《Attention is all you need》中,位置编码是有正弦和余弦函数计算出来的,且是固定的。
|
|
|
|
|
在《Attention is all you need》中,位置编码是通过正弦和余弦函数计算出来的,且是固定的。
|
|
|
|
|
|
|
|
|
|
优点:
|
|
|
|
|
|
|
|
|
@ -49,6 +49,7 @@ GPT-2的位置编码是可学习的参数。这意味着模型在训练过程中
|
|
|
|
|
### Transformer里的位置编码方法(原文)
|
|
|
|
|
|
|
|
|
|
~~~python
|
|
|
|
|
import torch
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
|
|
def get_positional_encoding(max_seq_len, d_model):
|
|
|
|
@ -99,7 +100,7 @@ tensor([-1.0000, 0.0044, -0.9673, -0.2535, -0.8724, -0.4889, -0.7253, -0.6884,
|
|
|
|
|
|
|
|
|
|
<img src="../assets/image-20240427180954246.png" alt="image-20240427180954246" width="550" />
|
|
|
|
|
|
|
|
|
|
为什么是用正弦和余弦函数,对于正弦函(sin):最大值是 +1,最小值是 -1。对于余弦函数(cos):最大值是 +1,最小值是 -1。也就是它们可以保证值是比较小的,而且也是符合深度学习模型可学习的参数。
|
|
|
|
|
为什么是用正弦和余弦函数,对于正弦函数(sin):最大值是 +1,最小值是 -1。对于余弦函数(cos):最大值是 +1,最小值是 -1。也就是它们可以保证值是比较小的,而且也是符合深度学习模型可学习的参数。
|
|
|
|
|
|
|
|
|
|
其中最重要的是允许模型学习相对位置:由于正弦和余弦函数的周期性(且是不同周期),对于任意固定偏移量 `k`,`PE(pos+k)`可以表示为 `PE(pos)` 的线性函数。这意味着模型可以很容易地通过学习注意力权重来关注相对位置,因为相对位置的编码可以通过简单的线性变换来获得。即我知道了绝对距离,也能知道相对距离。
|
|
|
|
|
|
|
|
|
@ -234,7 +235,7 @@ torch.Size([1, 4, 768])
|
|
|
|
|
|
|
|
|
|
<img src="../assets/image-20240427182734627.png" alt="image-20240427182734627" width="550" />
|
|
|
|
|
|
|
|
|
|
从代码来看,embedding跟position_embeddings就是同位置元素相加。以下面的方法来检验
|
|
|
|
|
从代码来看,embeddings跟position_embeddings就是同位置元素相加。以下面的方法来检验
|
|
|
|
|
|
|
|
|
|
~~~python
|
|
|
|
|
print(final_embeddings[0][0][0])
|
|
|
|
@ -260,7 +261,7 @@ tensor(-0.1923, grad_fn=<AddBackward0>)
|
|
|
|
|
|
|
|
|
|
聪明的你会注意到,位置编码跟向量是相加的,既然相加是不是意味着最终模型也分辨不出里面的位置信息呢?为什么不是用concat进行拼接,单独的数值来表示位置。
|
|
|
|
|
|
|
|
|
|
首先,拼接会让维度再度翻倍,其次,多头注意力里的QKV矩阵是线形变换,本质上也是将位置编码和向量进行类型的加工,作者把这个称为隐式拼接(concat)。但我觉得,最大的可能性就是模型效果好。这也可能是为什么GPT-2不使用正弦和余弦生成位置编码,而是直接用模型训练。
|
|
|
|
|
首先,拼接会让维度再度翻倍,其次,多头注意力里的QKV矩阵是线性变换,本质上也是将位置编码和向量进行类型的加工,这可以被视为一种隐式的拼接(concat)。但我觉得,最大的可能性就是模型效果好。这也可能是为什么GPT-2不使用正弦和余弦生成位置编码,而是直接用模型训练。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -268,4 +269,4 @@ tensor(-0.1923, grad_fn=<AddBackward0>)
|
|
|
|
|
|
|
|
|
|
位置编码使得模型能够理解单词在句子中的位置,从而更好地处理自然语言。无论是通过正弦和余弦函数的固定公式,还是通过可学习的参数,位置编码都为模型提供了理解文本所必需的结构信息。
|
|
|
|
|
|
|
|
|
|
且个人认为最重要的是在并行化的路上,走的更深了。那些鬼才们为了达到目的可以把每个部分进行拆解选择最优的同时,还能让各个模块联合到一起去达到他们想要的目的。
|
|
|
|
|
个人认为最重要的是不管做什么,都考虑了并行化。那些鬼才们为了达到目的可以把每个部分进行拆解选择最优的同时,还能让各个模块联合到一起去达到他们想要的目的。
|