Attention is all you need?从Encoder到Decoder拆解Transformer的Self-Attention机制
1. 从 Encoder 到 DecoderSelf-Attention 到底在算什么如果你第一次翻开《Attention Is All You Need》这篇论文大概率会被那张经典的 Transformer 结构图劝退左边一摞 Encoder右边一摞 Decoder中间还插着箭头。但真正撑起整个架构的其实只有一个核心动作——Self-Attention自注意力。它解决的问题很朴素一句话里每个词怎么知道该重点看哪些其他词传统 RNN 是按顺序一个词一个词往后传长距离依赖容易丢CNN 要靠堆叠卷积核扩大感受野效率不高。Self-Attention 的思路是让每个位置直接和序列里所有位置算一次相关性一步到位建立全局依赖。这也是论文标题敢叫 Attention is all you need 的底气。这篇面向想真正吃透注意力机制的开发者我会从 Encoder 和 Decoder 两个视角把 Self-Attention 的计算流程拆开配上可复现的注意力权重计算代码和逐层维度验证步骤。同时为了做对照实验我会用 TaoToken 统一 Key/API 通道调用模型把同一段文本喂进去观察注意力行为避免在多个平台之间来回切换 Key。适合谁看写过 PyTorch、知道张量维度概念、但被 Q/K/V 和 mask 绕晕的同学以及想自己动手验证注意力权重、而不是只停留在公式层面的工程师。读完之后你应该能独立写出一个带维度打印的 Self-Attention 模块并说清楚 Encoder 和 Decoder 里那两层注意力的区别到底在哪。2. TaoToken 前置准备统一 Key 与 API 通道在动手写代码之前先把调用通道理顺。做注意力对照实验时我经常需要把同一段输入分别送给不同模型观察它们对长距离依赖的处理差异。如果每个模型都要单独申请 Key、单独记 Base URL实验还没开始人已经累了。TaoToken 的价值就在这里一个 Key、一个 API 入口覆盖多种模型切换模型只改一个 model 字段。先注册并拿到 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成账号注册后进入控制台。控制台地址是 https://taotoken.net/console 在左侧找到 API Keys 菜单新建一个 Key 并复制保存。注意 Key 只在创建时完整显示一次丢了只能重建。拿到 Key 之后你需要记住两个地址。API 基础地址是 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为 OpenAI 兼容接口的 base_url 使用。文档入口在 https://taotoken.net/doc 里面有各语言 SDK 的接入示例遇到字段不确定时先查文档比猜快。这里有个容易踩的坑很多人把 base_url 写成 https://taotoken.net/api/v1 或者漏掉 /api结果请求直接 404。正确做法是 base_url 填 https://taotoken.net/api SDK 内部会自动拼接 /v1/chat/completions 这类路径。如果你用的是 OpenAI 官方 Python SDK代码里这样写from openai import OpenAI client OpenAI( api_key你的TaoToken Key, base_urlhttps://taotoken.net/api ) resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: 用一句话解释自注意力}] ) print(resp.choices[0].message.content)模型 ID 怎么填在控制台的模型列表里能看到当前可用的模型名直接复制即可。做注意力对照实验时我一般会选两到三个不同规模的模型比如一个小模型和一个大模型观察它们对同一段长文本的注意力分布差异。切换时只改 model 参数Key 和 base_url 都不动这就是统一通道省下来的时间。如果你更习惯用命令行工具做长期编码或 Agent 任务可以了解 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它适合把模型能力接进日常开发流而不是每次手动发请求。对于本篇的注意力实验用上面的 Python SDK 就够了。3. 可复制配置Self-Attention 权重计算与维度验证这一节是全文的技术核心。我会先给出一个最小可运行的 Self-Attention 实现然后逐行打印维度让你亲眼看到 Q、K、V 是怎么从输入变出来的。所有代码基于 PyTorch直接复制就能跑。先明确输入约定。假设 batch_size2序列长度 seq_len4模型维度 d_model8。输入张量 x 的形状是 [2, 4, 8]。Self-Attention 要做的第一件事是用三个线性层把 x 分别投影成 Q、K、Vimport torch import torch.nn as nn import math class SelfAttention(nn.Module): def __init__(self, d_model, n_heads): super().__init__() assert d_model % n_heads 0, d_model 必须能被 n_heads 整除 self.d_model d_model self.n_heads n_heads self.d_k d_model // n_heads self.w_q nn.Linear(d_model, d_model) self.w_k nn.Linear(d_model, d_model) self.w_v nn.Linear(d_model, d_model) self.w_o nn.Linear(d_model, d_model) def forward(self, x, maskNone): batch_size, seq_len, _ x.shape print(f输入 x 形状: {x.shape}) Q self.w_q(x) K self.w_k(x) V self.w_v(x) print(fQ/K/V 形状: {Q.shape}, {K.shape}, {V.shape}) # 拆成多头: [B, L, d_model] - [B, n_heads, L, d_k] Q Q.view(batch_size, seq_len, self.n_heads, self.d_k).transpose(1, 2) K K.view(batch_size, seq_len, self.n_heads, self.d_k).transpose(1, 2) V V.view(batch_size, seq_len, self.n_heads, self.d_k).transpose(1, 2) print(f多头拆分后 Q 形状: {Q.shape}) # 缩放点积注意力 scores torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k) print(f注意力分数 scores 形状: {scores.shape}) if mask is not None: scores scores.masked_fill(mask 0, float(-inf)) attn torch.softmax(scores, dim-1) print(f注意力权重 attn 形状: {attn.shape}) out torch.matmul(attn, V) print(f加权输出 out 形状: {out.shape}) # 合并多头 out out.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model) out self.w_o(out) print(f最终输出形状: {out.shape}) return out, attn跑一下这段代码你会看到维度变化链条输入 [2,4,8] → Q/K/V [2,4,8] → 多头拆分 [2,2,4,4] → scores [2,2,4,4] → attn [2,2,4,4] → 输出 [2,4,8]。每一步都打印出来比盯着论文公式猜要直观得多。关键点在于 scores 的计算Q 乘以 K 的转置得到的是每个位置对其他所有位置的相关性分数形状是 [B, n_heads, L, L]。除以 sqrt(d_k) 是论文里的缩放操作防止 d_k 变大时点积结果过大导致 softmax 梯度消失。你可以做个实验把 math.sqrt(self.d_k) 去掉观察 attn 的分布是不是变得更尖锐、接近 one-hot这就是梯度消失的直观表现。mask 的处理是 Encoder 和 Decoder 的分水岭。Encoder 的 Self-Attention 不需要 mask每个位置都能看到全序列。Decoder 的 Masked Self-Attention 需要一个下三角矩阵把未来位置的分数置为 -infsoftmax 之后这些位置权重为 0。生成 mask 的代码如下def causal_mask(seq_len): mask torch.tril(torch.ones(seq_len, seq_len)).bool() return mask # [L, L], 下三角为 True把它传进 forward 的 mask 参数注意形状要能广播到 [B, n_heads, L, L]。实测下来最容易出错的就是 mask 的 True/False 语义搞反导致该屏蔽的位置反而被保留。建议先打印 mask 矩阵确认下三角是 True。如果你想把这段代码接进真实模型做对照可以用 TaoToken 的模型对话入口 https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 快速验证输入输出再回到本地代码调维度。两者配合调试效率会高很多。4. 验证请求从注意力权重到模型对照实验代码写完了怎么确认它真的算对了光看形状对还不够得看数值行为是否符合预期。这一节我给出三个验证步骤从单元测试到真实模型对照层层递进。第一步验证注意力权重每行和为 1。softmax 之后attn 在最后一维的和应该恒等于 1。加一行断言row_sum attn.sum(dim-1) print(每行权重和:, row_sum) assert torch.allclose(row_sum, torch.ones_like(row_sum), atol1e-5)如果这步失败说明 softmax 的 dim 写错了或者 mask 里混进了 nan。第二步验证 mask 生效。构造一个 seq_len4 的输入用 causal_mask 跑一遍打印第一个头的 attn 矩阵。你应该看到上三角全是 0下三角有值。位置 0 只能看到自己位置 3 能看到 0 到 3。这个下三角结构就是 Decoder 自回归生成的数学保证。第三步做真实模型对照。用第 2 节的 TaoToken 客户端把同一段文本分别发给两个不同模型让它们完成一个需要长距离依赖的任务比如把这句话里指代它的词找出来。虽然我们拿不到模型的内部注意力权重但可以通过输出质量间接判断模型对长距离关系的处理能力。代码示例text 小猫追着球跑它玩得很开心。请问它指代什么 for model_name in [gpt-4o-mini, gpt-4o]: resp client.chat.completions.create( modelmodel_name, messages[{role: user, content: text}] ) print(model_name, -, resp.choices[0].message.content)实测下来不同模型对这类指代消解任务的表现差异恰好反映了它们在注意力分配上的不同策略。小模型可能更依赖局部邻近词大模型能捕捉更远的依赖。这就是为什么我说统一 Key 通道很重要——你可以在同一个脚本里循环切换模型把对照实验做成批量任务。如果你在验证过程中遇到请求失败先检查三件事Key 是否复制完整、base_url 是否为 https://taotoken.net/api 、model 字段是否在控制台模型列表里。这三项确认无误绝大多数问题都能解决。需要重新生成 Key 时去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 操作即可。5. 本篇常见错误排查401、维度不匹配与 mask 陷阱即使代码看起来没问题跑起来还是可能报错。这一节我把注意力实验里最常遇到的几个错误列出来对照真实报错信息给出排查路径。第一个高频错误是 401 Unauthorized。报错信息通常是Error code: 401 - {error: {message: Invalid API key}}。原因无非三种Key 复制时带了空格、Key 已过期或被删除、base_url 写错导致请求打到了别的服务。排查顺序是先打印 api_key 的前后各 4 位确认没截断再确认 base_url 是 https://taotoken.net/api 最后去控制台看 Key 状态。如果用的是环境变量注意 shell 里 export 的变量名和代码里读取的名字要一致。第二个错误是维度不匹配典型报错RuntimeError: matmul: Input operand 1 has a mismatch in its core dimension。这几乎总是 Q 和 K 的转置维度对不上。检查你的 Q 形状是 [B, n_heads, L, d_k]K.transpose(-2,-1) 之后应该是 [B, n_heads, d_k, L]两者相乘得到 [B, n_heads, L, L]。如果 d_model 不能被 n_heads 整除view 操作会直接报错所以init里的 assert 别删。第三个错误是 mask 语义搞反。如果你用 masked_fill(mask 0, -inf)那 mask 里 0 代表要屏蔽的位置。但如果你用 torch.tril 生成的是 1/0 矩阵下三角是 1那 mask0 屏蔽的就是上三角逻辑正确。可如果你不小心用了 mask 1那就把该保留的位置全屏蔽了softmax 之后全是 nan。报错信息可能是RuntimeError: Function SoftmaxBackward returned nan values。解决办法很简单打印 mask 矩阵肉眼确认下三角是保留值。第四个错误和 OAuth 或本地代理有关。如果你在环境里配置过 HTTP_PROXY 之类的变量请求可能被转发到不可达的地址报错类似local proxy failed或连接超时。这时候检查环境变量把代理相关配置清掉再试。注意这里说的是清理本地环境变量不是让你去配置任何网络工具。第五个错误是读取响应时reading choices报错通常是 resp.choices 为空。原因可能是请求被限流、模型名写错、或者 messages 格式不对。先打印完整 resp 对象看 error 字段再对照文档检查参数。如果模型名不在可用列表里控制台会返回明确提示。把这几类错误记下来下次遇到直接对号入座能省下大量搜索时间。6. 语义一致 CTA把注意力实验接进你的工作流代码跑通、错误排查完接下来就是把它变成日常可用的工具。我自己的做法是本地保留一份带维度打印的 Self-Attention 模块作为教学和调试用真实任务则通过 TaoToken 统一通道调用模型两者用同一套输入做对照。如果你主要做模型能力验证和对照实验模型对话入口最顺手https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。它适合快速试输入、看输出不用写完整脚本。如果你要把模型接进长期编码或 Agent 流程Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它解决的是每次手动发请求的重复劳动。需要管理多个 Key 或重建 Key 时API Keys 页面在这里https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。接入细节不确定就查文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。最后留一个实用技巧做注意力对照实验时把每次请求的 model、输入文本、输出结果写进一个 CSV跑完一批之后横向对比。这个习惯让我发现了很多单次请求看不出来的规律比如某些模型在长文本后半段注意力明显衰减。数据攒多了比任何教程都更能帮你理解注意力的真实行为。

