资讯动态

NLP面试必备:Attention到Transformer与预训练模型核心解析

发布时间:2026/10/13 18:25:11 来源:尧图企业网站定制
1. Attention机制从Seq2Seq瓶颈说起1.1 为什么需要Attention做NLP的基础面试题绕不开Attention。很多同学背了一堆公式张口就是Q、K、V但真被问到“Attention解决了什么问题”时反而答不到点上。秋招面试官问这个概念不是想听你背一遍定义而是想看你对整个序列建模瓶颈的理解。在Attention出现之前序列到序列任务的主流方案是Encoder-Decoder框架典型代表就是LSTM。编码器把整个输入序列压成一个固定长度的语义向量解码器再从这个向量逐步生成输出。这个思路在短句上还行句子一长就完蛋。因为无论输入是5个词还是50个词最终都压缩成一个向量信息量根本不够而且越靠前的词经过多步传播后梯度衰减越严重细节早就丢了。你可以把它想象成要把一本厚书的内容概括成一句话然后再让别人根据这句话把书复述出来——信息损失是不可避免的。Attention的核心思想就是“不再压缩全部信息而是在每一步解码时动态地从输入序列中挑选最相关的部分”。通俗点说就像人类翻译句子时眼睛会在原文上扫来扫去每次看最需要翻译的那几个词而不是把整句话记在脑子里再闭眼翻译。这个机制让模型能够随时回溯到输入序列的任意位置直接建立“输出词”与“输入词”之间的依赖关系绕开了信息瓶颈问题。对面试来说还有一层进阶理解Attention本质上是“让模型自己学会分配注意力权重”。它不关心输入顺序有多少步每一步都可以直接接触到整个序列所以梯度传递路径变短长距离依赖问题也得到了一定缓解。后来Transformer完全抛弃RNN纯粹靠Attention堆叠靠的就是这个特性。1.2 Attention的数学原理与计算流程面试中手推Attention是保留项目。你要能写出最核心的公式并且用通俗语言解释每一步在干什么。经典的加性注意力由Bengio等人提出但面试更常考的是缩放点积注意力Scaled Dot-Product Attention。给定查询向量q和键向量k注意力权重的计算方式是$$ score q \cdot k^T $$然后用Softmax归一化得到权重$$ \alpha_i \frac{exp(score_i)}{\sum_{j} exp(score_j)} $$最后对值向量v做加权求和$$ Attention(q, K, V) \sum_{i} \alpha_i v_i $$在自注意力场景中Q、K、V都由同一个输入X乘以不同的权重矩阵得到。Q代表“我要找什么”K代表“我有什么”V代表“我实际的内容”。Q和K做点积算的是“匹配程度”匹配分越高对应的V在输出中占的权重就越大。以翻译“I love NLP”到中文为例当解码器要生成“我”这个词时q会跟输入中每个位置的k做点积。因为“I”和“我”语义对应这个位置的得分就最高Softmax之后权重接近1其他位置趋近0。加权求和后输出向量主要包含“I”的信息后续分类层就能比较准确地预测出“我”。为什么叫“缩放”点积因为当维度d_k比较大时点积的数值会变得很大Softmax的梯度会趋近于0所以除以√d_k来缩放。面试官大概率会追问这个细节后面章节我专门展开。1.3 从Soft Attention到Self-Attention面试时你可能被问到Soft Attention、Hard Attention、Self-Attention的区别。Soft Attention是端到端可微的所有位置的权重都参与加权求和每个位置都会得到一部分注意力只不过有多有少。Hard Attention则是一个离散的选择过程只选中某一个位置训练时要用强化学习或者蒙特卡洛采样估计梯度复杂度高用得少。Self-Attention则改变了Q、K、V的来源。传统Attention中Q来自解码器K和V来自编码器而Self-Attention中Q、K、V全都来自同一个输入序列。它的作用是建立序列内部每个位置与其他所有位置的直接依赖。举个例子理解Self-Attention的效果在句子“那只猫因为太饿所以跑得很快”里模型要判断“它”指代什么RNN要一步步把信息传过来可能传着传着就丢了而Self-Attention让“它”直接和“猫”做一次点积计算权重分拉满一步到位。这也是为什么Transformer能比RNN更好地处理长距离依赖。面试回答这类问题时建议用“传统Attention是跨序列的信息交互Self-Attention是序列内部的信息交互”来总结简洁有力面试官会点头的。2. TransformerAttention的集大成者2.1 整体架构与核心组件Transformer是“Attention Is All You Need”这篇论文提出的架构2017年之后几乎重塑了NLP。面试中Transformer的整体结构几乎是必考的而且经常让现场画图。Transformer的主体包括Encoder和Decoder两大部分。Encoder由N个相同的层堆叠而成每层包含两个子层第一个是Multi-Head Self-Attention第二个是Position-wise Feed-Forward Network。每个子层后面都加了残差连接和Layer Normalization所以每个子层的输出可以写成$$ LayerNorm(x Sublayer(x)) $$Decoder的结构类似但多了一个子层Masked Multi-Head Self-Attention以及一个Cross-Attention层。Masked是为了防止解码时看到未来的信息因为在生成任务中当前位置只能关注到它之前的内容。Cross-Attention中Q来自解码器K和V来自编码器的输出这是Decoder和Encoder进行信息交互的关键。残差连接防止深层网络梯度消失LayerNorm加速训练稳定Feed-Forward层给网络增加非线性变换能力。这些细节面试都可能问到尤其是LayerNorm和BatchNorm的区别——NLP中序列长度可变BatchNorm在batch维度上归一化会受序列长度影响而LayerNorm在特征维度上归一化更适合Transformer。2.2 Multi-Head Attention详解单一注意力头只能学一种“匹配模式”Multi-Head把Q、K、V分别投影到多个子空间并行做多次注意力计算最后拼接再线性变换。公式如下$$ MultiHead(Q,K,V) Concat(head_1,...,head_h)W^O $$其中每个head是$$ head_i Attention(QW_i^Q, KW_i^K, VW_i^V) $$通俗理解一个头负责捕捉语法关系一个头负责捕捉指代关系一个头负责捕捉位置相邻关系。多个头并行工作相当于多个专家从不同角度看同一个句子把不同维度的信息都提取出来。面试官可能追问head数量怎么选论文里用了8个头维度64。如果模型总维度是512每个头分到64维并行计算后拼接维度又回到512。这个设计既保证了模型容量又控制了参数量。讲到这里还可以补充一点并不是所有任务都适合多头有些实验表明机器翻译任务中多头效果更好但在某些小规模数据上过多的头反而会带来冗余需要调参。还有一个高频题Transformer为什么要用残差因为Multi-Head Attention和Feed-Forward都经过非线性变换堆到很深的时候梯度容易消失残差连接相当于给梯度开了一条高速公路。2.3 Positional Encoding的作用Self-Attention本身不感知位置信息。把句子“我打你”和“你打我”输入Attention层计算点积的结果是一模一样的因为词与词之间的交互完全对称模型只知道“谁和谁有关系”不知道“谁是主语谁是宾语”。这对语言理解来说等于废了。Transformer用Positional Encoding给每个位置注入位置信息常见做法是用不同频率的正弦和余弦函数$$ PE_{(pos,2i)} sin(pos / 10000^{2i/d_{model}}) $$$$ PE_{(pos,2i1)} cos(pos / 10000^{2i/d_{model}}) $$也可以直接用可学习的位置嵌入。面试时重点说清楚为什么用正弦函数一是可以让模型外推长度因为三角函数是连续的理论上可以泛化到训练时没见过的长度二是正弦余弦之间可以通过线性变换相互表示方便模型捕捉相对位置关系。常见误区是有人会把Positional Encoding和Position Embedding混为一谈。前者是固定函数生成后者是随机初始化学习出来的。BERT用的是后者的思路Transformer原版用的是前者。都可行面试时能区分讲明白就是加分项。另外近年很多新模型用旋转位置编码RoPE、相对位置编码ALiBi等方案面试如果聊到可以简单提一句绝对位置编码在长文本外推上表现一般相对位置编码让模型更关注词与词之间的距离关系效果更稳。这部分属于进阶知识基础弱的同学先把正弦编码理解透就行。3. 预训练模型从Word2Vec到BERT的演进3.1 静态词向量与动态词向量的区别预训练模型的面试题通常先从Word2Vec和GloVe问起再过渡到ELMo、BERT。很多同学把“预训练”理解成“BERT之后才有的”其实Word2Vec也算预训练模型只不过它是静态的。Word2Vec通过Skip-gram或CBOW训练得到每个词的固定向量。问题是同一个词在不同上下文里的意思是一样的——比如“苹果”在“苹果很好吃”和“苹果发布了新手机”里向量完全相同这就会造成歧义无法区分。ELMo引入了上下文相关的思路。它不是给每个词一个固定向量而是训练一个双向LSTM语言模型每个词经过两层LSTM后把内部状态加权组合成动态词向量。同样一个“苹果”在上下文中对应的向量会因为周围词不同而不同。但ELMo用的是LSTM特征提取能力有限而且双向LSTM只是两个方向的拼接并不是真正同时看到上下文。BERT就彻底把Transformer拿来当特征提取器基于大规模语料做预训练然后把学出的参数迁移到下游任务上微调。面试里需要把这些模型串成一条演进线静态词向量 - 动态词向量 - 基于Transformer的预训练模型。这条线讲清楚了面试官会觉得你的知识体系是完整的。3.2 GPT与BERT的架构差异面试最经典的对比题是GPT和BERT。虽然都用Transformer但“长得像”不等于“思路一样”。GPT用的是Transformer的Decoder部分核心是自回归语言模型。训练目标是根据前面的词预测下一个词只能看到左侧上下文。BERT用的是Transformer的Encoder部分核心是Masked Language Model随机把输入中的一些词掩码然后让模型根据左右两侧的上下文预测被掩码的词。本质区别就是“单向”还是“双向”。举个例子帮助理解句子“我爱[掩码]”BERT看到左边的“我爱”和右边的空可以猜“自然语言处理”或“吃火锅”GPT只能看到“我爱”两个字要做预测难度更大但更符合生成任务的逻辑。面试中如果你提到“BERT的双向能力让它更强”面试官可能会反问那为什么GPT后来在生成任务上碾压BERT你要能回答BERT的结构做生成天生不自然它的Masked Language Model训练目标不适合一步步生成文本而GPT自回归的结构天然适合生成。再加上后来GPT用更大规模的数据和参数scale能力就上来了。这里体现出你对模型设计理念的理解不是单纯背优劣。3.3 其他重要预训练模型除了GPT和BERT面试还可能问到RoBERTa、ALBERT、T5、XLNet等。不用每个都背得滚瓜烂熟但至少要清楚它们在什么基础上做了什么改进。RoBERTa可以说成“更用心的BERT”。它用了更多数据、更长训练时间、去掉Next Sentence Prediction任务只用MLM把动态Masking加进来效果全面超越BERT。ALBERT的核心是参数共享和矩阵分解大幅减少参数量还引入了Sentence Order Prediction任务。XLNet结合了自回归和双向建模的优点通过排列语言模型来“假装双向”配合Transformer-XL的片段级循环机制长文本建模更强。T5把各种NLP任务都统一成“text-to-text”的格式输入输出都是文本像翻译一个句子一样处理所有任务。面试不建议把所有模型罗列一遍就完事。更好的策略是拿一个模型比如BERT做锚点说明它的局限然后讲清楚另一个模型怎么解决这个局限这样显得思考完整。比如提到BERT时代每个预训练模型越来越重、训练成本高于是出现了蒸馏技术把大模型压缩成小模型提到长文本问题就有了Transformer-XL和Longformer。这种关联式记忆比死记硬背靠谱得多。4. 秋招面试高频考点与答题思路4.1 Attention为什么除以根号d_k这是Attention配套问题里出现频率极高的一道。如果你只会背结论“防止梯度消失”面试官一般是不会满意的。推导一下假设q和k的各个维度都是均值为0、方差为1的随机变量点积q·k的结果就是d_k个乘积的和。每个独立的乘积方差是1相加后方差就变成d_k标准差变成√d_k。也就是说随着维度d_k增大点积的数值范围会跟着变大导致Softmax的输入过大。Softmax在输入很大的时候会倾向于输出接近one-hot的分布即某个位置概率接近1其他位置接近0。这样梯度会变得非常小因为Softmax函数在饱和区的导数趋近于0。除以√d_k后点积的方差重新回到1Softmax的输入落在梯度较大的区域训练更稳定。如果面试官再追问“为什么是√d_k而不是d_k”你可以回答除以d_k会把方差变成1/d_k多出一个系数可能导致信号太弱√d_k刚好把方差还原成1这是最自然的选择。能推导到这一步基本可以过关了。4.2 Transformer和LSTM的对比这也是每年秋招必考题。可以从几个维度回答并行性、长距离依赖、可解释性、复杂度。LSTM按时间步顺序处理序列当前时刻必须等前一时刻算完才能继续无法并行训练慢。Transformer的Self-Attention一次性看到整个序列可以同时计算所有位置的注意力GPU并行效率极高。长距离依赖上LSTM通过门控结构一步步传递信息理论上能记住长信息但实际容易丢失Transformer通过直接建立任意两个位置之间的连接路径长度是O(1)不管隔多远都能一步到位。复杂度上Self-Attention的时间和空间复杂度是O(n^2)LSTM是O(n)。所以在长文本上Transformer会变得很贵这也是后面很多模型专门做稀疏注意力、分块注意力来降低复杂度的原因。面试时如果能把“优势”和“代价”都讲出来会比单纯吹Transformer有深度。另一个可以补充的点是LSTM天然有顺序信息而Transformer需要额外加位置编码。因此对位置敏感的序列任务比如时间序列Transformer并非天然占优这也是面试里诱答的一个坑。你要主动说“Transformer的强大来自大规模预训练和并行能力但不意味着在所有序列任务上都无脑碾压RNN”这个观点很能体现你的判断力。4.3 BERT的预训练任务和Fine-tuningBERT预训练有两个任务一个是Masked Language ModelMLM一个是Next Sentence PredictionNSP。MLM随机把15%的token替换成[MASK]其中80%真的换成[MASK]10%换成随机词10%保持不变。这个设计的目的是缓解预训练和微调阶段的不一致微调的时候不会有[MASK]如果预训练全部用[MASK]模型会对这个特殊标记过于依赖。NSP是判断两个句子是不是连续的语料帮助模型理解句子间的关系。后来RoBERTa用实验证明NSP对很多任务帮助不大甚至可能干扰MLM的学习所以把NSP去掉了。面试时说这个演进能加分。Fine-tuning也经常出题。常见做法是把BERT最后一层对应的[CLS]向量接一个分类器做句子级任务做序列标注任务时则用每个token对应的输出向量预测标签。BERT的微调非常依赖学习率设置一般用较小的学习率2e-5到5e-5太大容易把预训练学到的知识冲掉。这也是我在实际项目中踩过坑的地方第一次微调时直接用默认学习率模型开始几步loss狂降然后突然暴增后来调小学习率才稳住。5. 面试实战手撕代码与自查清单5.1 手撕一个Scaled Dot-Product Attention求职季很多公司会让现场写Attention代码。别慌核心代码其实很短。以下是一个用PyTorch的实现import torch import torch.nn as nn import torch.nn.functional as F class ScaledDotProductAttention(nn.Module): def __init__(self, d_k): super().__init__() self.d_k d_k def forward(self, q, k, v, maskNone): scores torch.matmul(q, k.transpose(-2, -1)) / (self.d_k ** 0.5) if mask is not None: scores scores.masked_fill(mask 0, float(-inf)) attn_weights F.softmax(scores, dim-1) output torch.matmul(attn_weights, v) return output, attn_weights注意几个细节。scores计算完一定要除以d_k的平方根面试官会盯着这个。mask的处理是用masked_fill把非法的位置压成负无穷这样Softmax之后的权重会是0。写代码时维度别搞混q是(batch, heads, seq_len, d_k)k是(batch, heads, seq_len, d_k)k转置最后两个维度后做矩阵乘。面试时如果让你实现完整的Transformer编码器层也别慌记住结构顺序Multi-Head Attention - Add Norm - Feed-Forward - Add Norm。把每个子模块拆开写用nn.Module封装逻辑清晰即可。手撕代码的核心不是追求一遍跑通而是展示你对结构和维度的理解。5.2 秋招NLP基础自查清单把高频考点整理成一份清单面试前过一遍比盲目刷题效率高得多。知识点核心回答要点容易踩的坑Attention为什么有效解决Seq2Seq信息瓶颈直接建立远程依赖只答“让模型关注重点”不够为什么除以√d_kSoftmax饱和区梯度小缩放让方差回到1忘记推导点积方差Self-Attention和传统Attention区别QKV来源不同序列内部vs跨序列混淆两者Transformer结构Encoder、Decoder、Multi-Head、残差、LayerNorm画图时漏掉MaskedBERT和GPT的本质双向编码vs单向自回归只背名字不讲训练目标静态词向量和动态词向量是否随上下文变化把ELMo当静态模型预训练微调注意事项小学习率、任务适配忽略domain gap面试时还可以准备一个自己实际做过的NLP项目把上面这些知识点串进去讲。比如你做过文本分类就说“我用BERT做分类时发现长文本的注意力集中在几个关键词上于是参考Attention的可解释性分析调整了输入长度准确率提升了几个点”。有项目支撑的面试回答比纯背八股有说服力太多。5.3 手撕Transformer完整代码的关键思路有些面试会升级难度要求现场写一个transformer encoder layer。这里给一个实战中可用的写法也可以作为你平时背诵的蓝本。class MultiHeadSelfAttention(nn.Module): def __init__(self, d_model, n_head): super().__init__() self.n_head n_head self.d_k d_model // n_head 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): batch, seq_len, _ x.size() q self.w_q(x).view(batch, seq_len, self.n_head, self.d_k).transpose(1, 2) k self.w_k(x).view(batch, seq_len, self.n_head, self.d_k).transpose(1, 2) v self.w_v(x).view(batch, seq_len, self.n_head, self.d_k).transpose(1, 2) scores torch.matmul(q, k.transpose(-2, -1)) / (self.d_k ** 0.5) attn torch.softmax(scores, dim-1) out torch.matmul(attn, v) out out.transpose(1, 2).contiguous().view(batch, seq_len, -1) return self.w_o(out)需要注意view和transpose的顺序。先把最后一个维度拆成n_head和d_k再transpose把head维度提到前面最后注意contiguous否则view会报错。这个细节写代码时经常被卡住提前练熟。6. 秋招准备过程中的几点实战心得秋招复习NLP基础最忌讳的就是贪多嚼不烂。我看过太多同学把各种冷门模型全部背一遍结果问到一个“LSTM为什么缓解梯度消失”就卡壳。面试官要的不是百科全书而是你对核心脉络的把握。建议一条主线从Seq2Seq到Attention从Attention到Transformer从Transformer到BERT。这三步能串联讲通NLP基础的大半壁江山就稳了。另一个心得是画图和手推公式要落到纸面。你在脑子里觉得自己懂了和白板画一遍完全是两种状态。面试现场让你画Transformer结构图很多同学画着画着就乱了多是平时没练过。手机里存几张结构图每天默画一遍坚持一周效果立竿见影。关于刷题平台力扣热题对NLP算法岗帮助有限。算法题还是要刷常考的二分、贪心、动态规划但同时也要保证NLP基础知识的复习时间。我当时给自己定的比例是算法六成、NLP基础四成后来又根据投递的岗位做了调整偏算法工程的多刷代码题偏应用的多看模型细节和项目。模拟面试也很重要。找一位同方向的同学互相提问专挑对方薄弱的地方问远比一个人闷头背效率高。我在模拟面试过程中被问到“BERT的CLS向量到底能代表什么”当场语塞后来深入查了资料才算补上。这些问题在网上八股清单里不一定出现但实际面试里真能遇到。最后再说一点NLP基础面试题的根本其实是对“语言建模”的理解。不管Attention、Transformer还是预训练模型本质上都是在解决“如何更好地表示语言”这个问题。想清楚这一层你背的所有细节就有了归处回答起来也会更有底气。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