1.《Transformer代码复现》： https://blog.csdn.net/dgvv4/article/details/125491693

2.《Transformer中的Encoder机制》： https://blog.csdn.net/dgvv4/article/details/125507206

## 1. Decoder 的 self-attention 中的 mask

#### 下面举一个例子：

encoder的输入:  i love you

decoder的输入:  /f 我 爱 你

```import torch
from torch.nn import functional as F
# ------------------------------------------------------ #
# ------------------------------------------------------ #
# 目标序列中有两个句子，分别包含3、4个单词
tgt_len = torch.Tensor([3,4]).to(torch.int32)
# 目标序列有效单词矩阵 shape=[3,3], shape=[4,4]
tgt_matrix = [torch.ones(L, L) for L in tgt_len]
# 对每个元素全为1句子矩阵构造一个下三角矩阵
tri_matrix = [torch.tril(mat) for mat in tgt_matrix]
# 第一个句子长度为3，生成3*3大小且下三角区域的元素权威1，其余全为0的矩阵
for seq_len, matrix in zip(tgt_len, tri_matrix):  # 遍历每个下三角矩阵mask
matrix = torch.unsqueeze(matrix, dim=0)  # 维度扩充[seq_len,seq_len]==>[1,seq_len,seq_len]
new_tri_matrix.append(matrix)
valid_tri_matrix = torch.cat(new_tri_matrix, dim=0)
invalid_tri_matrix = (1 - valid_tri_matrix).to(torch.bool)
# ------------------------------------------------------ #
# ------------------------------------------------------ #
# 随机初始化一个 Q @ K^T 的计算结果 [batch, tgt_seq_len, tgt_seq_len]
score = torch.randn(2, max(tgt_len), max(tgt_len))
print('原始输入:', score)

```# 有效下三角矩阵mask:
tensor([[[1., 0., 0., 0.],
[1., 1., 0., 0.],
[1., 1., 1., 0.],
[0., 0., 0., 0.]],
[[1., 0., 0., 0.],
[1., 1., 0., 0.],
[1., 1., 1., 0.],
[1., 1., 1., 1.]]])

tensor([[[False,  True,  True,  True],
[False, False,  True,  True],
[False, False, False,  True],
[ True,  True,  True,  True]],
[[False,  True,  True,  True],
[False, False,  True,  True],
[False, False, False,  True],
[False, False, False, False]]])

# 原始输入scorce:
tensor([[[ 0.5266, -0.7873, -0.2481,  0.5554],
[-1.3146,  0.1668, -1.6488, -0.5159],
[-0.1590, -2.1458,  0.0217,  0.4044],
[ 1.0169,  0.8640, -0.9029,  0.5957]],
[[-0.6277,  0.0611, -1.3732, -0.6897],
[-1.3523,  0.6712,  0.0491,  2.2301],
[ 0.4627,  0.1737,  1.0111, -1.4099],
[ 0.1994,  0.2538,  0.5689, -0.2558]]])