相关新闻

echarts地图实战全攻略:从GeoJSON到series-map与geo组件

echarts地图实战全攻略:从GeoJSON到series-map与geo组件

做前端可视化的朋友,只要牵扯到地理数据,基本都绕不开 echarts地图。后台监控大屏、城市人流分析、门店选址评估、疫情热力图——凡是带着空间属性的数据,第一反应就是用地图来呈现。但说实话,很多人第一次接触 echarts 地图时都挺…

2026/10/2 15:19:27 阅读更多 →
Ubuntu+ROS2+Isaac Sim机器人仿真环境搭建全流程与踩坑实践

Ubuntu+ROS2+Isaac Sim机器人仿真环境搭建全流程与踩坑实践

做机器人仿真开发,Ubuntu、ROS2和Isaac Sim这套组合,单独装哪个都不算难,难的是让它们在同一个系统里好好协作、形成一条能真正跑通的工具链。我最近刚好在一台新机器上从零走了一遍:分区装Ubuntu、换源装驱动、装ROS2 Humble、再…

2026/10/2 15:19:27 阅读更多 →
C51单片机驱动ILI9341彩屏的硬件适配与Proteus仿真避坑指南

C51单片机驱动ILI9341彩屏的硬件适配与Proteus仿真避坑指南

1. 为什么选ILI9341?不是所有彩屏都适合C51单片机你手头有一块从淘宝淘来的3.2寸TFT彩屏,背面印着ILI9341,但接上STC89C52后,屏幕要么全黑、要么花屏、要么只闪一下就熄灭——这几乎是每个刚接触彩屏驱动的C51新手必经的“三连击”…

