惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google Online Security Blog
Google Online Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
腾讯CDC
C
CERT Recently Published Vulnerability Notes
博客园 - 聂微东
L
LINUX DO - 热门话题
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
C
Cisco Blogs
A
Arctic Wolf
Latest news
Latest news
Jina AI
Jina AI
P
Proofpoint News Feed
博客园 - 叶小钗
Vercel News
Vercel News
T
Threat Research - Cisco Blogs
博客园 - 三生石上(FineUI控件)
K
Kaspersky official blog
C
Check Point Blog
H
Heimdal Security Blog
博客园 - Franky
小众软件
小众软件
The Register - Security
The Register - Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
Project Zero
Project Zero
G
GRAHAM CLULEY
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
transformer进阶之路:#2 工作原理详解
AI-Frontiers · 2026-05-07 · via 博客园_首页

原文:
欢迎关注公众h: AI-Frontiers

transformer往期文章推荐

收藏! transformer学习资源汇总

transformer进阶之路:#1 整体概述

这是Transformer系列文章的第二篇。在第一篇中 transformer进阶之路:#1 整体概述 中,我们了解了 Transformer 的功能、使用方法、高级架构及其优势。

本篇将深入剖析其工作原理,详细研究数据在 Transformer 中的流动的机制,比如数据的矩阵表示和形状,以理解每个阶段具体逻辑。

架构概述

Transformer 架构的主要组成部分有:

1 架构概述

编码器解码器的数据输入包括:

  • 嵌入层

  • 位置编码层

编码器堆栈包含多个编码器。每个编码器包含:

  • 多头注意力层

  • 前馈层

解码器栈包含多个解码器。每个解码器包含:

  • 两个多头注意力层

  • 前馈层

输出(右上角)——生成最终输出,包含:

  • 线性层

  • Softmax层。

为了理解每个组件的作用,我们以训练一个翻译任务为例,一步步走过 Transformer 的工作流程。我们只用一个训练样本:输入序列是英文 "You are welcome",目标序列是西班牙语 "De nada"。

嵌入和位置编码

和任何自然语言处理模型一样,Transformer 需要知道每个单词的两件事:词义及其在序列里的位置。

  • 嵌入层: 负责编码单词的含义。

  • 位置编码层: 负责表示单词的位置。

Transformer 把这两部分编码直接相加,合二为一。

嵌入(Embedding)

Transformer 有两个嵌入层。输入序列被喂给第一个嵌入层,叫做 「输入嵌入」。

2 嵌入(Embedding)

目标序列则被喂给第二个嵌入层,不过在喂之前,需要先把目标序列向右移动一个位置,并在第一个位置插入一个「起始」标记。

注意,在推理阶段我们没有目标序列,只能像第一篇 transformer进阶之路:#1 整体概述 讲的那样,通过循环把输出序列喂给这第二个嵌入层。所以它也被称为「输出嵌入」。

文本序列通过我们的词汇表映射到数字词ID。然后,嵌入层将每个输入词映射到一个嵌入向量,该向量更丰富地表示了该词的含义。

2.1 嵌入(Embedding)

位置编码(Position Encoding)

RNN 本质上是一个循环:一个词接一个词地输入。因此它天然知道每个单词的位置。

但 Transformer 不用 RNN,序列里的所有单词是并行输入的。这虽然是它相比 RNN 的一大优势,但也意味着位置信息会丢失,必须单独把它加回来。

和两个嵌入层对应,Transformer 也有两个位置编码层。位置编码是独立于输入序列计算出来的。它们是一些固定的值,只取决于序列的最大长度。举个例子:

  • 第一个位置的编码是一个常数,表示这是第一个位置

  • 第二个位置的编码是另一个常数,表示这是第二个位置

  • 以此类推。

这些常数是用下面这个公式算出来的。

2-2

其中:

  • pos 是单词在序列中的位置

  • $d_{model } $ 是编码向量的长度(和嵌入向量的长度一样)

  • i 是这个向量里的索引值。

3 位置编码(Position Encoding)

换句话说,它把正弦曲线和余弦曲线交错在一起:所有偶数索引用正弦值,奇数索引用余弦值。举个例子,假如我们编码一个长度为 40 个词的序列,下图展示了其中几个(单词位置,编码索引)组合对应的编码值。

3.1 位置编码(Position Encoding)

蓝色曲线展示了第 0 个索引对于全部 40 个单词位置的编码值;橙色曲线是第 1 个索引的。剩下的索引值也会有类似的曲线。

矩阵维度

我们知道,深度学习模型一次处理一批训练样本。嵌入层和位置编码层操作的对象,是代表一批序列样本的矩阵。

4 矩阵维度

嵌入层接收一个形状为 (样本数, 序列长度) 的矩阵,里面是单词 ID。它把每个单词 ID 编码成一个词向量,词向量的长度就是嵌入尺寸(embedding size)。输出的矩阵形状就变成了:(样本数, 序列长度, 嵌入尺寸)。

位置编码使用的编码尺寸等于嵌入尺寸。所以它能生成一个形状完全一样的矩阵,直接加到嵌入矩阵上。

这个由嵌入层和位置编码层生成的 (样本数, 序列长度, 嵌入尺寸) 形状,会贯穿整个 Transformer:数据流过编码器堆栈和解码器堆栈时都保持不变,直到最后的输出层才会改变形状。

这里对 Transformer 里的 3D 矩阵维度有了个概念。为了让图示更简单,接下来我们会丢掉「样本数」这个维度,只针对单个样本使用 2D 表示。

4.1 矩阵维度

输入嵌入把输出送给编码器。同样,输出嵌入把输出送给解码器。

编码器

编码器堆栈和解码器堆栈,分别由若干个(通常是 6 个)编码器和解码器依次串联而成。

5 编码器

堆栈里的第一个编码器,接收来自嵌入层和位置编码层的输入。堆栈里的其他编码器,则接收上一个编码器的输出。

编码器把它的输入传给一个多头自注意力层。自注意力的输出再传给一个前馈层,然后前馈层把输出向上送给下一个编码器。

5.1 编码器

自注意力和前馈这两个子层,周围都有一圈残差连接,紧接着是一个层归一化。

最后一个编码器的输出,会按下面要讲的方式,被喂给解码器堆栈里的每一个解码器。

解码器

解码器的结构和编码器非常相似,但有两处不同。

和编码器一样,堆栈里的第一个解码器接收来自输出嵌入和位置编码的输入。堆栈里的其他解码器,则接收上一个解码器的输出。

解码器把它的输入传给一个多头自注意力层。但与编码器中的自注意力稍有不同:它只允许关注到序列中当前位置之前的位置。这是通过掩码(masking)未来位置实现的,我们稍后会详细讨论。

6 解码器

与编码器不同的是,解码器还有第二个多头注意力层,叫做「编码器-解码器注意力层」。这个层的工作方式类似自注意力,但它会结合两个来源的输入:一个是它下面的自注意力层的输出,另一个是编码器堆栈的输出。

自注意力的输出会传给前馈层,然后前馈层把输出向上送给下一个解码器。

这些子层:自注意力、编码器-解码器注意力和前馈层,周围都有一个残差连接,紧接着是一个层归一化。

注意力机制

在上一篇中,我们聊了为什么注意力在处理序列时如此重要。在 Transformer 里,注意力出现在三个地方:

  1. 编码器中的自注意力:输入序列关注自己

  2. 解码器中的自注意力:目标序列关注自己

  3. 解码器中的编码器-解码器注意力:目标序列关注输入序列

注意力层接收三个参数形式的输入,分别叫做 Query(查询)、Key(键)和Value(值)。

7.1 注意力机制

  • 在编码器的自注意力中:编码器的输入同时传给 Query、Key 和 Value 这三个参数。

  • 在解码器的自注意力中:解码器的输入同时传给 Query、Key 和 Value 这三个参数。

  • 在解码器的编码器-解码器注意力中:编码器堆栈最后一个编码器的输出,被传给 Value 和 Key 参数;而它下面那个自注意力(和层归一化)模块的输出,被传给 Query 参数。

7.1 注意力机制

多头注意力

Transformer 把每一个注意力处理器称为一个注意力头,然后并行地把这个过程重复多次。这就是多头注意力名字的由来。通过组合几个并行的、计算方式相似的注意力,它给了自己的注意力更强的辨别能力。

