Transformers 任务机制深度解析:语音、视觉与 NLP 模型如何"解决"任务
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
本文以 🤗 Transformers 官方文档《¿Cómo los 🤗 Transformers resuelven tareas?》为骨架,逐层拆解 Wav2Vec2、ViT、ConvNeXT、DETR、Mask2Former、GLPN、BERT、GPT-2、BART 等模型在语音/音频、计算机视觉与 NLP 三类任务上的内部工作方式,并结合本仓库 src/transformers/models 下的真实实现进行源码级印证。读完本文,你将掌握 Transformer 编码器、解码器、编码器-解码器三种架构各自的适用任务、各类任务头(head)的挂接原理,以及现代 CNN 的改进思路,从而能根据自己的任务选择并正确使用这些模型。
一、总览:几乎所有模型都是三种架构的变体
在 官方任务概览 中我们了解到 🤗 Transformers 覆盖了 NLP、语音音频与计算机视觉任务。而本文的核心问题是:模型内部到底做了什么,才产生出有用的预测?
答案是:得益于 Transformer 灵活的架构,绝大多数模型只是**编码器(encoder)、解码器(decoder)或编码器-解码器(encoder-decoder)**三种结构之一的变体:
- 编码器:双向建模,适合需要"理解整段输入"的任务(文本分类、Token 分类、问答、图像分类);
- 解码器:因果(单向)建模,适合自回归式生成(文本生成);
- 编码器-解码器:序列到序列,适合摘要、翻译等输入与输出均为序列的任务。
此外,本仓库还保留了多款现代卷积神经网络(CNN),它们至今仍是计算机视觉任务的主力之一。后文会分别展开。
💡 前提提示:在深入之前,建议先具备原始 Transformer 架构的基础知识——理解编码器、解码器与注意力机制,能帮助你快速理解下文所有模型的运作方式。
二、语音与音频:以 Wav2Vec2 为例
Wav2Vec2 是一个自监督预训练模型:先用大量无标注语音数据预训练,再用带标签数据微调,即可用于音频分类与自动语音识别(ASR)。其实现位于 modeling_wav2vec2.py,从源码结构看,模型由以下四个核心组件构成。
2.1 特征编码器:从原始波形到特征向量
**特征编码器(feature encoder)**接收原始音频波形,先将其归一化为零均值、单位方差,再转换为特征向量序列,每个向量约覆盖 20ms 的音频。在源码中对应 Wav2Vec2FeatureEncoder 类,其后的 Wav2Vec2FeatureProjection 负责将卷积提取的特征投影到 Transformer 所需的隐藏维度。
2.2 量化模块:把连续波形变成"离散语音单元"
与文本可以切分成词不同,波形在本质上是连续的,无法天然切分为独立单元。因此特征向量需要经过量化模块(quantization module),其目标是学习离散的语音单元:从一组码字集合——即codebook(可理解为语音的"词表")——中选出最能代表当前连续音频输入的向量,再送入模型。源码对应 Wav2Vec2GumbelVectorQuantizer,采用 Gumbel-Softmax 完成离散选择的近似可微化。
2.3 上下文网络:掩码 + 对比学习的预训练目标
预训练阶段,约一半的特征向量会被随机掩码,掩码后的特征被送入上下文网络(context network)——一个附加了相对位置编码的 Transformer 编码器。预训练目标是对比学习任务:模型需要从一组"干扰项"中选出被掩码位置对应的真实量化语音表示,这促使模型学习让上下文向量与正确的量化语音单元(目标标签)最相似。
值得说明的是,该对比损失(contrastive loss)与多样性损失(diversity loss)共同构成预训练总损失,这一设计在 Wav2Vec2ForPreTrainingOutput 的字段注释中有明确记录。
预训练完成后,就可以用你的数据微调 Wav2Vec2 完成音频分类或 ASR。
2.4 音频分类:在基座模型上加序列分类头
将预训练模型用于音频分类时,只需在 Wav2Vec2 基座模型之上加一个序列分类层:
- 分类层是一个线性层,接收编码器的隐藏状态;
- 隐藏状态表示每个音频帧学习到的特征,但各帧长度可变,因此先对隐藏状态做池化得到定长向量,再转换为各类别标签上的 logits;
- 计算 logits 与目标之间的交叉熵损失,找出最可能的类别。
在源码中对应 Wav2Vec2ForSequenceClassification:其projector将hidden_size投影到classifier_proj_size,再由classifier线性层映射到num_labels。同时它提供了freeze_feature_encoder()与freeze_base_model()两个方法,分别用于冻结特征编码器或整个基座模型、只训练分类头——这是微调时的常用手段。
完整的微调与推理流程可参考 音频分类任务指南。
2.5 自动语音识别(ASR):CTC 语言建模头
用于 ASR 时,在 Wav2Vec2 基座模型上加一个CTC(Connectionist Temporal Classification,时序分类)语言建模层:
- 该层是线性层,接收编码器隐藏状态并转换为 logits,每个 logits 对应一个 token 类别(token 数量来自任务词表);
- 计算 logits 与目标之间的CTC 损失,找出最可能的 token 序列,再解码为最终转录文本。
实现对应 Wav2Vec2ForCTC。CTC 的引入解决了"语音帧数远多于输出字符数、且帧与字符无对齐标注"的难题。完整微调流程见 ASR 任务指南。
三、计算机视觉:Transformer 与现代 CNN 两条路线
计算机视觉任务有两条主流路线:
- 将图像切分为补丁序列,用 Transformer 并行处理(如 ViT);
- 使用现代 CNN(如 ConvNeXT),仍然基于卷积层,但吸收现代网络设计。
还有第三种思路:把 Transformer 与卷积结合(如 Convolutional Vision Transformer (CvT)、LeViT)。它们本质上是前两种方案的组合,本文不展开。
图像分类通常用 ViT 与 ConvNeXT;而目标检测、分割、深度估计则分别更适合 DETR、Mask2Former 与 GLPN。
3.1 图像分类:ViT 的纯 Transformer 路线
ViT 完全用纯 Transformer 架构取代卷积。其关键创新在于图像如何喂给 Transformer:
- 切分为补丁并生成补丁嵌入:图像被切成互不重叠的方形补丁,每个补丁经 2D 卷积层转换为向量(补丁嵌入)。对 base 规模模型,每个补丁嵌入是 768 维;例如 224×224 的图像可切成 196 个 16×16 的补丁。正如文本被分词,图像被"分补丁"成序列。源码 ViTPatchEmbeddings 正是用一个
kernel_size=patch_size, stride=patch_size的Conv2d一次性完成投影,再flatten(2).transpose(1, 2)得到序列; - 加入
[CLS]学习嵌入:仿照 BERT,在补丁嵌入序列前拼接一个特殊可学习 token[CLS],其最终隐藏状态作为分类头的输入(其他输出被忽略),帮助模型学习编码整张图像的表示; - 加入可学习的位置嵌入:Transformer 本身不知道补丁的排列顺序,因此加上与补丁嵌入同尺寸的可学习位置嵌入,之后全部嵌入送入 Transformer 编码器。这两步对应 ViTEmbeddings;
- MLP 分类头:只取
[CLS]对应输出送入 MLP 头,转换为各类别 logits,用交叉熵损失寻找最可能的类别。
ViT 的预训练目标就是分类本身。基座与分类头分别对应 ViTModel 与 ViTForImageClassification。微调流程见 图像分类任务指南。
3.2 图像分类:ConvNeXT 的现代 CNN 路线
ConvNeXT 是吸收现代网络设计思想改良的 CNN,卷积仍是核心。
卷积基础:从高层看,卷积是用一个较小的矩阵(kernel)与图像的一小块像素窗口相乘,提取某种特征(如特定纹理、线条曲率),然后滑动到下一个窗口;卷积每次移动的距离称为stride。卷积输出可继续喂给下一层卷积,网络逐层学到更复杂抽象的特征。在卷积层之间通常插入池化层降低维度,使模型对特征位置的轻微变化更鲁棒。
ConvNeXT 从五个方面"现代化"CNN:
- 调整各阶段 block 数量,并用更大 stride/kernel 对图像"分块":非重叠滑动窗口的分块策略与 ViT 切补丁的思路相似;
- 引入瓶颈层(bottleneck):先降通道再恢复,因为 1×1 卷积更快且可加深网络;而倒置瓶颈则先扩通道再降维,更省内存;
- 用 depthwise 卷积替换瓶颈层中的 3×3 卷积:对每个输入通道分别做卷积再堆叠,从而加宽网络以提升性能;
- 增大 kernel 到 7×7:ViT 依靠注意力拥有全局感受野,ConvNeXT 通过增大卷积核尝试复现这一效果;
- 吸收 Transformer 的层设计:减少激活层与归一化层数量,激活函数由 ReLU 改为 GELU,用 LayerNorm 取代 BatchNorm。
卷积块的输出送入分类头,转换为 logits 并计算交叉熵损失以确定最可能的标签。
3.3 目标检测:DETR 的端到端范式
DETR(DEtection TRansformer)是端到端目标检测模型,将 CNN 与 Transformer 编码器-解码器结合,实现位于 modeling_detr.py:
- CNN backbone 提取特征:预训练 CNN backbone 接收像素表示的图像,生成低分辨率特征图;再用 1×1 卷积降维,得到高层语义的新特征图。由于 Transformer 是序列模型,特征图被展平为特征向量序列,并与位置嵌入拼接;
- 编码器 + 解码器 + 目标查询:特征向量送入编码器,通过注意力层学习图像表示;编码器隐藏状态与目标查询(object queries)在解码器中结合。目标查询是可学习嵌入,聚焦图像的不同区域,并在逐层注意力中不断更新。解码器隐藏状态经前馈网络预测每个目标查询的边界框坐标与类别标签(无目标则预测
no object); - 并行解码 N 个预测:与自回归模型逐个预测不同,目标检测是集合预测任务
(边界框, 类别),DETR 对每个目标查询并行解码,一步产出 N 个预测; - 二分匹配损失:训练时用二分匹配损失将固定数量的预测与固定数量的真值标签配对。若 N 个标签中真值不足,则用
no object类填充。该损失促使 DETR 找到预测与真值的一一对应:边界框或类别不对会引入损失,预测了不存在的物体也会被惩罚——这鼓励 DETR 去发现图像中的其他物体,而不是只盯着最显眼的目标。
检测头包含两部分:线性层将解码器隐藏状态转为类别 logits,MLP 预测边界框。整体对应 DetrForObjectDetection。微调流程见 目标检测任务指南。
3.4 图像分割:Mask2Former 的统一掩码分类架构
Mask2Former 是解决所有类型图像分割任务(实例、语义、全景)的通用架构,实现位于 modeling_mask2former.py。
传统分割模型通常针对某一特定分割任务定制;Mask2Former 则将每种分割任务都建模为**掩码分类(mask classification)**问题:把像素聚成 N 个片段,为给定图像预测 N 个掩码及其对应的类别标签。其三大核心组件:
- Swin backbone:接收图像,经 3 个连续的 3×3 卷积生成低分辨率图像特征图;
- 像素解码器(pixel decoder):逐步把低分辨率特征上采样为高分辨率逐像素嵌入,输出多尺度特征,分辨率分别为原图的 1/32、1/16 与 1/8;
- Transformer 解码器层 + 掩码注意力:各尺度的特征图被逐次送入一个 Transformer 解码器层,以从高分辨率特征中捕捉小物体。关键在于解码器中的掩码注意力(masked attention)——不同于可关注整幅图像的交叉注意力,掩码注意力只聚焦图像中特定区域,既更快又更好,因为局部特征足以让模型学习。
与 DETR 类似,Mask2Former 也使用可学习目标查询,并与像素解码器的图像特征结合做集合预测(类别标签, 掩码预测):解码器隐藏状态经线性层转为类别 logits,用交叉熵损失求最可能类别;掩码预测则由像素嵌入与解码器最终隐藏状态结合生成,并用sigmoid 交叉熵损失 + DICE 损失对比真值掩码,找出最可能的掩码。整体对应 Mask2FormerForUniversalSegmentation。微调流程见 语义分割任务指南。
3.5 深度估计:GLPN 的全局-局部路径网络
GLPN(Global-Local Path Network)将 SegFormer 编码器与轻量解码器结合用于深度估计,实现位于 modeling_glpn.py:
- 更小的图像补丁:与 ViT 一样把图像切成补丁序列,但补丁更小——这更适合分割、深度估计这类稠密预测任务。补丁经 GLPNOverlapPatchEmbeddings 转为补丁嵌入后送入编码器;
- 层次化编码器:GLPNEncoder 接收补丁嵌入,经过多个编码器块,每个块由注意力层与Mix-FFN(负责提供位置信息)组成。每个编码器块末尾有一个补丁融合层:把相邻补丁组的特征拼接,再用线性层降维,将补丁数量降到 1/4 分辨率,作为下一编码器块的输入;如此重复,最终得到 1/8、1/16、1/32 分辨率的图像特征;
- 轻量解码器 + 选择性特征融合(SFF):GLPNDecoder 接收编码器最后一个特征图(1/32 尺度)上采样到 1/16;随后经过 GLPNSelectiveFeatureFusion(SFF 模块),从注意力图中为每个特征选择并融合局部与全局特征,再上采样到 1/8;此过程重复直至解码特征与原始图像同尺寸。输出经两层卷积后应用sigmoid 激活,逐像素预测深度。
训练目标采用SiLog Loss(SiLogLoss),是深度估计常用的尺度不变对数损失。模型入口为 GLPNForDepthEstimation。
四、自然语言处理:编码器、解码器与序列到序列
Transformer 最初为机器翻译设计,如今几乎成为所有 NLP 任务的默认架构。不同任务适配不同结构:有的适合编码器,有的适合解码器,还有的需要编码器-解码器。
4.1 文本分类:BERT 的编码器范式
BERT 是仅编码器模型,也是首个有效实现深度双向性的模型——通过同时关注左右两侧的词来学习更丰富的文本表示,实现位于 modeling_bert.py。
输入表示:BERT 使用 WordPiece 分词 生成 token 嵌入;用特殊 token[SEP]区分单句与句对,在每段文本开头加特殊 token[CLS];还加入分段嵌入(segment embedding)标识 token 属于句对中的第一句还是第二句。
两个预训练目标:
- 掩码语言建模(MLM):随机掩码一定比例的输入 token,让模型预测它们。这解决了双向性的"作弊"问题——否则模型能看见全部词从而"预测"下一个词。被掩码 token 的最终隐藏状态送入带 softmax 的前馈网络,在整个词表上预测被掩码的词;
- 下一句预测(NSP):模型判断句子 B 是否紧随句子 A。一半时间 B 是真实下一句,另一半是随机句。判断结果送入带 softmax 的前馈网络,在两类(
IsNext与NotNext)上预测。
微调时的"头"机制:
- 文本分类:在基座模型上加序列分类头——线性层接收
[CLS]的最终隐藏状态,线性变换为 logits,交叉熵损失求最可能的标签。对应 BertForSequenceClassification。微调流程见 文本分类任务指南; - Token 分类(如 NER):加 token 分类头——线性层接收每个 token 的最终隐藏状态,对每个 token 计算 logits 与交叉熵损失。对应 BertForTokenClassification。见 Token 分类任务指南;
- 问答:加span 分类头——线性层将最终隐藏状态变换为答案
span的起始与结束 logits,用交叉熵损失找出对应答案的最可能文本区间。对应 BertForQuestionAnswering。见 问答任务指南。
💡 注意:一旦 BERT 预训练完成,做不同任务有多容易!只需在预训练模型上挂一个任务专属的头,把隐藏状态加工成想要的输出即可。
4.2 文本生成:GPT-2 的解码器范式
GPT-2 是仅解码器模型,在大规模文本上预训练,给定提示即可生成令人信服(尽管不一定真实!)的文本,也能完成问答等其他 NLP 任务——尽管没有为此显式训练。实现位于 modeling_gpt2.py。
- BPE 分词与掩码自注意力:GPT-2 用 BPE(字节对编码) 分词并生成 token 嵌入,加上位置嵌入指示 token 位置。输入嵌入经过多个解码器块;每个块内使用掩码自注意力(masked self-attention):GPT-2 不能关注未来 token,只能关注左侧 token。这与 BERT 的
[mask]token 不同——掩码自注意力是用注意力掩码把未来 token 的注意力分数置为0; - 语言建模头与因果目标:解码器输出送入语言建模头,线性变换隐藏状态为 logits;标签是序列中的下一个 token(把 logits 右移一位得到),计算交叉熵损失得到最可能的下一 token。
GPT-2 的预训练目标完全基于因果语言建模(CLM)——预测序列中的下一个词,这使它尤其擅长文本生成类任务。对应 GPT2LMHeadModel。微调见 语言建模任务指南 的因果语言建模部分;生成细节另见 文本生成策略指南。
4.3 摘要:BART 的序列到序列范式
BART 与 T5 这类编码器-解码器模型专为摘要等序列到序列任务设计,实现位于 modeling_bart.py。
架构与预训练:BART 的编码器结构与 BERT 很相似,接收文本的 token 与位置嵌入。BART 的预训练方式是破坏输入、再用解码器重建。与其他编码器使用特定破坏策略不同,BART 可施加任意类型的破坏,但text infilling(文本填充)策略效果最好:把若干段文本替换为一个[mask]token。这很重要——模型必须预测被掩码的 token,从而学会预测缺失 token 的数量。输入嵌入与掩码片段经编码器产生最终隐藏状态;与 BERT 不同,BART 末尾不接预测词的前馈网络。
解码与损失:编码器输出送入解码器,解码器须从编码器输出中预测被掩码的 token 以及任何未破坏的 token——这提供了额外上下文,帮助解码器恢复原文。解码器输出经语言建模头线性变换为 logits,交叉熵损失以右移一位的 token 为标签。对应 BartForConditionalGeneration。微调见 摘要任务指南。
4.4 翻译:BART 的跨语言适配与 mBART
翻译同样是序列到序列任务,可用 BART 或 T5 完成。
BART 适配翻译的方式是:添加一个随机初始化的独立编码器,将源语言映射为可在目标语言中解码的输入;新编码器的嵌入送入预训练编码器,替代原有词嵌入。训练分两步:第一步用模型输出的交叉熵损失更新源编码器、位置嵌入与输入嵌入(模型其他参数冻结);第二步所有参数一起训练。
此后 BART 有了多语言版本mBART(见 model_doc/mbart),针对翻译在多种语言上预训练。微调见 翻译任务指南;生成策略详见 文本生成策略指南。
五、结语:一条主线贯穿所有任务
回看全文,无论是 20ms 一帧的语音特征、16×16 的图像补丁,还是 WordPiece/BPE 切出的文本 token,🤗 Transformers 中所有模型都在遵循同一条主线:把原始输入离散化成序列 → 用编码器/解码器/编码器-解码器架构提取表示 → 挂一个任务专属的头把隐藏状态变换为目标输出(类别、span、边界框、掩码、下一 token 或深度图)。预训练模型是"通用特征提取器",任务头则是"任务专用适配器"——这正是你可以用同一套预训练权重快速解决多种任务的根本原因。据此,在动手微调任意模型前,你都可以先问自己三个问题:我的输入适合哪种离散化方式?哪种架构结构与我的任务最匹配?该任务的输出应该由哪种头来产生?
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考