文章目录
1. Attention
Attention函数的本质可以描述为:将查询(query)和一组键值(key-value)对映射到输出(output)。
从本质上理解,Attention是从大量信息中筛选出少量重要信息,并聚焦到这些重要信息上,忽略大多不重要的信息。权重越大越聚焦于其对应的Value值上,即权重代表了信息的重要性,而Value是其对应的信息。
2. Self-Attention
而自注意力机制是注意力机制的变体,其减少了对外部信息的依赖,更擅长捕捉数据或特征的内部相关性。具体讲就是,一个序列中的每个词都要和该序列中的所有词进行attention计算,目的是学习序列内部的词依赖关系,捕获句子的内部结构和相关性。这里主要参考Attention is all you need这篇论文中的实现方式进行介绍。
论文中,具体实现的self-attention机制为 Scaled Dot-Product Attention.
自注意力机制计算过程可以归纳为如下步骤:
- 将输入单词转化成嵌入向量表示形式;
- 根据每个词的嵌入向量分别得到q, k, v三个向量;
- 计算score:这里采用点积的计算方式得到value对应的分数 s c o r e = q ⋅ k score = q \cdot k score=q⋅k;
- 为了梯度的稳定,得到分数后,Transformer对每一个权重分数除以 d k \sqrt{d_k} dk;
- softmax激活函数,得到value对应的权重分数;
- 结果与v进行点积,得到每个输入向量的评分v,最后对v进行求和得到最终的输出结果。
实际的计算过程中,q, k, v会以矩阵的形式进行计算,分别对应公式中的Q,K和V。
实现代码如下:
class ScaledDotProductAttention(nn.Module):
def __init__(self):
super (ScaledDotProductAttention, self).__init__()
def forward(self, Q, K, V, attn_mask):
scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) #size:[batch_size, n_heads, len_q, len_k], 这里len_q和len_k相等,为序列长度
scores.masked_fill_(attn_mask, -1e9) #对mask中数值为1的位置,填充数值
attn = nn.Softmax(dim=-1)(scores)
context = torch.matmul(attn, V)
return context, attn
3. Multi-Head Attention
多头注意力机制可以让网络模型关注到来自不同位置的不同表示子空间的信息,
在多头注意力机制中,Q,K,V的形状大小分别为:
Q: [len_q, d_model]
K: [len_k, d_model]
V: [len_k, d_model]
其中设定len_q=len_k,对应序列长度,d_model对应特征维度。
此外,上式中参数 W i Q , W i K , W i V W_i^Q, W_i^K, W_i^V WiQ,WiK,Wi