tensor([[[ 5.2655e-01, -1.0000e+10, -1.0000e+10, -1.0000e+10],
[-1.3146e+00,  1.6676e-01, -1.0000e+10, -1.0000e+10],
[-1.5899e-01, -2.1458e+00,  2.1674e-02, -1.0000e+10],
[-1.0000e+10, -1.0000e+10, -1.0000e+10, -1.0000e+10]],
[[-6.2770e-01, -1.0000e+10, -1.0000e+10, -1.0000e+10],
[-1.3523e+00,  6.7119e-01, -1.0000e+10, -1.0000e+10],
[ 4.6272e-01,  1.7366e-01,  1.0111e+00, -1.0000e+10],
[ 1.9943e-01,  2.5381e-01,  5.6886e-01, -2.5576e-01]]])```

```# Decoder部分的目标序列对特征序列的muti-head-attention中的mask
import torch
from torch import nn
from torch.nn import functional as F
# ------------------------------------------------------ #
#（1）构造序列
# ------------------------------------------------------ #
src_len = torch.Tensor([2,4]).to(torch.int32)  # 特征序列中有两个句子，分别包含2、4个单词
tgt_len = torch.Tensor([3,5]).to(torch.int32)  # 目标序列中有两个句子，分别包含3、5个单词
# 对序列编码，有效单词位置的元素为1
valid_src_pos = [torch.ones(L) for L in src_len]  # 特征序列 [tensor([1., 1.]), tensor([1., 1., 1., 1.])]
valid_tgt_pos = [torch.ones(L) for L in tgt_len]  # 目标序列 [tensor([1., 1., 1.]), tensor([1., 1., 1., 1., 1.])]
max_src_len = max(src_len)  # 将特征序列的单词数统一成4个
max_tgt_len = max(tgt_len)  # 将目标序列的单词数统一成5个
for sent in valid_src_pos:  # 遍历每个特征句子
sent = torch.unsqueeze(sent, dim=0)  # 维度扩充 [max_src_len]==>[1, max_src_len]
new_valid_pos.append(sent)
for sent in valid_tgt_pos:  # 遍历每个目标句子
sent = torch.unsqueeze(sent, dim=0)  # 维度扩充 [max_tgt_len]==>[1, max_tgt_len]
new_valid_pos.append(sent)
# 前两个句子属于特征序列，后两个句子属于目标序列。将列表类型在axis=0维度上堆叠
valid_src_pos = torch.cat(new_valid_pos[:2], dim=0)  # tensor([[1., 1., 0., 0.], [1., 1., 1., 1.]])
valid_tgt_pos = torch.cat(new_valid_pos[2:], dim=0)  # tensor([[1., 1., 1., 0., 0.], [1., 1., 1., 1., 1.]])
# ------------------------------------------------------ #
# Q @ K^T 的shape为 [batch, tgt_seq_len, src_seq_len]
# ------------------------------------------------------ #
# 有效特征序列[2,4]==>[2,4,1], 有效目标序列[2,5]==>[2,5,1]
valid_src_pos = torch.unsqueeze(valid_src_pos, dim=-1)  # 值为1的元素代表有效单词，值为0的元素代表padding后的区域
valid_tgt_pos = torch.unsqueeze(valid_tgt_pos, dim=-1)
# [b, tgt_seq_len, 1] @ [b, 1, src_seq_len] = [b, tgt_seq_len, src_seq_len]
valid_cross_pos_matrix = torch.bmm(valid_tgt_pos, valid_src_pos.transpose(1,2))
print('有效关系矩阵：', valid_cross_pos_matrix)  # torch.Size([2, 5, 4])
invalid_cross_pos_matrix = 1 - valid_cross_pos_matrix
invalid_cross_pos_matrix = invalid_cross_pos_matrix.to(torch.bool)
print('mask矩阵:', invalid_cross_pos_matrix)  # torch.Size([2, 5, 4])
# ------------------------------------------------------ #
# ------------------------------------------------------ #
# 随机初始化一个 Q @ K^T 的计算结果 [batch, tgt_seq_len, src_seq_len]
score = torch.randn(2, 5, 4)
print('原输入:', score)

```# 有效关系矩阵：
tensor([[[1., 1., 0., 0.],
[1., 1., 0., 0.],
[1., 1., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
tensor([[[False, False,  True,  True],
[False, False,  True,  True],
[False, False,  True,  True],
[ True,  True,  True,  True],
[ True,  True,  True,  True]],
[[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False]]])
# 原输入:
tensor([[[ 1.4030, -0.0176, -2.9678, -0.5551],
[ 2.6138, -0.8088,  0.6641, -0.0128],
[-0.0370, -0.3206, -0.6634,  0.3626],
[ 1.1978,  1.9831, -0.3541, -0.8766],
[ 0.0655,  0.4267, -0.3459,  1.8217]],
[[-0.2351, -1.3515,  0.4783, -0.9379],
[ 0.2302, -1.5482, -0.0825,  1.0711],
[-0.3793, -0.9595,  0.9457, -1.5746],
[ 0.3685,  1.1116, -2.3528, -0.3916],
[-1.2416,  0.9410, -0.5407,  0.8035]]])