2026/10/2 15:19:27 阅读更多 →

最新新闻

霍尔式流量计从信号调理到算法实现:频率测量、滤波与标定全解析

霍尔式流量计从信号调理到算法实现:频率测量、滤波与标定全解析

做好几年流量测量设备,各种原理的流量计都摸过一遍,电磁的、涡街的、超声波的各有利弊,但要论“性价比高、结构简单、容易上手”,霍尔式流量计绝对排得上号。市面上大量热水器、净水器、冷却水监控、工业循环水系统里,…

2026/10/3 21:47:43 阅读更多 →
基于Klipper的Qt上位机实战:从通信协议到打印参数控制

基于Klipper的Qt上位机实战:从通信协议到打印参数控制

1. 项目概述与整体设计思路 1.1 为什么要做一个基于Klipper的Qt上位机 接触过3D打印的朋友应该对Marlin固件不陌生,那是把运动控制、温度管理、G代码解析全部塞进板载MCU的传统方案。而Klipper走的是另一条路——它把最吃算力的运动规划任务从MCU上剥离出来&#x…

2026/10/3 21:47:43 阅读更多 →
基于Qt的Klipper上位机开发:实时监控与通信解析实践

基于Qt的Klipper上位机开发:实时监控与通信解析实践

做3D打印上位机这件事,我是从“用别人的Web界面觉得不过瘾”开始的。Klipper这个固件生态有个特点:几乎所有常见前端(Mainsail、Fluidd)都是浏览器里的Web应用,功能很全,但想按自己的习惯定制监控界面、做本…

