transformer纯用的attention来做encode和decode架构模型
根据沐神视频所写
编码器
会将一个输入长为n的,编码器会把它表示为一个从 x 1 x_1 x1~ x n x_n xn的东西,假设是一个句子的话, x t x_t xt就是你的第t个词,其中每一个 z t z_t zt是 x t x_t xt向量的一个表示,假设是一个句子的话, z t z_t zt就是你的第t个词的一个向量的表示
解码器
对解码器来讲,会拿到编码器的输出然后生成一个长为m的序列,注意n和m是不一样长的。可以一样,也可以不一样,编码器中,词是一个个生成的(即,自回归,也就是过去时刻的输出也会作为你现在时刻的输入)
注意,解码器在预测第t个时刻的输出的时候,不应该看到第t个时刻以后得输入,实现方法是使用一个带掩码的注意力机制,即mask
自注意力机制
自注意力机制(Self-Attention Mechanism)是一种用于序列数据处理的机制,它允许输入序列中的不同位置之间进行交互,以便为每个位置分配不同的权重,从而更好地捕获序列中的关系。以下是自注意力机制的具体计算过程:
-
准备输入序列: 首先,需要有一个输入序列,该序列通常表示为一个矩阵,其中每行对应于序列中的一个元素,每列对应于元素的特征。
-
计算查询(Query)、键(Key)和值(Value): 对于每个输入元素,需要计算三个向量:查询向量(Q)、键向量(K(可以当做回答))和值向量(V(自身特征))。Q是decoder提供,其他两个是encoder提供。这些向量可以通过线性变换(通常是全连接层)从原始输入获得。这些向量的维度通常相同。output其实是value的一个加权和,所以输出的维度和value的维度是一样的,对于每一个value的权重,是value对应的key和查询query的相似度计算来的,相似度不同的注意力机制有不同的算法。
-
例:假如有三个value和三个不同的key,我们有一个query,这个query和第一个第二个key比较近,那么这个向量新得到的权重就是三个v的加权和,线的粗细代表权重的大小
-
计算注意力分数: 接下来,计算每个查询向量与所有键向量之间的注意力分数。这通常通过点积操作来实现。注意力分数衡量了查询与键的相似性,用于决定在值中分配多少关注度。
对于序列中的每个元素i,其注意力分数计算如下:
Attention_Score ( Q i , K j ) = Q i ⋅ K j d k \text{Attention\_Score}(Q_i, K_j) = \frac{Q_i \cdot K_j}{\sqrt{d_k}} Attention_Score(Qi,Kj)=dkQi⋅Kj
这里, Q i Q_i Qi是查询向量, K j K_j Kj 是第j个键向量, d k d_k dk 是键向量的维度,点积后需要除以 d k \sqrt{d_k} dk(可以理解为向量维度,让结果更平均)进行缩放。
-
计算注意力权重: 使用注意力分数来计算每个元素的注意力权重。通常,可以将注意力分数通过Softmax函数进行归一化,以确保权重的总和为1。
对于序列中的每个元素i,其注意力权重计算如下:
Attention_Weight ( Q i , K j ) = exp ( Attention_Score ( Q i , K j ) ) ∑ j exp ( Attention_Score ( Q i , K j ) ) \text{Attention\_Weight}(Q_i, K_j) = \frac{\exp(\text{Attention\_Score}(Q_i, K_j))}{\sum_{j} \exp(\text{Attention\_Score}(Q_i, K_j))} Attention_Weight(Qi,Kj)=∑jexp(Attention_Score(Qi,Kj))exp(Attention_Score(Qi,Kj))
这里,j 表示所有键的索引。
-
加权平均: 使用计算得到的注意力权重对值向量进行加权平均,以获得最终的输出向量。
对于序列中的每个元素i,其输出向量计算如下:
Output ( i ) = ∑ j Attention_Weight ( Q i , K j ) ⋅ V j \text{Output}(i) = \sum_{j} \text{Attention\_Weight}(Q_i, K_j) \cdot V_j Output(i)=∑jAttention_Weight(Qi,Kj)⋅Vj
这里,j 表示所有键的索引, V j V_j Vj 是第j个值向量。
实际上会把query写成矩阵,也就实现了并行
这时候能看到所有,但是输出的时候不能用后面,把后面的换成大负数,进入softmax就变成0了,相当于没用,这就是mask -
多头自注意力(Multi-Head Self-Attention): 在实际应用中,通常会使用多个自注意力头并行计算,每个头具有不同的参数,以捕获不同类型的关系。最后,多个头的输出将被拼接或合并以形成最终的输出。如图,先投影,即linear,再进行h次计算,再合并,再投影。
自注意力机制的这个计算过程允许模型根据输入序列的不同部分分配不同的关注度,从而更好地捕获序列中的长距离依赖关系和复杂关系,这在自然语言处理等任务中非常有用。这也是自注意力机制在Transformer等深度学习模型中广泛应用的原因之一。
多头注意力机制
可以模拟卷积神经网络多通道的效果,具体如上第六条
架构
左为编码器,右为解码器,解码器的输入其实就是在之前时刻的输出
图中就是layer
文章encoder中说的layer就那n个block中的一个,每个layer又有两个sub-layer,第一个sub-layer就是多头注意力机制,第二个是mlp,对每个子层使用的残差连接
子层公式
LayerNorm(x + Sublayer(x))
输入x进来,先进入子层(无论是自注意力还是mlp)因为是残差,所以把输入输出加在一起,最后进入LayerNorm,残差连接需要输出输出一致,否则要投影,为了简单起见,就把每一层输出维度变成512
可以看到,注意力层输入有三个,并且是一个东西一分为三说明,key,value,query是一个东西,所以是自注意力,假设一个句子长度是n,那输入是一个长为n的向量,也就是有n个query,所以有n个输出
解码器第一个注意力机制输入可能长度与编码器输入不一致,mask有区别其他一样
第二个不再是自注意力,输入key和value来自编码器输出,query来自下面的输入,这就导致key和value跟query长度可能不一样,一个n一个m,其实就是把编码器输出中想要的领过来。
LayerNorm
有一个矩阵,每一行是一个样本
batch-norm做的就是
每次把每一个特征在一个mini-batch里面把它的均值变成0方差变成1,batch-norm还会学一个
λ
,
β
\lambda, \beta
λ,β,也就是这个向量通过学习可以放成任意一个方差为某个值,均值为某个值的一个东西,layernorm和batchnorm几乎是一样的,layernorm是横着,把每个样本变为方差为1均值为0
但是输入一般都是三维,
蓝色是batchnorm,黄色是layernorm,seq样本长度,因为样本长度可能不一样,所以layernorm常用一些,值的波动小
图中的norm也就是指的这个
前向传播
就是只作用于最后一个维度的mlp
简化版架构
其实只有一个MLP,这里的MLP就是前向传播,对每个点独立做
position encoding
增加时序,返回512长度的向量,然后加上词向量
embedding
变为向量,长512的词向量
关于self
我之前其实一直理解错误了,是生成第一个词的时候,q提问,生成第二个词的时候要算上已经生成的第一个词,这才是self
cross
给定角色就算是吧