3.2 Encoder模块详解


3.2 Encoder模块详解

本节摘要:编码器由输入预处理(词嵌入加位置编码)与六个结构相同的编码器层堆叠而成,每层含多头自注意力与逐位置前馈两个子层,每个子层被"残差相加加层归一化"包裹。数据从嵌入出发逐层精炼,顶层输出是与输入等长的上下文表示序列,供解码器交叉注意力取用。本节追踪单层内的完整数据路径,解释"同一个词在不同句中得到不同表示"的机理、层数与信息提炼的关系,以及编码器输出的去向。

本节目标

阅读完本节,你应当能够:

  1. 列出编码器的组成:输入预处理加六层堆叠,说明各部分职责;
  2. 追踪一个向量经过单编码器层的完整路径与形状变化;
  3. 解释上下文相关表示的成因——为何同词不同句表示不同;
  4. 说明层数增加带来的精炼层次与代价;
  5. 描述编码器最终输出在解码器中的具体用途。

一、进入塔之前的两道工序

编码器塔本身很简单,复杂度都在塔外与层内。塔外两道工序:词嵌入与位置编码。每个词元编号查嵌入表得到模型维度的向量——这张表是可学习参数,语义相近的词在训练中被推到相近的位置;随后按第 2.3 节的方案生成位置编码并逐元素相加。走完这两步,每个词的表示同时携带"我是什么词"与"我在第几位",序列变成一个 n 行 d_model 列的矩阵,正式入塔。

一个常被追问的问题:嵌入层的数值要不要缩放?原论文把嵌入乘以模型维度的平方根,使其数值尺度与位置编码匹配,防止相加时一方淹没另一方。这类细节属于"不致命但影响训练平稳度"的工程项,复现时值得照做。

二、单层内部:双子层的流水线

六层编码器层结构完全相同、参数各自独立。单层内的流水线分两段。

第一段,多头自注意力。输入矩阵经三组投影生成查询、键、值,八头各自在子空间做缩放点积注意力,拼接后输出投影(细节即 2.1 与 2.2 节)。这一段让每个位置吸收全句信息。输出与输入相加(残差)、层归一化,得到第一段的规范输出。

第二段,逐位置前馈网络。每个位置的向量独立通过"升维、激活、降维"的两层网络(即 2.4 节),对吸收来的信息做非线性消化。输出再次与第一段输出相加、归一化,成为本层最终输出。

形状全程不变:n 行 d_model 列进,n 行 d_model 列出。这种"形状守恒"是残差连接与整个堆叠设计的前提——任何一层都可以无痛插拔或增删。

单个编码器层流水线

单个编码器层流水线

三、上下文相关表示:同词不同命

编码器最重要的性质,是产出"上下文相关"的表示。同一个"苹果",在"苹果发布了新手机"与"我吃了一个苹果"里,经过第一层自注意力后就开始分道扬镳——前者的表示吸收了"发布""手机"的信息,偏向公司义;后者吸收了"吃",偏向水果义。层数越深,分化越细:浅层多处理词法与局部搭配,中层浮现句法结构,深层编码语义与篇章关系。到顶层,每个位置的向量已经是"这个词在这句话里到底什么意思"的浓缩答案。

这个性质直接回答了词向量的老问题。Word2Vec 时代每个词只有一个静态向量,多义词只能取各义的平均,"苹果"的向量悬在公司与水果之间。编码器的动态表示让词义随语境流动,是深度上下文表示相对静态词向量的本质跃迁——也是 BERT 一类模型做理解任务表示能力强的底层原因。

层与层之间不是简单的重复劳动,而是分工精炼。可以粗略理解为:第一层把每个词"沾上"邻居的气息,中间层把句法骨架搭起来,深层把语义关系、指代、语气这些抽象结构压进表示。六层不是魔法数字——原论文的机器翻译任务上六层是效果与成本的平衡点;后续模型从几层到近百层都有,层数与任务复杂度、数据规模同步放大。

四、输出的去向与一个工程细节

编码器顶层输出有明确去处:作为解码器每一层交叉注意力的键与值。注意是"每一层"——解码器六层,每层的交叉注意力都查阅同一份编码器顶层输出,而不是各层对接编码器的对应层。这种"顶层对接、层层可查"的设计让信息接口简单统一。

一个有用的工程观察:由于编码器输出在推理时只需计算一次,之后整个逐词生成过程反复复用,翻译长句时编码器一次前向的开销被几十步解码摊薄。反过来,纯理解任务(分类、抽取)只需要编码器,没有解码循环——这也是 BERT 类模型推理成本可控的原因。

⚠️ 排查提示:复现时两个高频错误。一是掩码遗漏:批处理中同一批序列长短不齐,短序列补的填充位若不掩掉,编码器的自注意力会把无意义的填充向量当真实内容加权,长句短句混批时性能悄悄掉一截——需要在打分阶段把填充位的分数同样置为极大负数。二是层数参数共享搞反:六层参数应当各自独立,若误设为跨层共享,模型退化为深度循环的伪多层,容量骤降还不易察觉。

