核心内容摘要
当漫画遇见师道:用画笔勾勒“老师的亲密指导”
querys 是2*6*2keys也是2*6*2attn_scoresquerys keys.transpose(1,
attn_scores 最终维度是 2×6×6数值上是两个矩阵的批量矩阵乘法结果每个样本对应一个 6×6 的注意力分数矩阵transpose(1,
交换 keys 的第 1 维和第 2 维keys 原始维度[2, 6, 2] → 交换后[2, 2, 6]第一个位置批维度不变PyTorch 中是批量矩阵乘法规则对于维度为 [B, M, N] 的张量 A 和 [B, N, P] 的张量 BAB 的结果维度是 [B, M, P]B 是批次保持不变M×N 乘 N×P 得到 M×Pimporttorch#
构造querys和keys维度2×6×2用简单数值方便计算querystorch.tensor([# 第0个样本6个token每个token2维[[1,0],[2,1],[0,1],[3,2],[1,1],[0,0]],# 第1个样本6个token每个token2维[[0,1],[1,0],[2,2],[1,2],[0,2],[2,1]]],dtypetorch.float
# shape(2,6,
keystorch.tensor([# 第0个样本的keys和querys结构一致[[1,2],[0,1],[1,0],[2,1],[0,2],[1,1]],# 第1个样本的keys[[2,0],[1,1],[0,2],[2,1],[1,0],[0,2]]],dtypetorch.float
# shape(2,6,
#
执行transpose和矩阵乘法keys_Tkeys.transpose(1,
# shape(2,2,
attn_scoresquerys keys_T# shape(2,6,
#
输出结果print(attn_scores维度,attn_scores.shape)# 输出torch.Size([2, 6, 6])print(\n第0个样本的注意力分数矩阵6×
print(attn_scores[0].numpy())# 每个值是query token和key token的点积输出结果解读attn_scores维度 torch.Size([2, 6, 6])第0个样本的注意力分数矩阵6×6[[
1.
0.
1.
2.
0.
] # 第0个query token对6个key token的分数 [
4.
1.
2.
5.
2.
] # 第1个query token对6个key token的分数 [
2.
1.
0.
1.
2.
] [
7.
2.
3.
8.
4.
] [
3.
1.
1.
3.
2.
] [
0.
0.
0.
0.
0.
]]数值计算验证以第 0 个样本的第 0 个 query token 为例querys[0,0] [1, 0]keys [0,:, :] 6 个 key token 的 2 维向量和第 0 个 key token [1,2] 的点积1×1 0×2 1 → 对应矩阵 [0,0] 位置的 1和第 1 个 key token [0,1] 的点积1×0 0×1 0 → 对应矩阵 [0,1] 位置的 0… …最终得到 6×6 矩阵每个位置的值是「query 的第 i 个 token」和「key 的第 j 个 token」的点积即注意力分数核心意义大模型注意力机制中的关注程度6×6 的矩阵就是注意力分数矩阵含义是每个样本有 6 个 token矩阵中 attn_scores[b, i, j] 代表「第 b 个样本中第 i 个 token 对第 j 个 token 的关注程度」后续会对这个矩阵做dropout、softmax归一化得到和为 1 的注意力权重再和 values 相乘实现 “每个 token 融合其他 token 的信息”维度结论attn_scores 2×6×6batch2每个样本对应 6×6 的注意力分数矩阵计算逻辑批量矩阵乘法[2,6,2][2,2,6] → [2,6,6]数值意义每个元素是 query token 和 key token 的点积代表二者的相似度注意力分数dropout训练过程中随机忽略一些隐藏层单元来有效“丢弃”它们减少模型对特定隐藏层单元的依赖避免过拟合同时dropout仅在训练期间使用nn.Dropout对输入张量的每个元素以概率p默认
5随机设置为0同时将未被设置0的元素乘以 1/(1-p) 进行缩放保证输入的期望均值不变importtorchimporttorch.nnasnn#
定义Dropout层p
5dropoutnn.Dropout(p
0.
#
构造输入张量值全为10方便计算均值xtorch.ones(
*10# 1万个元素每个都是10print(原始输入均值,x.mean().item())# 输出
1
0#
训练模式下执行Dropout默认trainTruetorch.manual_seed(
# 固定随机种子结果可复现x_dropdropout(x)#
计算Dropout后的均值print(Dropout后均值,x_drop.mean().item())# 输出≈
1
0因随机采样略有浮动print(Dropout后非零元素值,x_drop[x_drop!0][0].item())# 输出
2
010×2#
验证模式下evalDropout不生效dropout.eval()x_drop_evaldropout(x)print(验证模式下均值,x_drop_eval.mean().item())# 输出
1