天上鑫宸不说话 發表於 2026-3-31 12:45:00

深度学习进阶(一)从注意力到自注意力

<p>新分类续接之前的注意力机制内容开始,展开一些更现代的理论。</p>
<p>在之前的深度学习内容中,我们已经介绍了注意力机制的核心流程,其本质可以概括为:<strong>在解码的每一个时间步增加注意力计算得到上下文向量,让模型可以根据当前状态,从输入序列中动态选择相关信息。</strong><br>
<img src="https://img2024.cnblogs.com/blog/3708248/202603/3708248-20260331124337497-1877514107.png" alt="image.png" loading="lazy"></p>
<p>实际上,你会发现:<strong>在这个传播过程中,传统的注意力机制只是一个插件。</strong><br>
在这个机器翻译的例子里,模型的主干仍然是 RNN,如果在解码的每一步去除了注意力计算,那么整个模型就是一个常见的不等长循环神经网络。</p>
<p><strong>而注意力计算的实质,其实是对解码器每一步的隐藏状态到该步输出间的一次“再加工”。</strong><br>
它是对解码器当前隐藏状态的一次<strong>信息增强</strong>,使得模型在生成输出时能够参考输入序列中的关键部分。<br>
总结来说就是:</p>
<blockquote>
<p><strong>注意力机制并没有改变模型“如何建模序列”,而只是让结果“更准确”。</strong></p>
</blockquote>
<p>于是一个想法产生了:</p>
<blockquote>
<p><strong>既然这种“信息增强”在本质上是有益的,为什么我们要把它限制在解码阶段?</strong></p>
</blockquote>
<p>这就是自注意力机制的出发点,它让注意力机制彻底摆脱了“优化插件”的地位,不再依附于 RNN 或其他结构存在,而是被抽象为一种<strong>独立的计算层</strong>,与全连接层、卷积层处于同一层级,最终成为 Transformer 乃至整个现代深度学习领域的核心内容。</p>
<h1 id="1自注意力机制的背景">1.自注意力机制的背景</h1>
<p>不必过多赘述,自注意力机制出自大名鼎鼎的论文:<strong><em>Attention Is All You Need</em></strong><br>
这篇 17 年的论文目前的引用量已超过十万级别,并持续快速增长,其影响力不仅局限于 NLP 领域,更扩展到计算机视觉、多模态学习等多个方向,是近年来深度学习领域最具里程碑意义的工作之一。<br>
在当前大模型的发展中,Transformer 已经成为事实上的核心架构,而自注意力就是它的核心计算单元。</p>
<p>如果把自注意力机制理解为一句话,它做的事情其实非常简单:</p>
<blockquote>
<p><strong>对于序列中的每一个位置,都去“看一遍”整个序列,然后根据相关性重新生成自己的表示。</strong></p>
</blockquote>
<p>我们知道:在传统序列建模中,每个位置的隐藏状态 <span class="math inline">\(\mathbf{h}^{(i)}\)</span> 仅依赖于当前输入 <span class="math inline">\(\mathbf{x}^{(i)}\)</span> 和前一时刻的状态 <span class="math inline">\(\mathbf{h}^{(i-1)}\)</span>。</p>
<p>但在自注意力中:</p>
<blockquote>
<p><strong>每一个位置的表示,不再依赖于时间递推,而是由整个序列共同决定。</strong></p>
</blockquote>
<p><strong>因此,在之后的相关内容中,就不会在出现由时间步递推而产生的“隐藏状态”这个词,而是回到了“层级间的输入和输出”这个范畴。</strong></p>
<p>下面就来展开其详细过程:</p>
<h1 id="2-自注意力机制的运算过程">2. 自注意力机制的运算过程</h1>
<h2 id="21-自注意力层的输入">2.1 自注意力层的输入</h2>
<p>首先,给定一个长度为 <span class="math inline">\(n\)</span> 的序列信息,经过嵌入层得到输入:</p>
<p></p><div class="math display">\[\mathbf{X} = [\mathbf{x}^{(1)}, \mathbf{x}^{(2)}, \dots, \mathbf{x}^{(n)}]
\]</div><p></p><p>现在, <span class="math inline">\(\mathbf{x}^{(i)}\)</span> 就表示第 <span class="math inline">\(i\)</span> 个位置的输入特征向量,假定每个向量的维度为 <span class="math inline">\(d\)</span> 。<br>
我们先用单个位置的向量,来说明自注意力机制的运算过程。</p>
<h2 id="22-querykey-和-value">2.2 Query、Key 和 Value</h2>
<p>每个输入向量 <span class="math inline">\(\mathbf{x}^{(i)}\)</span>进入自注意层的第一件事,是<strong>做三次线性变换,得到三种不同语义的表示</strong>:</p>
<ol>
<li><strong>Query(查询):</strong></li>
</ol>
<p></p><div class="math display">\[\mathbf{q}^{(i)} = \mathbf{W}_Q \mathbf{x}^{(i)}
\]</div><p></p><ol start="2">
<li><strong>Key(键):</strong></li>
</ol>
<p></p><div class="math display">\[\mathbf{k}^{(i)} = \mathbf{W}_K \mathbf{x}^{(i)}
\]</div><p></p><ol start="3">
<li><strong>Value(值):</strong></li>
</ol>
<p></p><div class="math display">\[\mathbf{v}^{(i)} = \mathbf{W}_V \mathbf{x}^{(i)}
\]</div><p></p><p>这里的 <span class="math inline">\(\mathbf{W}_Q, \mathbf{W}_K, \mathbf{W}_V\)</span> 都是<strong>可学习参数矩阵</strong>,它们的矩阵维度为:</p>
<p></p><div class="math display">\[W_Q \in \mathbb{R}^{d \times d_k}, \quad
W_K \in \mathbb{R}^{d \times d_k}, \quad
W_V \in \mathbb{R}^{d \times d_v}
\]</div><p></p><p>其中,<span class="math inline">\(\mathbf{W}_Q\)</span> 和 <span class="math inline">\(\mathbf{W}_K\)</span> 的维度必须相同所以只使用一个参数, <span class="math inline">\(d_k\)</span> 和 <span class="math inline">\(d_v\)</span> 是超参数,但我们一般也要求二者相同,具体原因我们下面就会讲到。<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202603/3708248-20260331124343096-362703136.png" alt="image.png" loading="lazy"><br>
总之,这一步,<strong>是我们定义了三种变换并为其赋予了语义</strong>,具体语义是由我们后续的操作实现的,我们可以先简单了解如下:</p>
<ul>
<li><span class="math inline">\(\mathbf{q}^{(i)}\)</span>:当前位置“想找什么”。</li>
<li><span class="math inline">\(\mathbf{k}^{(i)}\)</span>:当前位置“能提供什么特征”。</li>
<li><span class="math inline">\(\mathbf{v}^{(i)}\)</span>:当前位置“真正携带的信息”。</li>
</ul>
<h2 id="23-相关性计算">2.3 相关性计算</h2>
<p>完成变换后,现在,对于某个固定位置 <span class="math inline">\(i\)</span>,它会和<strong>所有位置</strong> <span class="math inline">\(j\)</span> 计算相关性:</p>
<p></p><div class="math display">\[\text{score}_{ij} = \frac{\mathbf{q}^{(i)} \cdot \mathbf{k}^{(j)}}{\sqrt{d_k}}
\]</div><p></p><p><strong>注意:相关性的计算包括 <span class="math inline">\(i\)</span> 位置自己!</strong><br>
这里,就可以开始理解我们为三种向量赋予的语义:<br>
我们简单代入一个例子,假设:</p>
<p></p><div class="math display">\[\mathbf{q}^{(i)}=[食物,空气,水]
\]</div><p></p><p></p><div class="math display">\[\mathbf{k}^{(j)}=[厨房,自然,湖泊]
\]</div><p></p><p>二者的点积结果就会较大,<strong>因为 <span class="math inline">\(i\)</span> 位置需要的信息和 <span class="math inline">\(j\)</span> 位置提供的信息比较匹配</strong>,再换一种情况:</p>
<p></p><div class="math display">\[\mathbf{k}^{(j)}=[厕所,太空,沙漠]
\]</div><p></p><p>显然,这种情况下 <span class="math inline">\(i\)</span> 位置的需求和 <span class="math inline">\(j\)</span> 位置的供给就不匹配,点积结果就会较小。</p>
<p><strong>再次强调神经网络内部的不可知性,我们只是举例说明,一轮轮反向传播后,三种变换参数矩阵不断学习,会让变换结果的运算形成类型例子这样的效果。</strong></p>
<p>从这个公式也可以看出来,<span class="math inline">\(d_q\)</span> 和 <span class="math inline">\(d_k\)</span> 必须相等来满足点积运算要求。</p>
<p>而使用 <span class="math inline">\(\sqrt{d_k}\)</span> 进行<strong>缩放</strong>,则是让梯度更稳定,防止之后的 softmax 饱和。<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202603/3708248-20260331124342702-1719723006.png" alt="image.png|640" loading="lazy"><br>
这一步的逻辑就和常规注意力机制中相关度度量比较相似了,我们以此来了解<strong>所有位置的信息和当前位置信息的相关性。</strong></p>
<h2 id="24-softmax-归一化">2.4 softmax 归一化</h2>
<p>继续,这步的逻辑也不陌生,对每个 <span class="math inline">\(i\)</span>,我们在<strong>所有</strong> <span class="math inline">\(j\)</span> 上做 softmax:</p>
<p></p><div class="math display">\[\alpha_{ij} = \frac{\exp(\text{score}_{ij})}{\sum_{j=1}^{n} \exp(\text{score}_{ij})}
\]</div><p></p><p>现在,我们得到就是 <span class="math inline">\(i\)</span> 位置对于每个位置的<strong>注意力权重</strong>,结果 <span class="math inline">\(\alpha_{ij}\)</span> 就表示<strong>位置 <span class="math inline">\(i\)</span> 从位置 <span class="math inline">\(j\)</span> 获取信息的比例。</strong><br>
<img src="https://img2024.cnblogs.com/blog/3708248/202603/3708248-20260331124336982-252917518.png" alt="image.png" loading="lazy"></p>
<h1 id="25-加权求和得到输出">2.5 加权求和得到输出</h1>
<p>最终,我们使用之前一直没用到的 <span class="math inline">\(\mathbf{v}\)</span> 和上一步计算得到注意力权重进行加强求和。</p>
<p></p><div class="math display">\[\mathbf{z}^{(i)} = \sum_{j=1}^{n} \alpha_{ij} \mathbf{v}^{(j)}
\]</div><p></p><p>在这里,我们才赋予 <span class="math inline">\(\mathbf{v}\)</span> 语义,它代表<strong>真正携带的信息</strong>,用于计算最终的输出,这种效果也是不断地监督学习得到的。</p>
<p>每个位置 <span class="math inline">\(i\)</span> 用自己的权重分布从所有 <span class="math inline">\(\mathbf{v}^{(j)}\)</span> 中“提取信息”,最终得到新的表示。<br>
<strong>同样地,所有 <span class="math inline">\(\mathbf{v}^{(j)}\)</span> 中也包括当前位置本身的 <span class="math inline">\(\mathbf{v}^{(i)}\)</span> 。</strong><br>
<img src="https://img2024.cnblogs.com/blog/3708248/202603/3708248-20260331124341433-387341474.png" alt="image.png" loading="lazy"><br>
在这一步,你会发现,<span class="math inline">\(d_k = d_v\)</span> 并不是必须的,<strong>前者决定判断相似度的维度,而后者决定信息表示的维度。</strong><br>
而通常为了结构统一与实现简洁,我们会让二者相等。</p>
<h1 id="25-矩阵形式">2.5 矩阵形式</h1>
<p>我们已经从<strong>单个位置 <span class="math inline">\(i\)</span> 的角度</strong>理解了自注意力的计算过程。现在就来看看在实际计算中矩阵并行运算过程吧:<br>
我们先将所有位置的向量堆叠起来:</p>
<p></p><div class="math display">\[\mathbf{X} =
\begin{bmatrix}
(\mathbf{x}^{(1)})^T \\
(\mathbf{x}^{(2)})^T \\
\vdots \\
(\mathbf{x}^{(n)})^T
\end{bmatrix}
\in \mathbb{R}^{n \times d}
\]</div><p></p><p>同理,可以得到:</p>
<p></p><div class="math display">\[\mathbf{Q} = \mathbf{X}\mathbf{W}_Q \in \mathbb{R}^{n \times d_k}
\]</div><p></p><p></p><div class="math display">\[\mathbf{K} = \mathbf{X}\mathbf{W}_K \in \mathbb{R}^{n \times d_k}
\]</div><p></p><p></p><div class="math display">\[\mathbf{V} = \mathbf{X}\mathbf{W}_V \in \mathbb{R}^{n \times d_v}
\]</div><p></p><p>显然,在这里 <span class="math inline">\(\mathbf{Q}\)</span> 的第 <span class="math inline">\(i\)</span> 行就是<span class="math inline">\(\mathbf{q}^{(i)}\)</span>、<span class="math inline">\(\mathbf{K}\)</span> 的第 <span class="math inline">\(j\)</span> 行就是<span class="math inline">\(\mathbf{k}^{(j)}\)</span>、<span class="math inline">\(\mathbf{V}\)</span> 的第 <span class="math inline">\(j\)</span> 行就是 <span class="math inline">\(\mathbf{v}^{(j)}\)</span>。</p>
<p>继续下一步:计算相关性矩阵:</p>
<p></p><div class="math display">\[\mathbf{S} = \mathbf{Q} \mathbf{K}^T \in \mathbb{R}^{n \times n} ,S_{ij} = \mathbf{q}^{(i)} \cdot \mathbf{k}^{(j)}   
\]</div><p></p><p>加入缩放后就是:</p>
<p></p><div class="math display">\[\mathbf{S} = \frac{\mathbf{Q} \mathbf{K}^T}{\sqrt{d_k}}
\]</div><p></p><p>对每一行做 softmax:</p>
<p></p><div class="math display">\[\mathbf{A} = \text{softmax}(\mathbf{S}) ,A_{ij} = \alpha_{ij}   
\]</div><p></p><p>最终进行加权求和:</p>
<p></p><div class="math display">\[\mathbf{Z} = \mathbf{A} \mathbf{V}\in \mathbb{R}^{n \times d_v}
\]</div><p></p><p>其中第 <span class="math inline">\(i\)</span> 行就是 <span class="math inline">\(\mathbf{z}^{(i)}\)</span>。</p>
<p><strong>现在,大的要来了:将所有步骤合并,自注意力可以写成一个紧凑的形式:</strong></p>
<p></p><div class="math display">\[\mathrm{Attention}(\mathbf{Q},\mathbf{K},\mathbf{V})=\mathrm{softmax}\left(\frac{ \mathbf{Q}\mathbf{K}^T}{\sqrt{d_k}}\right) \mathbf{V}
\]</div><p></p><p><strong>这就是 Transformer 中最核心的一行公式。</strong></p>
<p><strong>最终,通过自注意力, 我们将原始输入增强成了一个融合了全局上下文的表示。</strong><br>
这就是自注意力的完整运算过程。</p>
<h1 id="3-自注意力机制的核心优势">3. 自注意力机制的核心优势</h1>
<p>与传统方法相比,自注意力有一个核心优势:<strong>模型可以直接建模任意长距离依赖关系</strong>。<br>
在传统序列模型(比如 RNN)中,信息是这样传播的:</p>
<p></p><div class="math display">\[\mathbf{x}^{(1)} \rightarrow \mathbf{h}^{(1)} \rightarrow \mathbf{h}^{(2)} \rightarrow \dots \rightarrow \mathbf{h}^{(n)}
\]</div><p></p><p>路径长度是 <span class="math inline">\(n\)</span> ,不仅路径长,而且信息需要经过多次非线性变换,容易发生梯度消失或信息衰减。</p>
<p>而在<strong>单层</strong>自注意力中:</p>
<p></p><div class="math display">\[\mathbf{z}^{(i)} = \sum_{j=1}^{n} \alpha_{ij} \mathbf{v}^{(j)}
\]</div><p></p><p><strong>位置 <span class="math inline">\(i\)</span> 和任意位置 <span class="math inline">\(j\)</span> 之间,是“一步直达”的。</strong> <span class="math inline">\(i\)</span> 可以直接从 <span class="math inline">\(j\)</span> 获取信息,不需要经过任何中间节点,信息路径长度是 1,这就可以实现更长距离的依赖。<br>
此外,自注意力机制可以在所有位置上<strong>并行计算</strong>,而 RNN 必须按时间步顺序递归计算,这使得训练效率大幅提升。</p>
<p><strong>总结来说,自注意力机制用一次全局加权重建表示,把“序列依赖”从递归建模转变为全局直接建模,从而在提升表达能力的同时获得更短的信息传播路径与更高的计算效率。</strong></p>
<p>这就是单层自注意力的逻辑,在下一篇,我们就以此为基础,展开多头自注意力的内容。</p><br><br>
来源:https://www.cnblogs.com/Goblinscholar/p/19800737
頁: [1]
查看完整版本: 深度学习进阶(一)从注意力到自注意力