人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载导读在《动手学深度学习》d2l-zh的注意力机制章节中注意力评分函数attention scoring function是连接查询query与键key和注意力权重的核心桥梁。本文基于 chapter_attention-mechanisms/attention-scoring-functions_origin.md 展开从高斯核出发推导评分函数的数学定义系统讲解掩蔽 softmax 操作、加性注意力additive attention与缩放点积注意力scaled dot-product attention两种主流评分函数并结合仓库d2l工具包如 d2l/torch.py中的源码实现给出可直接运行的 PyTorch 代码示例。读完本文你将掌握注意力汇聚的加权和本质、如何在批量处理中掩蔽填充词元以及如何根据查询与键的向量长度选择合适的评分函数为理解 Transformer、多头注意力等更复杂的注意力机制打下基础。从高斯核到注意力评分函数在 Nadaraya-Watson 核回归 一节中我们使用高斯核来对查询和键之间的关系建模。高斯核的指数部分实际上就是一个注意力评分函数attention scoring function简称评分函数。将该函数的输出送入 softmax 运算后我们得到与键对应的值的概率分布即注意力权重最后注意力汇聚的输出就是基于这些注意力权重的值的加权和。从宏观来看上述算法可以实例化注意力机制的通用框架记注意力评分函数为 $a$注意力汇聚的输出可以计算为值的加权和。由于注意力权重本身是一个概率分布因此加权和本质上是加权平均值。数学定义与通用框架用数学语言描述假设有一个查询 $\mathbf{q} \in \mathbb{R}^q$ 和 $m$ 个键-值对 $(\mathbf{k}_1, \mathbf{v}_1), \ldots, (\mathbf{k}_m, \mathbf{v}_m)$其中 $\mathbf{k}_i \in \mathbb{R}^k$、$\mathbf{v}_i \in \mathbb{R}^v$。注意力汇聚函数 $f$ 被表示成值的加权和$$f(\mathbf{q}, (\mathbf{k}_1, \mathbf{v}_1), \ldots, (\mathbf{k}_m, \mathbf{v}m)) \sum{i1}^m \alpha(\mathbf{q}, \mathbf{k}_i) \mathbf{v}_i \in \mathbb{R}^v$$其中查询 $\mathbf{q}$ 和键 $\mathbf{k}_i$ 的注意力权重标量通过注意力评分函数 $a$ 将两个向量映射成标量再经过 softmax 运算得到$$\alpha(\mathbf{q}, \mathbf{k}_i) \mathrm{softmax}(a(\mathbf{q}, \mathbf{k}_i)) \frac{\exp(a(\mathbf{q}, \mathbf{k}i))}{\sum{j1}^m \exp(a(\mathbf{q}, \mathbf{k}_j))} \in \mathbb{R}$$由此可见选择不同的评分函数 $a$ 会直接导致不同的注意力汇聚行为。本节将介绍两个主流评分函数——加性注意力与缩放点积注意力它们稍后将被用于实现 Bahdanau 注意力chapter_attention-mechanisms/bahdanau-attention.md、多头注意力与 Transformer 等更复杂的注意力机制。掩蔽 Softmax 操作softmax 操作用于输出一个概率分布作为注意力权重。但在某些场景下并非所有值都应该被纳入注意力汇聚。典型例子是机器翻译中的小批量处理见 chapter_recurrent-modern/machine-translation-and-dataset.md为了对齐不同长度的句子一些文本序列被填充了没有意义的特殊词元。为了仅对有意义的词元进行注意力汇聚需要指定一个有效序列长度有效词元个数在计算 softmax 时过滤掉超出该范围的位置。下面的masked_softmax函数实现了这一掩蔽 softmax 操作masked softmax operation任何超出有效长度的位置都会被掩蔽并置为 0。以下是 PyTorch 版本的核心实现与 chapter_attention-mechanisms/attention-scoring-functions.md 中#tab pytorch的代码一致def masked_softmax(X, valid_lens): 通过在最后一个轴上掩蔽元素来执行softmax操作 # X:3D张量valid_lens:1D或2D张量 if valid_lens is None: return nn.functional.softmax(X, dim-1) else: shape X.shape if valid_lens.dim() 1: valid_lens torch.repeat_interleave(valid_lens, shape[1]) else: valid_lens valid_lens.reshape(-1) # 最后一轴上被掩蔽的元素使用一个非常大的负值替换从而其softmax输出为0 X d2l.sequence_mask(X.reshape(-1, shape[-1]), valid_lens, value-1e6) return nn.functional.softmax(X.reshape(shape), dim-1)实现的关键思路valid_lens为None直接对最后一个轴执行普通 softmax不进行任何掩蔽。一维valid_lens长度为批量大小表示每个样本矩阵统一的有效长度。此时通过torch.repeat_interleave(valid_lens, shape[1])将每个长度重复shape[1]每个样本中的矩阵行数次以便与展平后的每一行一一对应。二维valid_lens为每个矩阵中的每一行单独指定有效长度先reshape(-1)展平。掩蔽手段将超出有效长度的元素替换为非常大的负值-1e6其指数结果趋近于 0从而在 softmax 输出中被完全屏蔽。底层依赖d2l.sequence_mask其 PyTorch 实现位于 d2l/torch.py通过torch.arange(maxlen) valid_len[:, None]生成布尔掩码再将掩码为False的位置赋值为value。为了演示该函数的工作方式考虑一个小批量包含两个 $2 \times 4$ 的矩阵样本两个样本的有效长度分别为 2 和 3。经过掩蔽 softmax 操作超出有效长度的值都被掩蔽为 0masked_softmax(torch.rand(2, 2, 4), torch.tensor([2, 3]))同样也可以使用二维张量为矩阵样本中的每一行指定有效长度masked_softmax(torch.rand(2, 2, 4), d2l.tensor([[1, 3], [2, 4]]))掩蔽 softmax 不仅在注意力评分函数中使用在 d2l/torch.py 的MaskedSoftmaxCELoss带掩蔽的交叉熵损失中也被复用——sequence_mask会先对标签权重矩阵做同样的掩蔽这正是本仓库中一次实现、多处复用的设计体现。加性注意力当查询和键是不同长度的向量时可以使用加性注意力additive attention作为评分函数。给定查询 $\mathbf{q} \in \mathbb{R}^q$ 和键 $\mathbf{k} \in \mathbb{R}^k$加性注意力的评分函数为$$a(\mathbf q, \mathbf k) \mathbf w_v^\top \text{tanh}(\mathbf W_q\mathbf q \mathbf W_k \mathbf k) \in \mathbb{R}$$其中可学习参数为 $\mathbf W_q\in\mathbb R^{h\times q}$、$\mathbf W_k\in\mathbb R^{h\times k}$ 和 $\mathbf w_v\in\mathbb R^{h}$。从结构上看这等价于将查询和键拼接后输入一个只含单个隐藏层的多层感知机MLP隐藏单元数 $h$ 是一个超参数激活函数使用 $\tanh$并禁用偏置项。PyTorch 实现PyTorch 版本的AdditiveAttention类实现如下同时保存在 d2l/torch.py 中class AdditiveAttention(nn.Module): 加性注意力 def __init__(self, key_size, query_size, num_hiddens, dropout, **kwargs): super(AdditiveAttention, self).__init__(**kwargs) self.W_k nn.Linear(key_size, num_hiddens, biasFalse) self.W_q nn.Linear(query_size, num_hiddens, biasFalse) self.w_v nn.Linear(num_hiddens, 1, biasFalse) self.dropout nn.Dropout(dropout) def forward(self, queries, keys, values, valid_lens): queries, keys self.W_q(queries), self.W_k(keys) # 在维度扩展后 # queries的形状(batch_size查询的个数1num_hidden) # keys的形状(batch_size1“键值”对的个数num_hiddens) # 使用广播方式进行求和 features queries.unsqueeze(2) keys.unsqueeze(1) features torch.tanh(features) # self.w_v仅有一个输出因此从形状中移除最后那个维度。 # scores的形状(batch_size查询的个数“键-值”对的个数) scores self.w_v(features).squeeze(-1) self.attention_weights masked_softmax(scores, valid_lens) # values的形状(batch_size“键值”对的个数值的维度) return torch.bmm(self.dropout(self.attention_weights), values)前向传播可分为四个阶段线性投影分别用W_q和W_k将查询、键映射到统一维度num_hiddens。广播求和queries.unsqueeze(2)得到形状(batch_size, 查询数, 1, num_hiddens)keys.unsqueeze(1)得到(batch_size, 1, 键-值对数, num_hiddens)两者相加后每个查询与每个键一一组合形成所有 (查询, 键) 对的融合特征。激活与标量映射经过tanh后w_v输出维度为 1将其映射为标量得分scores形状为(batch_size, 查询数, 键-值对数)。掩蔽 归一化 加权求和masked_softmax(scores, valid_lens)生成注意力权重同时记录到self.attention_weights供可视化经 dropout 正则化后通过批量矩阵乘法torch.bmm与values相乘得到注意力汇聚输出。玩具示例用一个玩具示例演示AdditiveAttention。查询、键、值的形状批量大小、步数或词元序列长度、特征大小分别为 $(2, 1, 20)$、$(2, 10, 2)$ 和 $(2, 10, 4)$注意力汇聚输出的形状为批量大小查询的步数值的维度queries, keys d2l.normal(0, 1, (2, 1, 20)), d2l.ones((2, 10, 2)) # values的小批量数据集中两个值矩阵是相同的 values torch.arange(40, dtypetorch.float32).reshape(1, 10, 4).repeat( 2, 1, 1) valid_lens d2l.tensor([2, 6]) attention AdditiveAttention(key_size2, query_size20, num_hiddens8, dropout0.1) attention.eval() attention(queries, keys, values, valid_lens)尽管加性注意力包含可学习参数但由于本例中每个键都是相同的无法被任何查询区分得到的注意力权重是均匀的由指定的有效长度决定。用热力图可以直观地看到这一点d2l.show_heatmaps(d2l.reshape(attention.attention_weights, (1, 1, 2, 10)), xlabelKeys, ylabelQueries)show_heatmaps的实现位于 d2l/torch.py它以imshow绘制矩阵热图并支持设置 x/y 轴标签与子图标题是本书中可视化注意力权重的通用工具。缩放点积注意力使用点积可以得到计算效率更高的评分函数但点积要求查询和键具有相同的长度 $d$。假设查询和键的所有元素都是独立的随机变量且均满足零均值和单位方差那么两个向量点积的均值为 0、方差为 $d$。为确保无论向量长度如何点积的方差都保持为 1我们将点积除以 $\sqrt{d}$得到缩放点积注意力scaled dot-product attention评分函数$$a(\mathbf q, \mathbf k) \mathbf{q}^\top \mathbf{k} /\sqrt{d}$$在实践中通常从小批量的角度考虑效率对 $n$ 个查询和 $m$ 个键-值对计算注意力其中查询和键的长度为 $d$值的长度为 $v$。查询 $\mathbf Q\in\mathbb R^{n\times d}$、键 $\mathbf K\in\mathbb R^{m\times d}$ 和值 $\mathbf V\in\mathbb R^{m\times v}$ 的缩放点积注意力为$$\mathrm{softmax}\left(\frac{\mathbf Q \mathbf K^\top }{\sqrt{d}}\right) \mathbf V \in \mathbb{R}^{n\times v}$$PyTorch 实现PyTorch 版本的DotProductAttention类如下同时保存在 d2l/torch.py 中其中使用 dropout 进行模型正则化class DotProductAttention(nn.Module): 缩放点积注意力 def __init__(self, dropout, **kwargs): super(DotProductAttention, self).__init__(**kwargs) self.dropout nn.Dropout(dropout) # queries的形状(batch_size查询的个数d) # keys的形状(batch_size“键值”对的个数d) # values的形状(batch_size“键值”对的个数值的维度) # valid_lens的形状:(batch_size)或者(batch_size查询的个数) def forward(self, queries, keys, values, valid_lensNone): d queries.shape[-1] # 设置transpose_bTrue为了交换keys的最后两个维度 scores torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d) self.attention_weights masked_softmax(scores, valid_lens) return torch.bmm(self.dropout(self.attention_weights), values)与加性注意力相比该实现更简洁且没有任何可学习参数只包含一次批量矩阵乘法torch.bmm计算 $\mathbf Q \mathbf K^\top$其中对keys转置以交换后两个维度、一次缩放、一次掩蔽 softmax 与一次与values的批量矩阵乘法。valid_lens可以省略None此时不进行任何掩蔽。与加性注意力使用相同数据演示为了对比使用与加性注意力示例相同的键、值和有效长度对于点积操作令查询的特征维度与键的特征维度相同均为 2queries d2l.normal(0, 1, (2, 1, 2)) attention DotProductAttention(dropout0.5) attention.eval() attention(queries, keys, values, valid_lens)与加性注意力演示相同由于键包含的是相同的元素这些元素无法通过任何查询进行区分因此获得均匀的注意力权重d2l.show_heatmaps(d2l.reshape(attention.attention_weights, (1, 1, 2, 10)), xlabelKeys, ylabelQueries)两种评分函数的对比与选型对比维度加性注意力AdditiveAttention缩放点积注意力DotProductAttention适用条件查询与键向量长度不同$q \neq k$查询与键向量长度相同$q k d$评分公式$\mathbf w_v^\top \tanh(\mathbf W_q\mathbf q \mathbf W_k \mathbf k)$$\mathbf q^\top \mathbf k / \sqrt{d}$可学习参数有$\mathbf W_q, \mathbf W_k, \mathbf w_v$无计算开销需要 MLP 前向相对较高仅有矩阵乘法与缩放计算效率更高方差控制不适用除以 $\sqrt{d}$ 使点积方差保持为 1选择建议当查询和键向量长度相同时优先使用缩放点积注意力因为它计算效率更高且恰好是 Transformer 中自注意力与多头注意力见 chapter_attention-mechanisms/multihead-attention.md、chapter_attention-mechanisms/transformer.md的核心运算当查询与键长度不同例如 RNN 编码器-解码器中解码器状态与编码器隐状态维度不一致时则使用加性注意力Bahdanau 注意力正是它的直接应用见 chapter_attention-mechanisms/bahdanau-attention.md。小结与练习小结注意力汇聚的输出可以计算为值的加权平均选择不同的注意力评分函数会带来不同的注意力汇聚行为。当查询和键是不同长度的向量时可以使用加性注意力评分函数当它们长度相同时缩放点积注意力评分函数的计算效率更高。练习修改小例子中的键并可视化注意力权重。加性注意力和缩放点积注意力是否仍然产生相同的结果为什么只使用矩阵乘法能否为具有不同向量长度的查询和键设计新的评分函数当查询和键具有相同的向量长度时向量求和作为评分函数是否比点积更好为什么进一步阅读评分函数的两大实现均已收录在d2l工具包中可直接导入使用d2l/torch.py含masked_softmax、AdditiveAttention、DotProductAttention其他框架的实现见 d2l/mxnet.py、d2l/tensorflow.py、d2l/paddle.py。评分函数的下游应用Bahdanau 注意力 chapter_attention-mechanisms/bahdanau-attention.md、多头注意力 chapter_attention-mechanisms/multihead-attention.md、Transformer chapter_attention-mechanisms/transformer.md。掩蔽思想的延伸带掩蔽的交叉熵损失MaskedSoftmaxCELoss位于 d2l/torch.py用于序列到序列学习的训练。赞分享人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载相关推荐【深度学习实战】注意力机制增强线性偏置注意力库教程【深度学习实战】注意力机制增强线性偏置注意力库教程 项目介绍 注意力与线性偏差Attention with Linear Biases 是一个由 Ofir双向交叉注意力革新深度学习注意力机制的新范式双向交叉注意力革新深度学习注意力机制的新范式 在深度学习和自然语言处理领域注意力机制一直是推动技术进步的核心动力。双向交叉注意力Bidirectional深度学习注意力机制入门指南从南瓜书第5章神经网络基础到自注意力公式详解深度学习注意力机制入门指南从南瓜书第5章神经网络基础到自注意力公式详解 想要理解深度学习中的 注意力机制 和 自注意力公式 吗Datawhale团队的《南瓜教程机器学习上一篇APK-Installer 上手教程如何在 Windows 上免模拟器安装安卓应用下一篇从破解版陷阱到远程面板Wand-Enhancer 安全上手的 5 道关创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考