8 多头注意力

Query、Key 和 Value 会分别各自通过一个独立的线性层(每个层有自己的权重),产生三个结果:Q、K 和 V。然后,如下图所示,它们会通过注意力公式组合在一起,生成注意力分数。

8.1 多头注意力

这里需要认识到一个关键点:Q、K 和 V 携带的是序列中每个词的编码表示。注意力计算会把序列中的每一个词和其他每一个词都结合起来,这样,最终算出的注意力分数里,就编码了序列中每个词的一个分数。

刚才讨论解码器时,我们简单提到了掩码。上面的注意力图示里也画出了Mask。我们来看看它是怎么工作的。

注意力掩码

在计算注意力分数时,注意力模块会执行一个掩码步骤。掩码有两个目的:

a) 在编码器自注意力机制和编码器-解码器注意力机制中:掩码用于将输入句子中存在填充的部分的注意力输出置零,以确保填充不会影响自注意力。(注:由于输入序列的长度可能不同,因此像大多数自然语言处理应用一样,它们会使用填充标记进行扩展,以便将固定长度的向量输入到Transformer中。)

9 注意力掩码

编码器-解码器注意力机制也类似。

9.1 注意力掩码

b) 在解码器中,自我注意力:掩码作用是防止解码器在预测下一个单词时偷看目标句子的其余部分。

解码器处理源序列中的单词,并利用这些单词预测目标序列中的单词。在训练过程中,这一过程通过教师强制法实现,即将完整的目标序列作为解码器的输入。因此,在预测某个位置的单词时,解码器可以利用该单词之前和之后的目标单词。这使得解码器能够作弊,利用未来时间步的目标单词进行预测。

举个例子,当预测 “Word 3” 的时候,解码器应该只能参考目标序列里的前 3 个输入词,而不能看到第 4 个词 “Ketan”。

9.2 注意力掩码

因此,解码器会屏蔽序列中稍后出现的输入词。

9.3 注意力掩码

在计算注意力得分时(参见前面展示计算过程的图片),在调用 Softmax 函数之前,会对分子应用掩码。被掩码掉的元素(白色方块)被设置为负无穷大,以便 Softmax 函数将这些值转换为零。

生成输出

解码器堆栈中的最后一个解码器,把它的输出传给输出组件,由它转换成最终的输出句子。

线性层把解码器的向量投射成单词分数:对于句子中的每个位置,都会为目标词汇表里的每一个独特的词生成一个分数值。举个例子,假设我们最终的输出句子有 7 个词,而目标西班牙语词汇表有 10000 个独特词汇。那么,我们会为这 7 个词里的每一个,都生成 10000 个分数值。这些分数值,表示在该句子位置上,词汇表中每个词出现的可能性大小。

然后,Softmax 层把这些分数转换成概率(所有概率加起来等于 1.0)。在每个位置上,我们找到概率最高的那个词所对应的索引,然后把这个索引映射回词汇表里真正的词。这些词就构成了 Transformer 的输出序列。

10 生成输出

训练与损失函数

训练期间,我们会用一个损失函数(比如交叉熵损失)来比较生成的输出概率分布和目标序列。概率分布给出了每个词出现在该位置上的概率。

11 训练与损失函数

假设我们的目标词汇表只有四个词。我们的目标是产出一个概率分布,让它匹配我们期望的目标序列:"De nada END"。

这意味着:

  • 对于第一个单词位置,概率分布应该在 "De" 这个词上概率为 1,而词汇表里所有其他词的概率为 0。

  • 同样,"nada" 应该在第二个单词位置上概率为 1,"END" 在第三个单词位置上概率为 1。

跟往常一样,这个损失会被用来计算梯度,通过反向传播来训练 Transformer。

小结

希望这篇文章能让读者明白,训练期间 Transformer 内部到底发生了什么。正如我们在前一篇文章中所讨论的,推理阶段它会在一个循环中运行,但大部分处理过程是一样的。

多头注意力模块,正是 Transformer 强大能力的来源。在下一篇文章中,我们将继续深入一步,真正理解注意力计算的细节。

感谢阅读文章,如果觉得不错,欢迎关注、点赞、转发!