transformer

参考资料

https://github.com/wmathor/nlp-tutorial
https://blog.csdn.net/qq_37236745/article/details/107352167
https://blog.csdn.net/weixin_45782047/article/details/123016062
https://www.bilibili.com/video/BV1pu411o7BE/
https://www.bilibili.com/video/BV12L4y157MS/

整体架构及代码结构

在这里插入图片描述

  1. 初始化参数
  2. 构建数据集
  3. 位置编码
  4. pad_mask 和 seq_mask
  5. self-attention
  6. multihead-attention
  7. ffn:两层的mlp
  8. encoder-layer 和 decoder-layer
  9. encoder 和 decoder
  10. transformer
  11. train 和 test

流程分析(endoder)

Inputs:将输入的句子通过词表映射成[batch_size, src_len]大小的tensor

Input Embedding:输出[batch_size, src_len, d_model]大小的tensor,将每个单词用d_model维度的向量表示

Positional Embedding:输出[batch_size, src_len, d_model]大小的tensor,为每个单词加上位置编码

Multi-Head Attention:重点理解Attention、Mask、Multi-Head三部分
关于Scaled Dot-Product Attention:
对以上tensor做线性变换(即分别*Wk,Wv,Wq,大小均为[d_model, d_model]),得到三个箭头从左到右分别输入矩阵K(键矩阵),V(值矩阵),Q(查询矩阵),大小分别为

Q: [batch_size, n_heads, len_q, d_k]
K: [batch_size, n_heads, len_k, d_k]
V: [batch_size, n_heads, len_v(=len_k), d_v]
# Q和K要做内积,维度相同;K和V的len相同

在这里插入图片描述

关于Padding mask:

# 调用顺序
#1.Encoder中 enc_self_attn_mask: [batch_size, src_len, src_len]
enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs) 
#get_attn_pad_mask中 
pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # 留下seq_k即enc_inputs等于0的坐标
#对于每层Layer enc_self_attn: [batch_size, n_heads, src_len, src_len]
self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])
enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)

#2.EncoderLayer中 enc_outputs: [batch_size, src_len, d_model], attn: [batch_size, n_heads, src_len, src_len]
self.enc_self_attn = MultiHeadAttention()
enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask)

#3.Multi-Head中 attn_mask: [batch_size, n_heads, seq_len, seq_len]
def forward(self, input_Q, input_K, input_V, attn_mask):
    attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1)
	context, attn = ScaledDotProductAttention()(Q, K, V, attn_mask)
    
#4.ScaledDotProduct中 scores: [batch_size, n_heads, len_q, len_k]
scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k)
scores.masked_fill_(attn_mask, -1e9) #用-1e9填充attn_mask为true的位置

效果如下图,
在这里插入图片描述
关于Multi-Head:每个注意力机制去优化每个词汇的不同特征部分,使得词义多元化

#Multi-Head中 input_Q: [batch_size, len_q, d_model],Q: [batch_size, n_heads, len_q, d_k]
self.W_Q = nn.Linear(d_model, d_k * n_heads, bias=False)
Q = self.W_Q(input_Q).view(batch_size, -1, n_heads, d_k).transpose(1,2)# 这里的view相当于numpy中resize的作用,而-1,表示根据其他维度自动补齐向量维度

#这里是将多头的计算结果合并,实际上Multi-Head操作使得d_model-->d_k * n_heads-->n_heads * d_v,对应代码是将张量多分出一个维度再减少一个维度
context, attn = ScaledDotProductAttention()(Q, K, V, attn_mask)
context = context.transpose(1, 2).reshape(batch_size, -1, n_heads * d_v) # context: [batch_size, len_q, n_heads * d_v]

在这里插入图片描述

Add & Norm:
在这里插入图片描述
在这里插入图片描述

与decoder的区别

1.在softmax之前,需要将得到的attention score做mask处理
在这里插入图片描述

2.在cross-attention层,矩阵K(键矩阵),V(值矩阵)来自encoder的输出,Q(查询矩阵)来自decoder

总结

在这里插入图片描述

更多推荐