2026/10/3 21:47:42 阅读更多 →
DeepSeek Harness 桌面端安装避坑与内网部署实践指南

DeepSeek Harness 桌面端安装避坑与内网部署实践指南

1. 这次桌面端最大的变化:终于不用在终端里指挥一切了作为一个从 DeepSeek Harness 还在纯命令行阶段就开始折腾的老用户,我看到“官方桌面端”这几个字的时候,第一反应是:终于不用再靠 YAML 文件和各种命令去猜“现在到底执行到哪…

2026/10/3 21:46:42 阅读更多 →
DeepSeek Harness桌面端实战:从工作流编排到本地vLLM部署

DeepSeek Harness桌面端实战:从工作流编排到本地vLLM部署

DeepSeek Harness 官方桌面端终于有了。看到这个消息,我第一时间去下载装好了。原因很简单,作为每天跟大模型工作流打交道的人,之前用DeepSeek做工程化编排,要么在网页聊天窗里手搓提示词,要么开命令行敲一堆参数&…

2026/10/3 21:46:42 阅读更多 →
FPGA单粒子翻转(SEU)原理与可靠性加固策略解析

FPGA单粒子翻转(SEU)原理与可靠性加固策略解析

1. 单粒子翻转到底是什么,为什么FPGA这么怕它做FPGA开发时间久了,早晚会遇到一类极其隐蔽的问题:产品在实验室里跑得好好的,功能、时序、功耗全都没有任何问题,一到现场就偶发故障,而且极难复现。你去查时序…

2026/10/3 21:46:42 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →