拓冰建站拓冰建站
首页 / 资讯中心 / 正文

注意力机制:从核回归到Transformer的权重化信息聚合

1. 从“看哪里”到“学哪里”注意力机制的核心直觉在机器学习和深度学习的实践中我们常常面临一个根本性的挑战如何处理海量的输入信息无论是处理一张高分辨率图片中的千万像素还是分析一篇长文档中的每个词语模型如果对每个输入单元都“一视同仁”地投入同等计算资源不仅效率低下而且容易淹没在噪声中无法抓住关键信息。这就像我们人类在阅读时不会逐字逐句以相同的精力去分析而是会快速扫视将注意力集中在标题、关键词和核心段落上。这种“选择性聚焦”的能力正是注意力机制试图赋予模型的。注意力机制的核心思想可以概括为“权重化的信息聚合”。它不是一个具体的模型而是一种设计范式一种资源分配策略。其目标是为输入序列中的不同部分分配不同的重要性权重然后根据这些权重对信息进行加权汇总从而得到一个更能代表当前任务需求的上下文表示。简单来说它教会模型在“看”的时候知道“哪里更重要”。这种思想并非凭空而来其数学根源可以追溯到统计学中的非参数回归方法特别是核回归。核回归为我们提供了一种优雅的框架如何根据查询点我们当前关注的问题与一系列键值对历史经验或输入数据的相似度来动态地计算一个加权平均的预测值。注意力机制尤其是其最基础的“注意力池化”形式可以看作是核回归在深度学习语境下的一个神经化、参数化的扩展。理解了这个连接我们就能从更坚实的统计基础出发而不仅仅是把注意力当作一个“魔法模块”。在接下来的内容里我们将从最直观的“注意力提示”概念入手逐步深入到其数学实现——注意力池化并揭示其与核回归的血缘关系。我们会用具体的例子和代码片段展示如何从零构建一个最简单的注意力模型并讨论其在现代深度学习架构如Transformer中的核心地位。无论你是刚入门的新手还是希望巩固基础的老手理解这个“从统计到神经网络”的演进路径都将大有裨益。2. 注意力提示从生物本能到算法框架在深入公式之前让我们先建立一个牢固的直觉。注意力本质上是一种资源分配方案。在计算资源有限的前提下将更多的“算力”分配给更重要的输入部分。2.1 生活中的注意力提示想象一下你在一个嘈杂的鸡尾酒会上。房间里充满了各种对话声、音乐声和杯盘碰撞声。此时你的朋友叫了你的名字。尽管环境音的总音量可能远大于朋友的声音但你的大脑会瞬间将“听觉注意力”聚焦到朋友声音传来的方向抑制其他背景噪音。这里的“你的名字”就是一个强大的非自主性提示非自主性线索它基于刺激本身的突出性显著性自动捕获了你的注意力。另一种情况是你正在聚精会神地阅读一份复杂的项目报告寻找关于预算的部分。此时你的注意力是由你内心的任务和目标驱动的这是一种自主性提示自主性线索。你主动地、有意识地将认知资源导向与“预算”相关的章节、表格和数字。在机器学习模型中这两种提示都有其对应物非自主性提示显著性例如在图像中一个像素与其周围像素差异巨大高对比度边缘、明亮斑点这个区域本身就具有视觉显著性容易吸引模型的“注意”。在序列中一个出现频率极低或极高的词如专业术语或停用词也可能具有统计显著性。自主性提示任务驱动这是更强大、更常用的方式。模型根据当前要解决的具体任务例如“翻译这句话”、“回答这个问题”、“检测图中的猫”生成一个查询Query。这个查询就像我们大脑中的“任务指令”用于在输入数据键Key中寻找最相关的内容并提取对应的值Value。2.2. 查询、键与值注意力机制的三元组这是理解注意力机制最关键的抽象。我们可以将其类比于信息检索系统查询Query代表当前模型“想知道什么”或“关注什么”。例如在翻译任务中当模型在生成目标语言的第t个词时它需要一个查询来回顾源语言句子中哪些部分最相关。键Key代表输入数据中每个元素的“标识”或“索引”。它用于与查询进行匹配计算相似度。键和查询通常存在于同一个向量空间以便进行相似度比较。值Value代表输入数据中每个元素实际包含的“信息内容”。一旦通过查询-键匹配找到了相关的元素我们就需要提取这些元素所承载的具体信息值。一个简单的比喻你Query去图书馆输入数据找一本关于“深度学习注意力机制”Query的内容的书。图书馆的图书检索系统Key里存有每本书的标题和关键词Key。你输入查询系统返回一系列相似度高的书名Key-Query匹配。最后你根据这个列表去书架上找到对应的书籍Value并阅读其中的内容聚合Value。在绝大多数注意力实现中键和值通常来源于同一个输入序列甚至是相同的向量但分别经过不同的线性变换层W_K,W_V投影到不同的空间以承担不同的角色。查询则可能来自另一个序列如解码器状态或同一序列的不同位置自注意力。注意这种“键-值”分离的设计是精妙的。它允许模型学习到根据什么特征Key去检索和检索到之后提取什么信息Value这两者可以是不同的。例如在基于内容的推荐系统中Key可以是电影的类型、演员用于匹配用户兴趣Query而Value可以是电影的详细描述、评分用于最终生成推荐列表。3. 注意力池化核回归的神经化诠释现在我们将直觉转化为数学。注意力池化是注意力机制最基础的计算单元其目标就是根据查询q对一组键值对{(k1, v1), (k2, v2), ..., (kn, vn)}进行加权求和得到输出。3.1 从平均池化到加权池化假设我们有一组数据点(x1, y1), (x2, y2), ..., (xn, yn)想要预测在位置x查询对应的y值。最简单的方法是平均池化f(x) mean(yi)。这显然不合理因为距离x远近不同的xi应该对预测有不同贡献。更合理的方法是Nadaraya-Watson核回归。它的预测公式为f(x) Σ_i [α(x, xi) * yi]其中α(x, xi)是权重由核函数K计算得出α(x, xi) K(x - xi) / Σ_j K(x - xj)。这里x是查询Query。xi是键Key即数据点的位置。yi是值Value即数据点的标签。K(·)是一个核函数如高斯核用于度量查询x与键xi之间的相似度。相似度越高权重α越大。分母是一个归一化项通常称为注意力权重确保所有权重之和为1使得输出f(x)是值yi的凸组合。这就是最原始的注意力池化模型在预测点x的输出是所有训练样本yi的加权平均权重取决于x与每个xi的相似度。3.2 引入可学习参数从非参数到参数化经典的核回归是非参数的核函数K是固定的如高斯函数。深度学习中的注意力池化则对其进行了参数化改造使其能够从数据中学习如何计算相似度。最常见的做法是使用加性注意力或缩放点积注意力来计算相似度分数。以缩放点积注意力为例 假设查询q、键k、值v都是向量。我们计算查询与每个键的点积衡量相似度然后进行缩放和归一化Softmax得到权重最后对值进行加权求和。# 伪代码示意 def attention_pooling(query, keys, values): # 计算相似度分数 scores[i] query · keys[i] scores torch.matmul(query, keys.transpose(-2, -1)) # 缩放为了梯度稳定并计算注意力权重 weights F.softmax(scores / sqrt(d_k), dim-1) # d_k是键向量的维度 # 加权求和 output torch.matmul(weights, values) return output, weights在这个框架下核函数K的角色被点积相似度或加性网络替代并且查询、键、值都可以通过神经网络W_Q, W_K, W_V从原始输入学习得到。归一化项Softmax对应核回归公式中的分母Σ_j K(x - xj)确保权重和为1。通过这种参数化注意力池化不再依赖于预设的、固定的距离度量如高斯核的欧氏距离而是可以学习适应特定任务的最优相似度计算方式。例如在文本任务中它可以学习到“苹果”公司”和“水果”苹果”在与不同查询交互时应有不同的相似度。3.3 一个简单的NumPy实现理解计算流程让我们抛开深度学习框架用最基础的NumPy来实现一个最简版的注意力池化加深理解。import numpy as np def nadaraya_watson_kernel_regression(x_train, y_train, x_query, bandwidth1.0): 简单的Nadaraya-Watson核回归高斯核 x_train: 训练键 (n_samples,) y_train: 训练值 (n_samples,) x_query: 查询点 (1,) bandwidth: 高斯核的带宽参数 # 计算查询与所有训练键的欧氏距离负数因为高斯核是距离的减函数 distances x_query - x_train # (n_samples,) # 使用高斯核计算非归一化权重 unnormalized_weights np.exp(-distances**2 / (2 * bandwidth**2)) # (n_samples,) # 归一化得到注意力权重 attention_weights unnormalized_weights / np.sum(unnormalized_weights) # (n_samples,) # 加权池化 y_pred np.sum(attention_weights * y_train) # (1,) return y_pred, attention_weights # 生成一些非线性数据 np.random.seed(42) x_train np.linspace(-5, 5, 50) y_train np.sin(x_train) 0.2 * np.random.randn(50) # 正弦函数加噪声 # 在多个查询点上进行预测 x_queries np.linspace(-5, 5, 200) predictions [] all_weights [] for xq in x_queries: yp, aw nadaraya_watson_kernel_regression(x_train, y_train, xq, bandwidth0.5) predictions.append(yp) all_weights.append(aw) # 可视化此处省略绘图代码但概念上我们会看到一条平滑曲线 # 对于每个x_query模型都“注意”到了附近x_train的点并给出了预测。这个例子清晰地展示了注意力池化的流程计算相似度高斯核- 归一化权重Softmax的连续类比- 加权求和池化。带宽参数bandwidth控制了注意力的“聚焦”程度。带宽小则注意力集中只关注非常近的点预测曲线波动大带宽大则注意力分散平滑效应强。实操心得带宽的选择在核回归或类似注意力中带宽或缩放因子sqrt(d_k)是一个超参数其作用类似于卷积神经网络中的感受野。它决定了模型关注的范围大小。在实践中通常通过验证集来调整这个参数。在Transformer的缩放点积注意力中缩放因子sqrt(d_k)是为了防止点积结果过大导致Softmax梯度消失这是一个重要的工程技巧。4. 注意力机制的全景从池化到现代架构基础的注意力池化是一个强大的模块但将其嵌入到完整的神经网络中并规模化才真正释放了其潜力。4.1 注意力机制的几种基本形态加性注意力早期RNN编码器-解码器架构中常用。它通过一个小的前馈网络来计算查询和键的相似度score(q, k) v^T * tanh(W_q * q W_k * k)。这种方式更灵活但计算量稍大。点积注意力查询和键直接做点积score(q, k) q^T * k。计算高效但要求查询和键的维度相同且当维度d_k较高时点积值的方差会变大容易将Softmax推入梯度极小的区域。缩放点积注意力点积注意力的改进版score(q, k) q^T * k / sqrt(d_k)。缩放操作使得点积值的方差稳定在1左右有利于训练。这是Transformer中使用的标准形式。自注意力当查询、键、值都来自同一个序列时称为自注意力。它允许序列中的每个位置与序列中所有位置包括自身进行交互从而捕捉序列内部的长期依赖关系。这是Transformer的核心。交叉注意力查询来自一个序列如解码器而键和值来自另一个序列如编码器。常用于机器翻译、问答等需要跨序列对齐的任务。4.2 多头注意力并行化的注意力“专家”单一的注意力池化在每次计算时只能建立一种类型的依赖关系。为了让模型同时关注来自不同表示子空间的信息提出了多头注意力。其思想很简单将查询、键、值通过不同的线性投影矩阵投影到h个不同的低维子空间头。在每个头上独立地执行缩放点积注意力得到h个输出。最后将这些输出拼接起来再通过一个线性投影得到最终结果。# 伪代码概念 class MultiHeadAttention(nn.Module): def forward(self, Q, K, V): # 1. 线性投影拆分成h个头 Q_heads split(self.W_q(Q)) # (batch, h, seq_len, d_k) K_heads split(self.W_k(K)) V_heads split(self.W_v(V)) # 2. 每个头独立计算注意力 head_outputs [] for i in range(h): output_i, _ scaled_dot_product_attention(Q_heads[i], K_heads[i], V_heads[i]) head_outputs.append(output_i) # 3. 拼接所有头的输出 concat_output concatenate(head_outputs) # (batch, seq_len, h*d_v) # 4. 最终线性投影 final_output self.W_o(concat_output) return final_output这相当于让h个不同的“注意力专家”同时工作一个可能专注于语法结构一个可能专注于语义相似另一个可能专注于指代关系。最后综合所有专家的意见做出更稳健的决策。4.3 注意力机制在模型中的位置与作用在现代架构中注意力机制通常不是孤立存在的而是与其它层交织在一起Transformer Block标准Transformer块包含一个多头自注意力层和一个前馈神经网络层每个层周围都有残差连接和层归一化。这种设计使得注意力能够被深度堆叠。编码器-解码器结构在编码器中使用自注意力来理解源序列的内部结构。在解码器中使用掩码自注意力防止看到未来信息和交叉注意力关注编码器输出来生成目标序列。视觉Transformer将图像分割成 patches每个 patch 视为一个 token然后直接应用 Transformer 编码器。其中的注意力机制让模型能够建立图像块之间的全局依赖超越了CNN局部感受野的限制。踩坑实录注意力权重的可视化与解释。我们常常想通过可视化注意力权重来理解模型“在看哪里”。但这需要谨慎Softmax的竞争性Softmax使得权重是相对的。一个位置权重高不一定是因为它绝对重要可能只是因为其他位置更不重要。特别是在长序列中权重分布可能非常均匀。多头注意力的分散不同头的注意力模式可能差异很大简单平均可能没有意义。需要分别检查每个头。不能直接等价于重要性高注意力权重表明该位置的信息被大量用于计算当前输出但这不一定是“因果性”的重要。有时模型可能通过注意力机制“忽略”某些噪声给低权重这也是一种重要的能力。 我的经验是将注意力权重作为理解模型内部工作机理的一种辅助工具而不是“金标准”。结合梯度类方法如Grad-CAM或扰动测试能获得更可靠的解释。5. 超越基础注意力机制的变体与优化基础的缩放点积注意力虽然强大但在处理长序列时面临O(n^2)计算和内存复杂度的瓶颈因为需要计算所有查询-键对。为此研究者提出了多种高效注意力变体。5.1 局部注意力与稀疏注意力思想并非所有查询都需要和所有键交互。强制每个查询只关注一个局部窗口如前后w个位置或一种预定义的稀疏模式如固定步长、块状模式。局部注意力类似CNN的局部感受野计算复杂度降至O(n*w)。在图像或某些具有强局部相关性的序列上很有效。稀疏Transformer设计固定的稀疏注意力模式例如Stride模式关注固定间隔的位置、Fixed模式关注某些固定位置。这需要先验知识。轴向注意力在多维数据如图像中沿高度和宽度两个轴分别进行注意力计算将O(h^2 * w^2)复杂度降为O(h^2 w^2)。5.2 线性化注意力核心思路通过数学变换将计算注意力权重的顺序进行交换从而避免计算显式的n x n注意力矩阵。一个著名的代表是Linformer和Linear Transformer。它们的基本思想是将标准的Softmax注意力公式Attention(Q, K, V) softmax(QK^T/sqrt(d)) V进行重写。通过使用核函数近似或低秩投影将K和V投影到低维空间使得QK^T的计算不再需要显式的n x n矩阵。例如Linear Transformer使用elu(x)1作为核函数使得注意力可以写成(Q * (K^T V))的形式从而实现线性复杂度。这类方法在长序列推理中能极大节省内存和时间。5.3 内存压缩与分块计算内存高效的注意力如FlashAttention通过精妙的IO感知算法在GPU显存层次结构HBM - SRAM中重新组织计算顺序避免存储庞大的中间注意力矩阵从而在几乎不改变算法的情况下大幅降低内存占用并提升速度。分块注意力将长序列分成块在块内进行精确注意力计算在块间使用一种简化的注意力机制如平均池化后的全局向量。这是一种工程上的折中方案。技术选型思考如何选择注意力变体这取决于你的具体任务和资源约束任务特性如果你的数据具有强烈的局部性如图像、音频局部注意力或轴向注意力是很好的起点。如果需要完全的全局交互如某些文档级NLP任务则需考虑线性注意力或内存优化方法。序列长度这是决定性因素。对于n512的序列标准注意力通常可以承受。对于n1024就必须考虑高效注意力变体。硬件资源如果GPU内存有限FlashAttention是必选项。它现在已被集成进主流的深度学习框架如PyTorch 2.0的scaled_dot_product_attention高效实现。精度要求有些线性化或稀疏化方法会引入近似误差。在关键任务上需要通过实验验证其对最终性能的影响。 我的建议是优先使用经过充分优化的标准注意力实现如PyTorch的F.scaled_dot_product_attention它内部可能已经集成了FlashAttention等优化。只有当序列长度成为明确瓶颈时再着手研究和引入特定的高效注意力变体。6. 实战构建一个用于回归任务的注意力层理论说了这么多我们来动手实现一个可以嵌入全连接网络的、最简单的注意力池化层并用于一个简单的回归任务。我们将实现一个“通用的”注意力池化层它接受一组键值对和一个查询输出加权后的值。然后将其用于拟合一个一维的非线性函数。import torch import torch.nn as nn import torch.nn.functional as F import numpy as np import matplotlib.pyplot as plt class SimpleAttentionPooling(nn.Module): 一个简单的注意力池化层使用缩放点积注意力。 def __init__(self, d_k, d_v): super().__init__() # 通常我们会有关联的线性层来投影Q, K, V。这里为了简单假设输入已经投影好。 # 或者我们内置投影层。这里我们选择内置更通用。 self.d_k d_k # 注意这个例子中我们让查询、键、值的维度可以不同但计算注意力时q和k维度需相同。 # 我们假设输入是原始特征用线性层投影到指定维度。 self.W_q nn.Linear(d_k, d_k, biasFalse) # 查询投影 self.W_k nn.Linear(d_k, d_k, biasFalse) # 键投影 self.W_v nn.Linear(d_v, d_v, biasFalse) # 值投影 def forward(self, queries, keys, values): Args: queries: (batch_size, num_queries, d_k) keys: (batch_size, num_keys, d_k) values: (batch_size, num_keys, d_v) Returns: output: (batch_size, num_queries, d_v) attn_weights: (batch_size, num_queries, num_keys) Q self.W_q(queries) # (B, Nq, d_k) K self.W_k(keys) # (B, Nk, d_k) V self.W_v(values) # (B, Nk, d_v) # 计算缩放点积注意力 scores torch.matmul(Q, K.transpose(-2, -1)) / (self.d_k ** 0.5) # (B, Nq, Nk) attn_weights F.softmax(scores, dim-1) # (B, Nq, Nk) output torch.matmul(attn_weights, V) # (B, Nq, d_v) return output, attn_weights # 构建一个使用注意力池化的简单回归模型 class AttentionRegressionModel(nn.Module): def __init__(self, input_dim1, hidden_dim64, output_dim1): super().__init__() # 我们将整个训练集视为“记忆”键值对。 # 但实际上我们需要动态处理。这里我们用一个网络来生成“记忆”的键和值。 self.memory_net nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), ) # 注意力池化层d_k和d_v都设为hidden_dim self.attention_pool SimpleAttentionPooling(d_khidden_dim, d_vhidden_dim) # 输出层从池化后的特征预测输出 self.output_layer nn.Linear(hidden_dim, output_dim) def forward(self, x_query, x_memory, y_memory): x_query: 要预测的查询点 (B, Nq, 1) x_memory: 作为记忆的训练点坐标 (B, Nm, 1) y_memory: 作为记忆的训练点标签 (B, Nm, 1) 注意这是一个“非参数”风格的使用记忆数据作为输入的一部分。 更常见的参数化方式是将记忆编码到模型参数中这里仅为演示注意力机制。 # 1. 将记忆的x编码为键和值 # 键由x_memory编码得到 K self.memory_net(x_memory) # (B, Nm, hidden_dim) # 值我们想让值包含y的信息。一种简单做法是将y_memory与编码后的特征结合。 # 这里为了极端简化我们直接用y_memory作为值的一部分或者也通过一个网络。 # 更合理的做法值也应该是一个学习到的表示。这里我们偷懒用K作为值即键值相同。 V K # (B, Nm, hidden_dim) # 2. 将查询点x_query编码为查询向量 Q self.memory_net(x_query) # (B, Nq, hidden_dim) # 3. 注意力池化 context, attn_weights self.attention_pool(Q, K, V) # context: (B, Nq, hidden_dim) # 4. 输出预测 y_pred self.output_layer(context) # (B, Nq, 1) return y_pred, attn_weights # 生成模拟数据 def generate_data(num_samples100): x np.linspace(-3, 3, num_samples) y np.sin(x) * np.exp(-0.1 * x**2) 0.1 * np.random.randn(num_samples) # 一个衰减振荡信号 return torch.FloatTensor(x).view(-1, 1), torch.FloatTensor(y).view(-1, 1) # 训练和评估 def train_and_evaluate(): # 数据 x_all, y_all generate_data(200) # 划分“记忆”集训练集和查询集测试集 indices np.random.permutation(len(x_all)) train_idx, test_idx indices[:150], indices[150:] x_train, y_train x_all[train_idx], y_all[train_idx] x_test, y_test x_all[test_idx], y_all[test_idx] model AttentionRegressionModel(input_dim1, hidden_dim32, output_dim1) optimizer torch.optim.Adam(model.parameters(), lr0.01) criterion nn.MSELoss() epochs 500 batch_size 32 num_train len(x_train) for epoch in range(epochs): model.train() perm torch.randperm(num_train) total_loss 0 for i in range(0, num_train, batch_size): idx perm[i:ibatch_size] batch_x_mem x_train[idx].unsqueeze(0) # (1, B, 1) - 这里简化假设batch内记忆相同 batch_y_mem y_train[idx].unsqueeze(0) # 在这个batch中我们用记忆数据来预测记忆数据本身自回归这只是一个演示。 # 更合理的设置是从记忆集中采样一部分作为支持集另一部分作为查询。 # 这里我们简单地将batch内的点既作记忆又作查询。 y_pred, _ model(batch_x_mem, batch_x_mem, batch_y_mem) loss criterion(y_pred.squeeze(0), batch_y_mem.squeeze(0)) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() if (epoch1) % 100 0: print(fEpoch [{epoch1}/{epochs}], Loss: {total_loss/(num_train//batch_size):.4f}) # 评估在测试集上用全部训练集作为记忆 model.eval() with torch.no_grad(): # 将全部训练集作为记忆 x_mem x_train.unsqueeze(0) # (1, N_train, 1) y_mem y_train.unsqueeze(0) # 预测测试集 y_pred_test, attn_weights model(x_test.unsqueeze(0), x_mem, y_mem) test_loss criterion(y_pred_test.squeeze(0), y_test) print(fTest MSE: {test_loss.item():.4f}) # 可视化 plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) plt.scatter(x_train.numpy(), y_train.numpy(), alpha0.6, labelTrain (Memory)) plt.scatter(x_test.numpy(), y_test.numpy(), alpha0.6, labelTest (Query)) # 生成平滑曲线用于绘制预测 x_plot torch.linspace(-3, 3, 300).view(-1, 1) y_plot_pred, _ model(x_plot.unsqueeze(0), x_mem, y_mem) plt.plot(x_plot.numpy(), y_plot_pred.squeeze().numpy(), r-, linewidth2, labelModel Prediction) plt.legend() plt.title(Regression Fit with Attention) # 可视化某个测试查询点的注意力权重 plt.subplot(1, 2, 2) query_idx 25 # 选择一个测试点 sample_attn attn_weights[0, query_idx].cpu().numpy() # (N_train,) plt.bar(x_train.squeeze().numpy(), sample_attn, alpha0.7, width0.05) plt.axvline(xx_test[query_idx].item(), colorr, linestyle--, labelfQuery x{x_test[query_idx].item():.2f}) plt.xlabel(Memory x) plt.ylabel(Attention Weight) plt.title(fAttention Weights for a Test Query) plt.legend() plt.tight_layout() plt.show() if __name__ __main__: train_and_evaluate()这个例子虽然简单但完整展示了如何将注意力池化作为一个可微分的神经网络层来构建和使用。模型通过学习能够为每个查询点动态地从“记忆”训练集中检索并聚合信息。可视化注意力权重可以看到对于某个查询点x模型确实会给附近的x_train点分配更高的权重这与核回归的直觉一致但这里的相似度度量通过memory_net学习比预设的高斯核更加灵活。注意事项与扩展记忆集的处理上面的例子中记忆集是作为模型输入动态传入的这更像是一种“非参数”或“基于记忆”的学习方式。更常见的参数化方式是将知识固化在网络的权重中注意力用于处理序列输入本身。计算效率在实际应用中如果记忆集很大这种每次计算所有查询-键对的方式开销巨大。这就需要用到我们前面提到的高效注意力机制。键与值的分离本例中为了简化令VK。在更复杂的任务中V应该独立学习以承载与K不同的信息。位置信息对于序列数据输入本身没有顺序信息。需要额外加入位置编码如正弦余弦编码、可学习编码来让注意力机制感知位置。这是Transformer成功的关键之一。注意力机制从核回归的统计思想出发通过神经网络的参数化改造已成为深度学习中最核心的构件之一。理解其从“提示”到“池化”再到“架构”的演进脉络不仅能帮助我们在实践中更好地应用它例如选择合适的变体、调试注意力权重更能让我们洞察其本质——一种动态的、数据驱动的资源分配策略。无论是处理自然语言、图像还是其他序列化数据当你希望模型学会“有选择地聚焦”时注意力机制几乎总是你的第一选择。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门