部件 参数共享范围 说明
词嵌入表 全模型共享(与输出投影可绑定) 同词同向量
各编码器层 层间独立 六套参数各自学习
层内前馈网络 跨位置共享 同层所有位置同权重
注意力投影 层内统一 各头独立投影到子空间

💡 理解检验:解释"为什么编码器输出的每个向量与输入位置一一对应,却又不止是那个词的向量"。答案落在自注意力的加权混合与逐层精炼上——对应位置承载,全句信息供料。

五、从单层到六层:堆叠的层次分工

六层不是六次同样的重复。对训练好的模型做逐层探测(例如逐层探针与注意力可视化),能看到清晰的分工轮廓:第一二层的注意力头多聚焦局部相邻与词法搭配;中间层开始浮现句法结构——依存关系、短语边界在注意力模式里成形;最上两层承载更抽象的语义关系与指代信息。信息逐层"精炼"的比喻由此有了实证支撑:每一层消费上一层的产出,产出更抽象的表示。

这个分工对工程也有指导意义。迁移学习时冻结浅层、只调深层常能以更小成本保住大部分效果——浅层学的是通用语言属性,跨任务稳定;深层与任务目标绑定更紧。出错分析时同理:低级错误(搭配混乱)查浅层相关配置,高级错误(语义颠倒)把注意力放在深层与数据分布上。

编码器的三种典型用法

完整的两塔机器翻译只是一种用法。其一,理解任务:只用编码器,塔顶表示接池化或特殊符位置后进分类头,BERT 路线的骨架。其二,检索与匹配:两个句子分别过编码器,用表示的相似度排序,向量检索系统的核心组件。其三,多模态编码:把图像切块、音频分帧后当作"词元"喂进编码器,同一架构处理不同模态——Vision Transformer 的思路。三种用法共享本节讲的全部内部机制,差别只在塔外怎么接。

⚠️ 再补一条复现细节:批内填充位的掩码要与损失屏蔽配套——注意力掩码只管"不看",损失屏蔽管"不计分",两处常写在不同代码路径里,改了一处忘了另一处是高频事故。建议把两处的掩码张量同源生成,一处定义两处引用。

💡 一分钟的自我检测:向自己解释"为什么编码器顶层输出的第 k 个向量,既是第 k 个词的表示、又包含全句信息"。答案要点:残差流保位置对应、注意力混合全句内容、逐层精炼两者叠加。能组织出这三层因果,本节即可收官。

编码器的表示能直接当"语义向量"用吗?

能,而且这正是它最大的应用外溢。塔顶每个位置的向量是深度上下文化的词义表示,整句表示可由池化(平均或取特殊符位置)得到,广泛用于检索、聚类、语义匹配。与静态词向量相比,它的区分度来自双向上下文——同一个词在褒贬两句里的池化向量能拉开距离。工程上这类表示已是向量检索系统的标配底座,理解了编码器的内部机制,排查"检索不准"的问题时才知道该从表示质量还是从索引参数下手。

重点提炼

  • 两道预处理:查表嵌入乘尺度因子,加正弦位置编码,矩阵入塔;
  • 双子层流水线:多头自注意力(全局交流)加逐位置前馈(非线性消化),各被残差加归一包裹;
  • 形状守恒:n 行 d_model 列进出每层,层可无痛增删;
  • 上下文相关表示:同词在不同句逐层分化,动态词义取代静态向量的平均义;
  • 层数即精炼深度:浅层局部搭配、中层句法、深层语义,六层是当年的平衡点而非铁律;
  • 输出去向单一:顶层表示供解码器每层交叉注意力作键值,推理时一次计算反复复用;
  • 两个高频坑:填充位掩码、层间参数误共享。

编码器只会读不会写。下一节看解码器——多一个子层的塔,如何带着因果约束逐词写出目标序列。

常见疑问

问:BERT 为什么只要编码器,不要解码器?
答:任务性质决定的。BERT 做的是理解类任务(分类、抽取、句间关系),只需要把源句编码成富含上下文的表示,不涉及逐词生成——双向可见的编码器恰好是理解的最优形态,解码器的因果限制反而是累赘。反过来,生成任务需要解码器的自回归结构。编码器与解码器的分家(BERT 与 GPT 两条路线)是「按任务取半边」的经典示范,也是理解当代模型谱系的钥匙。

问:编码器一层里子层的顺序可以换吗?
答:子层逻辑顺序(注意力→前馈)基本是共识,因为「先交流再加工」的次序有道理;但归一化放层前还是层后(Pre-Norm 与 Post-Norm 之争)正是 2.5 节讨论过的可换项。架构图上看似固定的连线,其实每个位置的设计都有理由与替代方案——能说出「为什么这样、还能怎样、换了会怎样」,才算真读懂了架构。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U