本文是「速通 AI」系列的配套面试指南,覆盖从数学基础到 Agent 开发的 86 道高频面试题(含 2 道综合题)。每道题附完整解答,可直接用于面试准备。
使用建议:先通读「速通 AI」系列文章理解原理,再用本文检验掌握程度。面试前重点复习自己答不上来的题目。
最后更新:2026年7月。使用前建议结合实际项目经验理解记忆。
1. 数学基础(第 1 篇)
Q1:梯度下降的原理是什么?学习率过大/过小分别会怎样?
梯度下降是通过迭代更新参数来最小化损失函数的优化算法。核心公式:
$$ \theta_{\text{new}} = \theta_{\text{old}} - \eta \cdot \nabla L(\theta) $$其中 $\eta$ 是学习率,$\nabla L$ 是损失函数对参数的梯度。
学习率的影响:
- 太大:步子跨过最优解,来回震荡甚至发散。例如 $y=(x-3)^2$,$\eta=1.0$ 时 $x$ 在 0 和 6 之间来回跳。
- 太小:收敛极慢,可能需要数万步才能到达最优点。
- 刚好:稳定收敛,远处大步走、近处小步挪(梯度自动减速)。
实际训练中通常从 0.001 开始,观察 loss 曲线:震荡就减小,下降太慢就增大。
面试时怎么讲:“梯度下降就是’沿着最陡的方向下山’。每步算一次梯度(哪个方向最陡),往反方向走一步。学习率控制步子大小——太大会震荡,太小走不动。实际中用 Adam 或 SGD+动量,不用原始梯度下降。”
面试官可能追问:“学习率过大除了震荡还可能发生什么?” → 答案:loss 爆炸(NaN),参数更新后进入损失函数的"悬崖"区域,梯度突然变大导致参数飞出去。解决方案:梯度裁剪 + 学习率 warmup。
Q2:什么是反向传播算法?它的数学本质是什么?
反向传播是高效计算神经网络中每个参数梯度的算法。数学本质是链式法则。
对于复合函数 $y = f(g(x))$,链式法则给出 $\frac{dy}{dx} = f'(g(x)) \cdot g'(x)$。
在神经网络中,损失 $L$ 是多层复合函数。反向传播从损失出发,逐层往回计算每个参数的"责任":
$$ \frac{\partial L}{\partial W} = \frac{\partial L}{\partial z} \cdot \frac{\partial z}{\partial W} $$每一步都很简单(局部导数),但组合起来就能高效计算复杂网络的所有梯度。这就是为什么反向传播让训练深层网络成为可能。
常见误区:以为反向传播是一种独立的算法。实际上它只是链式法则的系统性应用——前向传播构建计算图,反向传播沿图计算梯度。
面试时怎么讲:“反向传播就是链式法则的系统性应用。从损失出发,逐层往回算每个参数的梯度。关键点:每层的梯度 = 上游传回来的误差信号 × 本层的局部梯度。这就是为什么激活函数的导数很重要——如果导数接近 0,梯度就会在这一层’断掉’。”
Q3:Sigmoid 函数的导数是什么?为什么会出现梯度消失?
Sigmoid 导数的推导结果:
$$ \sigma'(x) = \sigma(x) \cdot (1 - \sigma(x)) $$这个结果意味着导数可以直接用函数值计算,不需要重新算指数函数。
梯度消失的原因:当 $x$ 很大时 $\sigma(x) \approx 1$,$\sigma'(x) \approx 0$;当 $x$ 很小时 $\sigma(x) \approx 0$,$\sigma'(x) \approx 0$。Sigmoid 的最大导数仅为 0.25(当 $x=0$ 时)。在网络中每经过一层 Sigmoid,梯度至少衰减为原来的 1/4。经过 10 层后梯度衰减为 $0.25^{10} \approx 10^{-6}$——参数几乎不更新,网络"学不动了"。
常见误区:很多人以为 Sigmoid 的梯度消失是因为"导数小于 1"。实际上任何导数小于 1 的函数连乘都会消失,Sigmoid 的问题更严重——它的最大导数只有 0.25,消失速度比 ReLU(正区间导数恒为 1)快得多。
面试时怎么讲:“Sigmoid 把输入压缩到 0-1,但问题是导数最大只有 0.25。多层连乘后梯度指数衰减——10 层后梯度只剩 0.25 的 10 次方,约等于零。这就是为什么深层网络用 ReLU(正区间导数恒为 1,不会消失)。”
Q4:ReLU 和 Sigmoid 的区别?为什么 ReLU 成为主流?
| 维度 | Sigmoid | ReLU |
|---|---|---|
| 公式 | $\frac{1}{1+e^{-x}}$ | $\max(0, x)$ |
| 输出范围 | (0, 1) | [0, +∞) |
| 正区间梯度 | 最大 0.25,会消失 | 恒为 1,不消失 |
| 计算效率 | 需要指数运算 | 只需一次比较 |
| 激活模式 | 所有神经元都有输出 | 部分神经元输出 0(稀疏激活) |
ReLU 成为主流的三个原因:
- 正区间梯度恒为 1:不会消失,支持训练深层网络
- 计算效率极高:$\max(0, x)$ 比 $e^{-x}$ 快得多
- 稀疏激活:部分神经元被"关闭",相当于天然正则化
ReLU 的代价是"死亡 ReLU"问题(负区间梯度恒为 0),解决方案包括 Leaky ReLU、GELU/Swish。
常见误区:以为 ReLU 没有缺点。实际上"死亡 ReLU"是真实存在的问题——如果一个神经元的输入持续为负,它就永远不会更新,相当于"死了"。Leaky ReLU 给负区间一个小斜率(如 0.01),GELU 用平滑曲线替代硬切换。
面试时怎么讲:“ReLU 的核心优势是正区间梯度恒为 1,不会消失。代价是负区间梯度为 0(死亡 ReLU)。现代模型用 GELU 或 Swish 替代——它们在负区间有小梯度,不会完全死掉。”
面试官可能追问:“GELU 和 ReLU 的区别?” → GELU 是平滑的 ReLU,在 $x=0$ 处不是硬切换而是渐变。GPT/BERT 用 GELU,ResNet 用 ReLU。GELU 的表达能力更强但计算稍慢。
Q5:Softmax 函数的作用?为什么要用 $e^x$?
Softmax 把一组任意实数转换为概率分布(所有值 > 0,且和为 1):
$$ \text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}} $$用 $e^x$ 的三个原因:
- $e^x > 0$ 保证所有输出为正数(概率不能为负)
- $e^x$ 单调递增(保持大小关系)
- $e^x$ 的导数是自己(计算方便)
数值稳定性:输入很大时 $e^x$ 会溢出。解决方案是减去最大值:$\text{softmax}([1000, 1001, 1002]) = \text{softmax}([-2, -1, 0])$,结果完全一样但不会溢出。
常见误区:以为 Softmax 只用于分类任务的输出层。实际上 Softmax 在 Transformer 的注意力机制中也大量使用——计算注意力权重时必须用 Softmax 把分数归一化为概率分布。
面试时怎么讲:“Softmax 把任意实数变成概率分布——所有值大于 0,和为 1。用 e 的 x 次方是因为它保证正数且单调递增。数值稳定性靠减最大值解决。不只是分类输出层,Transformer 的注意力权重也用 Softmax。”
面试官可能追问:“Softmax 的温度参数 T 有什么用?” → $T$ 控制输出的"尖锐程度"。$T \rightarrow 0$ 时接近 argmax(确定性),$T \rightarrow \infty$ 时接近均匀分布(随机性)。推理时用 $T < 1$ 让输出更确定,用 $T > 1$ 让输出更多样。
Q6:什么是过拟合?如何用正则化解决?L1 和 L2 正则化的区别?
过拟合:模型在训练数据上表现很好,但在新数据上表现差——就像"死记硬背练习题,考试遇到新题就不会"。
面试时怎么讲:“过拟合就是模型把训练数据的噪声也学了。解决方法:L1/L2 正则化(限制权重大小)、Dropout(随机丢弃神经元)、数据增强(增加训练数据多样性)、早停(验证集 loss 不再下降就停)。”
正则化通过在损失函数中加入惩罚项,限制模型复杂度:
$$ L_{\text{total}} = L_{\text{original}} + \lambda \cdot \text{惩罚项} $$| 特性 | L1 (Lasso) | L2 (Ridge) |
|---|---|---|
| 惩罚项 | $\sum \|w_i\|$ | $\sum w_i^2$ |
| 效果 | 使部分权重变为 0(特征选择) | 使所有权重趋近 0(权重衰减) |
| 几何直觉 | 菱形约束,容易在角点相交 | 圆形约束,交点通常不在坐标轴上 |
| 适用场景 | 特征很多,需要筛选 | 特征都有用,防止过拟合 |
实操建议:大多数场景用 L2(权重衰减)就够了。如果特征维度很高(如 NLP 的 one-hot)且怀疑只有少数特征有用,用 L1 做特征选择。实际中常用 Elastic Net(L1 + L2 的组合)。
常见误区:以为正则化是解决过拟合的唯一方法。实际上数据增强、Dropout、早停(Early Stopping)、减少模型复杂度都是有效的抗过拟合手段。正则化只是其中之一。
面试官可能追问:“除了正则化还有什么方法防止过拟合?” → 数据增强(增加训练数据多样性)、Dropout(随机丢弃神经元)、早停(验证集 loss 不再下降时停止训练)、减少模型参数量、交叉验证。
Q7:什么是最大似然估计?它和交叉熵损失有什么关系?
最大似然估计(MLE):选择让观测数据出现概率最大的参数。
例如硬币抛 10 次出现 7 次正面,MLE 的答案是 $p = 0.7$——这很直觉。
关键联系:交叉熵损失 = 负对数似然。当你最小化交叉熵时,你实际上在最大化似然——让模型的参数使得观测到的训练数据出现的概率最大。这就是为什么交叉熵是分类任务的标准损失函数——它有坚实的概率论基础。
面试时怎么讲:“最大似然估计就是选让观测数据出现概率最大的参数。交叉熵 = 负对数似然——最小化交叉熵就是最大化似然。这就是为什么分类任务用交叉熵损失——它有概率论基础,不是随便选的。”
常见误区:以为 MLE 总是正确的。实际上 MLE 对小样本容易过拟合——抛 3 次全是正面,MLE 算出 p=1,显然不对。需要贝叶斯方法(加先验)或正则化。
Q8:梯度下降有哪几种变体?SGD、Mini-batch、Batch 的区别?
| 方法 | 每步使用的数据 | 优点 | 缺点 |
|---|---|---|---|
| 批量梯度下降(BGD) | 全部数据 | 梯度方向最准确 | 数据量大时极慢 |
| 随机梯度下降(SGD) | 1 个样本 | 快 | 方向不稳定 |
| 小批量梯度下降(MBGD) | 32/64/128 个样本 | 兼顾速度和稳定性 | 需要调 batch size |
实际训练中几乎都用 MBGD。batch size 通常从 32 开始,根据 GPU 显存调整。SGD 的随机噪声反而有助于跳出局部最优。
常见误区:以为 batch size 越大越好。实际上大 batch 会让优化陷入"尖锐最小值"(sharp minima),泛化性变差。小 batch 的噪声反而有助于找到"平坦最小值"(flat minima),泛化性更好。
常见误区:以为 Adam 总是比 SGD 好。实际上 Adam 的泛化性通常不如 SGD+动量——Adam 容易陷入"尖锐最小值"(sharp minima),在测试集上表现差。CV 任务(对泛化性要求高)通常用 SGD+动量。
面试官可能追问:“Adam 的一阶矩和二阶矩是什么?” → 一阶矩 $m_t$ 是梯度的指数移动平均(方向),二阶矩 $v_t$ 是梯度平方的指数移动平均(幅度)。一阶矩提供动量,二阶矩提供自适应学习率。
Q9:矩阵乘法在神经网络中扮演什么角色?为什么 GPU 适合做矩阵运算?
神经网络的前向传播本质上就是一连串的矩阵乘法:
$$ \text{output} = \text{input} \cdot W + b $$每一层都在做"输入 × 权重矩阵 + 偏置"。
GPU 适合的原因:矩阵乘法的本质是"大量独立的乘加运算",这些运算是完全并行的。CPU 有少量强核心(如 8 个),GPU 有大量计算核心,擅长并行处理简单的乘加运算(如几千个核心同时做 $a \times b + c$)。矩阵乘法正好适合 GPU 的"人海战术"。
面试时怎么讲:“神经网络的前向传播就是一连串矩阵乘法。CPU 有 8 个强核心,GPU 有几千个弱核心。矩阵乘法的每个元素独立计算——GPU 的几千个核心同时算,比 CPU 的 8 个核心串行算快几百倍。”
常见误区:以为 GPU 什么都比 CPU 快。实际上 GPU 擅长并行的简单计算(矩阵乘法),但串行复杂逻辑(如 if/else 分支)CPU 更快。GPU 的优势是"人海战术",不是"单兵作战"。
Q10:什么是特征值和特征向量?PCA 降维的原理?
对于矩阵 $A$,如果 $A\mathbf{v} = \lambda\mathbf{v}$,则 $\mathbf{v}$ 是特征向量,$\lambda$ 是特征值。
PCA 降维原理:
- 计算数据的协方差矩阵
- 求协方差矩阵的特征值和特征向量
- 特征值大的特征向量 = 数据变化最大的方向
- 只保留前 $k$ 个最重要的方向,丢弃其他
核心思想:100 个特征中,前 3 个"最重要的方向"就能解释 95% 的数据变化。维度从 100 降到 3,但只损失 5% 的信息。
面试时怎么讲:“PCA 找数据变化最大的方向(主成分),把数据投影到这些方向上。100 维数据,前 3 个主成分可能就解释 95% 的方差——维度从 100 降到 3,只损失 5% 信息。”
常见误区:以为 PCA 总是好的。实际上 PCA 假设数据的主要结构是线性的,对非线性数据效果差(此时需要用 Kernel PCA 或自编码器)。另外 PCA 会丢失方差小但对分类重要的维度。
面试官可能追问:“PCA 和 t-SNE 的区别?” → PCA 是线性降维,保持全局结构,速度快。t-SNE 是非线性降维,保持局部结构,速度慢但可视化效果好。PCA 适合预处理,t-SNE 适合可视化。
2. 深度学习与 PyTorch(第 2 篇)
Q11:神经网络为什么需要激活函数?没有激活函数会怎样?
没有激活函数时,无论多少层网络,本质上都只是一个线性变换(矩阵连乘还是矩阵)。两层网络合并后:$y = W_3(W_2(W_1 x + b_1) + b_2) + b_3 = Wx + b$——等于一层。
激活函数引入非线性,让网络能够拟合任意复杂的函数。这就是"万能近似定理":一个有足够多神经元的单隐层网络,可以逼近任意连续函数。
常见误区:以为激活函数越多越好。实际上每加一层激活函数都会引入信息损失(如 ReLU 会把负值清零)。深度网络的关键是平衡非线性和信息保留——残差连接就是为了让信息能"绕过"激活函数直接传递。
面试时怎么讲:“没有激活函数,多层网络等于一层——矩阵连乘还是矩阵。激活函数引入非线性,让网络能拟合任意复杂函数。但不能用太多——ReLU 会把负值清零,信息会丢失。所以用残差连接让信息能’绕过去’。”
面试官可能追问:“万能近似定理说单隐层就够了,为什么还要深层网络?” → 单隐层需要指数级多的神经元才能逼近复杂函数,深层网络用更少的参数就能学到层次化的特征(底层→边缘,中层→纹理,高层→物体)。
Q12:反向传播的完整计算过程?链式法则如何应用?
以 2 层网络为例:
前向传播:$z_1 = W_1 x + b_1$ → $a_1 = \sigma(z_1)$ → $z_2 = W_2 a_1 + b_2$ → $L$
反向传播(从右往左):
- $\frac{\partial L}{\partial z_2} = z_2 - y$(损失对输出的梯度)
- $\frac{\partial L}{\partial W_2} = (z_2 - y) \cdot a_1^T$(输出层权重的梯度)。交叉熵 + Softmax 组合下,$\delta_2 = \hat{y} - y$ 就是预测值减真实值。
- $\frac{\partial L}{\partial a_1} = W_2^T \cdot (z_2 - y)$(误差传回隐藏层)
- $\frac{\partial L}{\partial z_1} = \frac{\partial L}{\partial a_1} \odot \sigma'(z_1)$(通过激活函数导数过滤)
- $\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial z_1} \cdot x^T$(隐藏层权重的梯度)
每层的梯度 = 误差信号 × 激活函数导数 × 输入信号。
面试时怎么讲:“反向传播就是链式法则的系统性应用。从损失出发,逐层往回算每个参数的梯度。关键点:每层的梯度 = 上游传回来的误差信号 × 本层的局部梯度(激活函数导数 × 输入)。这就是为什么激活函数的导数很重要——如果导数接近 0(如 Sigmoid),梯度就会在这一层’断掉’。”
Q13:梯度消失和梯度爆炸的原因和解决方案?
梯度消失:激活函数导数 < 1(如 Sigmoid 最大导数仅 0.25),多层连乘后指数衰减。深层参数几乎不更新。
梯度爆炸:权重矩阵谱范数 > 1,多层连乘后指数增长。loss 变为 NaN 或震荡发散。
面试时怎么讲:“梯度消失和爆炸的根因是链式法则的连乘效应。消失:导数 < 1 连乘后趋近 0,深层参数不更新。爆炸:导数 > 1 连乘后趋近无穷,loss 变 NaN。解决:ReLU(正区间导数恒为 1)、残差连接(梯度高速公路)、梯度裁剪(限制梯度最大值)。”
| 问题 | 解决方案 |
|---|---|
| 梯度消失 | ReLU(正区间导数恒为 1)、残差连接(梯度高速公路)、BatchNorm |
| 梯度爆炸 | 梯度裁剪(clip_grad_norm)、权重初始化(He/Xavier)、BatchNorm |
Q14:CNN 的卷积操作原理?参数共享和平移不变性是什么?
卷积核(如 3×3 的小矩阵)像"滑动窗口"在图片上滑动,检测局部特征。
参数共享:同一个卷积核用在图片的所有位置——不管图片多大,参数量都是 3×3 = 9 个。
平移不变性:因为参数共享,猫在图片左上角和右下角,识别方法是一样的。
三大优势:
- 局部感知:每个输出只看 3×3 区域
- 参数共享:同一套参数检测同一特征
- 平移不变性:目标在任何位置都能被检测到
权重共享将参数量从 $C_{\text{in}} \times C_{\text{out}} \times k^2 \times H \times W$ 降为 $C_{\text{in}} \times C_{\text{out}} \times k^2$,是 CNN 能处理大图像的根本原因。例如输入 224×224×3,全连接需要约 1.5 亿参数,CNN 只需几千个。
常见误区:以为 CNN 只能处理图像。实际上 1D-CNN 也广泛用于文本分类(TextCNN)和时间序列分析。CNN 的核心是局部特征提取——只要数据有局部结构(时间序列的窗口、文本的 n-gram),CNN 就适用。
面试时怎么讲:“CNN 用卷积核滑动检测局部特征。核心优势:参数共享(同一个核扫全图,参数量与图片大小无关)+ 平移不变性(猫在左上角和右下角都能识别)。这就是为什么 CNN 能处理大图片——全连接要 1.5 亿参数,CNN 只要几千个。”
面试官可能追问:“CNN 的感受野是什么?怎么计算?” → 感受野是输出特征图上一个像素对应原始输入的区域大小。3×3 卷积堆 2 层,感受野 = 5×5。公式:$r_l = r_{l-1} + (k-1) \times \prod_{i=1}^{l-1} s_i$。
Q15:ResNet 的残差连接为什么能解决梯度消失?
传统层:$y = F(x)$,梯度 $\frac{\partial L}{\partial x} = \frac{\partial L}{\partial y} \cdot \frac{\partial F}{\partial x}$
残差层:$y = F(x) + x$,梯度 $\frac{\partial L}{\partial x} = \frac{\partial L}{\partial y} \cdot (\frac{\partial F}{\partial x} + 1)$
多了一个 $+1$ 的"梯度高速公路"。即使 $\frac{\partial F}{\partial x}$ 接近 0,梯度仍然可以通过 $+1$ 直接传回去。这就是为什么 ResNet 可以训练 152 层甚至更深的网络。没有残差连接,152 层的网络梯度方差会膨胀到无法训练——每层梯度连乘,要么指数衰减(消失)要么指数增长(爆炸)。
常见误区:以为残差连接是"跳过了一层"。实际上 $y = F(x) + x$ 仍然经过了 $F(x)$ 的计算,只是额外加了原始输入。模型可以学到 $F(x) \approx 0$(什么都不做),但更常见的是学到 $F(x)$ 是对 $x$ 的"微调"。
面试时怎么讲:“残差连接就是 $y = F(x) + x$。反向传播时梯度多了一条 ‘+1’ 的高速公路——即使 F 的梯度接近 0,梯度也能直接传回去。这就是 ResNet 能训练 152 层的原因。”
面试官可能追问:“Pre-LN 和 Post-LN 的区别?” → Pre-LN 在注意力/FFN 之前做 LayerNorm(训练更稳定,梯度更平滑),Post-LN 在之后做(原始 Transformer 的做法,需要 warmup)。现代模型(GPT-3、LLaMA)均采用 Pre-LN。
Q16:RNN 的梯度消失问题?LSTM 的门控机制如何缓解?
RNN 的梯度需要从 $h_T$ 一路传回 $h_1$,每一步都乘以 $W_h$。如果 $W_h$ 的特征值 < 1,梯度指数衰减;如果 > 1,梯度指数增长。
LSTM 的解决方案:引入细胞状态 $C_t$ 和三个门(遗忘门、输入门、输出门)。
关键:细胞状态的更新是加法而非乘法:$C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t$
加法的梯度是 1,不会衰减。这就是"梯度高速公路"——信息可以沿着细胞状态直接传递,不需要经过激活函数的连乘。
面试时怎么讲:“RNN 的梯度消失是因为每步都乘以 W_h。LSTM 用细胞状态 C_t 做加法更新——加法的梯度是 1,不会衰减。三个门控制信息的遗忘、输入、输出。这就是 LSTM 能处理长序列的原因。”
常见误区:以为 LSTM 完全解决了梯度消失。实际上遗忘门 $f_t < 1$ 时梯度仍会衰减,只是比 RNN 慢得多。超长序列(10000+ 步)LSTM 仍然会遇到长程依赖问题。
面试官可能追问:“LSTM 真的完全解决了梯度消失吗?” → 没有完全解决。遗忘门 $f_t < 1$ 时梯度仍会衰减,只是比 RNN 的连乘衰减慢得多。对于超长序列(10000+ 步),LSTM 仍然会遇到长程依赖问题——这就是为什么 Transformer 出现了。
Q17:GRU 和 LSTM 的区别?
| 特性 | LSTM | GRU |
|---|---|---|
| 门的数量 | 3 个(遗忘门、输入门、输出门) | 2 个(重置门、更新门) |
| 状态 | 隐藏状态$h_t$ + 细胞状态 $C_t$ | 只有隐藏状态$h_t$ |
| 参数量 | 更多 | 更少(约 LSTM 的 75%) |
| 效果 | 长序列更好 | 短序列相当,训练更快 |
选择建议:默认用 LSTM(效果更稳定),数据量大或需要快速实验时用 GRU。
实操建议:序列长度 < 100 且数据量少 → GRU(参数少,不容易过拟合);序列长度 > 100 或对精度要求高 → LSTM。现代大模型已经不用 RNN 了(用 Transformer),但理解 LSTM 对面试很重要。
面试官可能追问:“既然 Transformer 更好,为什么还要学 LSTM?” → ① LSTM 是理解序列建模演进的关键一环;② 某些实时场景(如流式语音识别)LSTM 仍有优势(Transformer 需要完整序列);③ 面试官想看你是否理解 RNN 的局限性。
Q18:BatchNorm 的原理和作用?为什么能加速训练?
对每个 mini-batch 的数据做标准化:
- 计算这个 batch 的均值 $\mu$ 和方差 $\sigma^2$
- 标准化:$\hat{x} = (x - \mu) / \sqrt{\sigma^2 + \varepsilon}$
- 缩放和平移:$y = \gamma \cdot \hat{x} + \beta$($\gamma$ 和 $\beta$ 是可学习的参数)
为什么有效:BatchNorm 的核心作用是平滑损失曲面,让梯度更加稳定,从而允许使用更大的学习率,加速收敛。
常见误区:以为 BatchNorm 随时都能用。实际上 BatchNorm 在 batch size 很小时(如 1-2)效果很差(统计量不准);在序列数据上不适合(每个 token 的统计量不同);与 Dropout 同时使用时可能产生冲突。
面试时怎么讲:“BatchNorm 对每个 mini-batch 做标准化,平滑损失曲面,允许用更大学习率。但有两个坑:batch 小时统计量不准;和 Dropout 同时用可能冲突。所以 Transformer 用 LayerNorm(不依赖 batch size)。”
面试官可能追问:“BatchNorm 在推理时怎么处理?” → 推理时不用当前 batch 的统计量,而是用训练时累积的 running mean 和 running variance(指数移动平均)。这就是为什么 model.eval() 很重要——它切换 BatchNorm 到推理模式。
Q19:Dropout 的原理?训练和推理时的区别?
训练时随机将 50% 的神经元输出置为 0。类比:期末考试随机缺席一半学生,迫使每个学生都必须自己学会知识。
推理时关闭 Dropout,但所有权重乘以 $(1-p)$ 来补偿训练时的缩放。
常见误区:以为 Dropout 和 BatchNorm 可以同时使用。实际上两者对数值分布的假设不同——BatchNorm 依赖 batch 统计量,Dropout 随机改变激活值,同时使用可能导致训练不稳定。现代 Transformer 通常只用 LayerNorm + Dropout(或不用 Dropout)。
面试时怎么讲:“Dropout 训练时随机把 50% 神经元置零,推理时关闭。作用是防止过拟合——迫使每个神经元独立学习。坑:和 BatchNorm 同时用会不稳定。”
面试官可能追问:“为什么推理时不用 Dropout?” → 推理需要确定性输出——同一个输入应该每次都得到同样的结果。Dropout 的随机性只在训练时有用(正则化),推理时必须关闭。
Q20:PyTorch 的自动求导(Autograd)是如何工作的?
- 前向传播时:PyTorch 记录每一步操作,构建"计算图"
- 调用
.backward()时:从输出节点开始,沿计算图反向传播 - 每个节点:通过链式法则计算梯度
- 结果:存储在每个叶子节点的
.grad属性中
PyTorch 使用"动态图"策略——每次前向传播时实时构建计算图,支持 Python 的 if/for 控制流,调试方便。
面试时怎么讲:“PyTorch 自动求导:前向传播时构建计算图(记录每一步操作),调用 backward() 时沿图反向计算梯度。关键特点:动态图——每次前向传播实时构建,支持 if/for,调试方便。TensorFlow 1.x 是静态图(先定义图再执行),调试困难。”
面试官可能追问:“PyTorch 和 TensorFlow 的核心区别?” → PyTorch 用动态图(define by run),调试方便,适合研究。TensorFlow 2.x 也支持动态图,但 1.x 是静态图(define then run),部署更方便。现在两者差距在缩小。
Q21:Adam 优化器的原理?和 SGD 的区别?
Adam = Momentum + RMSProp:
- Momentum(一阶矩):累积历史梯度的均值,减少震荡
- RMSProp(二阶矩):累积历史梯度的方差,自适应调整每个参数的学习率
对于梯度一直很大的参数,学习率自动变小;对于梯度一直很小的参数,学习率自动变大。
| 优化器 | 特点 | 适用场景 |
|---|---|---|
| SGD | 简单、泛化好 | CV 任务 |
| Adam | 收敛快、对学习率不敏感 | NLP/Transformer 首选 |
| AdamW | Adam + 解耦权重衰减 | Transformer 训练标准 |
实操建议:CV 任务通常用 SGD+动量,泛化性更好;NLP/大模型通常用 AdamW,收敛更稳定。
Q22:混合精度训练的原理?为什么能节省显存?
大部分计算用 float16(快、省显存),关键操作(损失计算、梯度累积)保留 float32(准)。
以 7B 模型为例:
| 精度 | 模型参数显存 | 总显存 |
|---|---|---|
| float32 | 28 GB | ~112 GB |
| 混合精度 | ~18 GB | ~88 GB |
节省约 30% 显存,训练速度提升 2-3 倍,精度与 float32 持平。
实操建议:如果你在训练大模型,几乎必须用混合精度(PyTorch 的 torch.cuda.amp)。显存省 30%,速度快 2 倍,精度几乎无损。唯一注意:loss scaling 要开(PyTorch 的 GradScaler 自动处理)。
常见误区:以为混合精度只是"把 float32 换成 float16"。实际上需要保留关键操作的 float32(损失计算、梯度累积),否则会数值溢出。还需要 loss scaling(放大损失值)防止小梯度下溢为 0。
面试官可能追问:“什么是 loss scaling?” → float16 的最小正值约 $6 \times 10^{-8}$,很小的梯度会下溢为 0。Loss scaling 先把损失值放大(如 ×1024),梯度也跟着放大,更新前再缩回来。
3. Transformer 架构(第 3 篇)
Q23:Self-Attention 的计算过程?Q、K、V 分别代表什么?
Q(Query):每个词的"需求"——我在找什么信息 K(Key):每个词的"标签"——我能提供什么 V(Value):每个词的"内容"——我的实际信息
计算过程:
- $Q = X \cdot W_Q$,$K = X \cdot W_K$,$V = X \cdot W_V$(三个不同的线性变换)
面试时怎么讲:“Self-Attention 让每个词都能看到所有其他词。Q 是’我在找什么’,K 是’我能提供什么’,V 是’我的内容’。Q 和 K 点积得到相关性分数,Softmax 归一化后加权求和 V。除以根号 d_k 防止 Softmax 饱和。”
面试官可能追问:“为什么 Q/K/V 要用不同的权重矩阵?” → 如果用同一个矩阵,Q=K=V,注意力分数会退化为自相关。用不同的矩阵让模型能学习"需求"和"提供"的不同表示——就像搜索引擎的查询词(Q)和文档标题(K)是不同的东西。
- $\text{scores} = Q \cdot K^T$(计算每对词之间的相关性)
- $\text{scaled\_scores} = \text{scores} / \sqrt{d_k}$(缩放,防止 softmax 梯度消失)
- $\text{weights} = \text{softmax}(\text{scaled\_scores})$(归一化为概率分布)
- $\text{output} = \text{weights} \cdot V$(加权求和)
每个词的输出都是所有词的 Value 的加权和,权重由词与词之间的相关性决定。
Q24:为什么要除以 $\sqrt{d_k}$?不除会怎样?
当 $d_k$ 很大时,$Q \cdot K^T$ 的值可能很大。大的输入值会导致 softmax 输出接近 one-hot(如 0.982),梯度接近 0,训练停滞。
除以 $\sqrt{d_k}$ 让方差回到 1,softmax 的梯度正常。
| 方案 | 输入值 | Softmax 输出 | 梯度状态 |
|---|---|---|---|
| 不缩放 | [26, 18, 30, 22] | [0.018, 0.000, 0.982, 0.000] | 梯度很小 |
| 缩放(÷8) | [3.25, 2.25, 3.75, 2.75] | [0.276, 0.102, 0.455, 0.167] | 梯度正常 |
为什么点积的方差是 $d_k$? 假设 Q 和 K 的每一维独立同分布,均值 0 方差 1。点积 $q \cdot k = \sum_{i=1}^{d_k} q_i k_i$,每一项 $q_i k_i$ 的方差是 1(独立随机变量乘积的方差 = 方差之积 = 1×1 = 1)。$d_k$ 个独立项求和,方差相加:$\text{Var}(q \cdot k) = d_k$。除以 $\sqrt{d_k}$ 后:$\text{Var}(q \cdot k / \sqrt{d_k}) = d_k / d_k = 1$。
常见误区:很多人以为除以 $\sqrt{d_k}$ 是为了"数值稳定性"(防止溢出)。实际上浮点数精度足够处理这些数值,真正的问题是 Softmax 的梯度——当输入值方差很大时,Softmax 会进入饱和区,梯度接近零,训练停滞。
面试时怎么讲:“Q 和 K 的每一维是均值 0 方差 1 的随机变量,点积是 $d_k$ 项求和,方差变成 $d_k$。当 $d_k=64$ 时,点积的典型值可能在 [-16, 16] 范围,Softmax 会输出接近 one-hot 的分布。除以 $\sqrt{d_k}$ 把方差压回 1,让 Softmax 输出更均匀,梯度正常。”
Q25:多头注意力的作用?为什么不用一个大的注意力头?
单头注意力只能学到一种"注意力模式"。多头注意力的每个头学习不同的"关系检测器":
- Head 1 可能学到指代关系(“it"指代"animal”)
- Head 2 可能学到修饰关系(“tired"修饰"animal”)
- Head 3 可能学到因果关系(“didn’t cross"和"tired"有因果)
就像 CNN 中多个卷积核分别检测竖线、横线、斜线一样。
常见误区:以为头数越多越好。实际上头数过多会导致每个头的 $d_k$ 太小($d_k = d_{\text{model}} / n_{\text{heads}}$),每个头的表达能力下降。BERT-base 用 12 头($d_k=64$),LLaMA-7B 用 32 头($d_k=128$)——头数和维度需要平衡。
面试时怎么讲:“单头注意力只能学到一种关注模式,比如语法关系。多头注意力让模型同时从多个角度理解——一个头关注语法,一个头关注语义,一个头关注指代。最后拼接起来,信息更丰富。就像 CNN 用多个卷积核检测不同边缘一样。”
Q26:位置编码的作用?为什么 Transformer 需要位置信息?
Self-Attention 是"位置无关"的——“狗咬人"和"人咬狗"在 Self-Attention 的计算中完全一样。但它们的意思完全不同。
位置编码额外告诉模型"每个词在哪个位置”,让模型能够区分词序。
常见误区:以为位置编码是"加到词向量上"的固定值。实际上正弦位置编码是固定的,但可学习的位置编码(如 BERT 用的)是训练出来的。RoPE 更特殊——它乘到 Q/K 上,不加到输入上。
面试官可能追问:“RoPE 和正弦位置编码的区别?” → 正弦编码加到输入上(绝对位置),RoPE 乘到 Q/K 上(相对位置)。RoPE 的关键优势:注意力分数只依赖相对位置 $(n-m)$,支持长度外推。LLaMA/Qwen/Mistral 都用 RoPE。
Q27:正弦位置编码的设计原理?为什么用 sin/cos?
$$ PE(pos, 2i) = \sin(pos / 10000^{2i/d}), \quad PE(pos, 2i+1) = \cos(pos / 10000^{2i/d}) $$三个巧妙原因:
- 每个位置有唯一的编码:sin/cos 的组合可以唯一标识每个位置
- 相对距离可用线性变换表示:$PE(pos+k)$ 可以用 $PE(pos)$ 的线性变换得到
- 可以外推到更长的序列:正弦函数是周期性的,可以计算任意位置
实操建议:如果你在训练新模型,用 RoPE 替代正弦编码(LLaMA/Qwen 都用它)。如果你在用 BERT/GPT-2,它已经是正弦编码了,不需要改。
面试时怎么讲:“正弦位置编码用 sin/cos 函数给每个位置一个唯一编码。三个巧妙之处:每个位置唯一、相对距离可以用线性变换表示、可以外推到更长序列。但现代模型已改用 RoPE(相对位置,效果更好)。”
面试官可能追问:“为什么底数选 10000?” → 这是一个经验选择。10000 的幂次可以产生从高频到低频的正弦波——低维度变化快(捕捉近距离关系),高维度变化慢(捕捉远距离关系)。
Q28:Encoder 和 Decoder 的区别?
| 特性 | Encoder | Decoder |
|---|---|---|
| 作用 | “理解”——读懂输入 | “写作”——生成输出 |
| 注意力 | Self-Attention(双向,所有位置互相看) | Masked Self-Attention(单向,只能看前面) + Cross-Attention |
| 输入 | 完整的输入序列 | 已生成的部分序列 + Encoder 的输出 |
| 代表模型 | BERT | GPT |
常见误区:以为 Encoder 和 Decoder 的区别只是"双向 vs 单向”。实际上 Decoder 还有 Cross-Attention(从 Encoder 获取信息)和 Masked Attention(遮盖未来位置)。这就是为什么 Decoder 适合生成——它能同时看输入和已生成的内容。
面试时怎么讲:“Encoder 双向理解(BERT),Decoder 单向生成(GPT)。Decoder 额外有 Masked Attention(遮盖未来)和 Cross-Attention(看 Encoder 输出)。现代趋势是 Decoder-only 统一一切。”
面试官可能追问:“有没有同时用 Encoder 和 Decoder 的模型?” → T5、BART 是 Encoder-Decoder 架构,适合翻译、摘要等"输入→输出"任务。现代趋势是 Decoder-only(GPT、LLaMA),因为它更简单且 scaling law 更好。
Q29:Masked Self-Attention 的作用?为什么要遮盖未来位置?
训练时我们知道完整的译文,但不能让模型"偷看"未来的词。如果不加 Mask,模型会直接抄答案,什么都学不到。
实现方式:将未来位置的注意力分数设为 $-\infty$,softmax 后变为 0。
常见误区:以为 Masked Attention 是"遮盖已生成的词"。实际上恰恰相反——遮盖的是"未来还没生成的词",让模型只能看前面已生成的内容。
面试官可能追问:“Mask 是在训练时还是推理时用?” → 训练时必须用(因为训练数据是完整的,不遮盖会偷看答案)。推理时不需要显式 Mask——因为生成是逐词的,每次输入只包含已生成的词,天然看不到未来。
Q30:Cross-Attention 是什么?Q、K、V 分别来自哪里?
- Q 来自 Decoder(“我在找什么信息?")
- K 和 V 来自 Encoder(“源语言提供了什么信息?")
这让 Decoder 在生成每个译文词时,都能"回头看"原文的相关部分——这就是"注意力对齐”。
面试官可能追问:“Cross-Attention 和 Self-Attention 的计算有什么区别?” → 计算方式完全一样(Q·K^T → Softmax → ·V),区别在于 Q 来自 Decoder,K/V 来自 Encoder。Self-Attention 的 Q/K/V 都来自同一个序列。
Q31:残差连接和 LayerNorm 的作用?
残差连接:$y = F(x) + x$,保留原始信息 + 新学到的信息。来自 ResNet 的智慧,让梯度可以"跳过"层。
LayerNorm:对同一样本的不同维度做归一化,稳定数值范围。用 LayerNorm 而非 BatchNorm 的原因:NLP 中每个句子长度不同,BatchNorm 的统计量不稳定。
常见误区:以为残差连接是"可选的优化”。实际上没有残差连接,深层 Transformer 根本训不动——梯度会指数衰减。残差连接是 Transformer 能堆叠到 96 层(GPT-3)的关键。
面试官可能追问:“LayerNorm 放在哪里?Pre-LN 还是 Post-LN?” → Pre-LN(注意力/FFN 之前)训练更稳定,GPT-3、LLaMA 都用。Post-LN(之后)是原始 Transformer 的做法,需要 warmup。
Q32:FFN(前馈网络)的作用?为什么升维 4 倍?
FFN 对每个位置独立做非线性变换:$\text{FFN}(x) = \text{ReLU}(x \cdot W_1) \cdot W_2$
升维 4 倍(512→2048)的原因:在高维空间中做非线性变换,可以画出更复杂的"分类边界",再投影回原维度。
Attention vs FFN 的分工:
- Attention:收集信息(“看看别人说了什么”)
- FFN:处理信息(“想想自己该怎么理解”)
常见误区:以为 FFN 只是"升维再降维"的线性变换。实际上中间有激活函数(ReLU 或 SwiGLU)——没有激活函数,两次线性变换可以合并为一次,升维就失去意义了。
面试时怎么讲:“FFN 对每个位置独立做非线性变换。先升维 4 倍,增加表达能力,再降回原维度。Attention 负责收集信息,FFN 负责处理信息——两者交替堆叠。”
Q33:LayerNorm 和 BatchNorm 的区别?为什么 Transformer 用 LayerNorm?
| 特性 | BatchNorm | LayerNorm |
|---|---|---|
| 归一化维度 | 跨 batch(同一特征在不同样本上归一化) | 跨特征(同一样本在不同维度上归一化) |
| 依赖 batch size | 是 | 否 |
| 适合变长序列 | 不适合 | 适合 |
Transformer 用 LayerNorm 的原因:NLP 中每个句子长度不同、每个 token 的含义不同,用 LayerNorm 更合适。所以 BatchNorm 在 batch 较小时统计量不稳定(均值和方差估计不准),而 LayerNorm 可以稳定地在任意 batch size 下工作(甚至 batch size=1 也能正常归一化)。
常见误区:以为 LayerNorm 和 BatchNorm 的区别只是"归一化的维度不同"。实际上核心区别是对 batch size 的依赖——BatchNorm 需要统计整个 batch 的均值和方差,batch 小时估计不准;LayerNorm 每个样本独立计算,与 batch size 无关。
*实操建议:CV 用 BatchNorm(batch size 大,图像数据分布稳定);NLP/序列任务用 LayerNorm(batch size 小,序列长度不一);视觉 Transformer(ViT)也用 LayerNorm。*这就是为什么 Transformer(batch size 通常较小)必须用 LayerNorm。
Q34:Transformer 的计算复杂度是多少?和 RNN 相比如何?
| 特性 | RNN | Transformer |
|---|---|---|
| 计算复杂度 | $O(n \cdot d^2)$ | $O(n^2 \cdot d)$ |
| 长距离依赖 | 困难(梯度消失) | 容易(直接连接) |
| 并行计算 | 不可(串行) | 可以(所有位置同时) |
| 训练速度 | 慢 | 快(10-100 倍) |
当 $n < d$ 时 Transformer 更快。大多数 NLP 任务中 $d=512$,$n$ 通常 < 512,所以 Transformer 更优。
常见误区:以为 Transformer 总是比 RNN 快。实际上当序列长度 $n$ 很大时(如 $n=100000$),$O(n^2)$ 的注意力计算会成为瓶颈——这就是为什么长序列需要 Flash Attention、稀疏注意力等优化技术。
实操建议:短序列(<512)→ Transformer 快且效果好;长序列(>4096)→ 需要 Flash Attention 或稀疏注意力;超长序列(>100K)→ 考虑 Mamba(线性注意力)或 Longformer。
面试官可能追问:“Flash Attention 是什么?” → Flash Attention 通过分块计算和避免存储完整的 $n \times n$ 注意力矩阵,把显存从 $O(n^2)$ 降到 $O(n)$,同时利用 GPU 的 SRAM 缓存加速计算。不是改变注意力的数学,而是改变计算的实现方式。
4. 预训练语言模型(第 4 篇)
Q35:BERT 和 GPT 的核心区别?分别适合什么任务?
| 特性 | BERT | GPT |
|---|---|---|
| 架构 | Transformer Encoder | Transformer Decoder |
| 方向 | 双向(同时看前后文) | 单向(只看前面的词) |
| 训练目标 | 遮盖词预测(MLM) | 预测下一个词(自回归) |
| 擅长任务 | 理解类(分类、NER、问答) | 生成类(文本生成、对话) |
BERT 像"阅读理解"——读完全文再回答。GPT 像"写作"——一个字一个字地写。
面试时怎么讲:“BERT 是双向 Encoder,适合理解任务(分类、NER)。GPT 是单向 Decoder,适合生成任务(对话、写作)。核心区别:BERT 能看到前后文,GPT 只能看前面。所以 BERT 理解更好,GPT 生成更好。”
实操建议:分类任务用 BERT 更方便;生成任务首选 GPT。微调成本 BERT 更低(参数量小)。
常见误区:以为 BERT 和 GPT 可以互换。实际上 BERT 不能做自回归生成(训练时每个位置都能看到全文),GPT 不能做双向理解(训练时只能看前面)。用 BERT 做生成或用 GPT 做分类都是"大材小用"或效果不好。
Q36:BERT 的 MLM(遮盖语言模型)预训练任务是怎么做的?
随机遮盖 15% 的词,让模型预测被遮盖的词。
15% 被选中词的处理策略(80/10/10 规则):
- 80% 替换为 [MASK]:让模型学习"根据上下文填空"
- 10% 替换为随机词:迫使模型不能只依赖 [MASK] 标记
- 10% 保持原词不变:让模型学习"判断每个词是否正确"
常见误区:以为 BERT 训练时总是看到 [MASK] 标记。实际上只有 80% 的被选中词用 [MASK],10% 用随机词,10% 保持原词——这让模型无法投机取巧,必须真正理解语言。
面试官可能追问:“为什么不用 100% [MASK]?” → 如果 100% 用 [MASK],模型会学到"只在看到 [MASK] 时才预测"的捷径。混合策略让模型对每个位置都需要理解上下文。
Q37:BERT 的 NSP(下一句预测)任务的作用?
给模型两个句子,判断它们是否是连续的。
- 正例:“他去超市买了牛奶。” + “然后回家做早餐。” → IsNext
- 负例:“他去超市买了牛奶。” + “今天天气很好。” → NotNext
让模型学到"句子之间的逻辑关系",对问答、推理等任务有帮助。
常见误区:以为 NSP 很重要。实际上 RoBERTa 论文证明 NSP 对性能提升不大,甚至可能有害。后来的模型(如 RoBERTa、LLaMA)都去掉了 NSP,只用 MLM。
面试官可能追问:“为什么 NSP 没用?” → NSP 太简单了——模型可能只学到"两个句子是否来自同一篇文档"的表面特征(如主题一致性),而不是真正的语言理解。
Q38:GPT 的自回归生成过程?每次生成一个 token 时在做什么?
- 输入已有的文本(如"I love")
- 模型输出下一个词的概率分布(如 “AI”=53.2%, “the”=9.7%)
- 采样(或取 argmax)选择一个词(如"AI")
- 将"AI"拼接到输入 → “I love AI”
- 重复步骤 2-4,直到生成结束标记
每次生成都要重新计算整个序列的注意力(新 token 需要看到前面所有 token),所以生成 100 个 token 需要 100 次前向传播。
常见误区:以为 GPT 生成时每次只看上一个词。实际上 GPT 用 Masked Self-Attention,每个新 token 可以看到前面所有 token(不只是上一个)。这就是为什么 GPT 能保持上下文连贯。
面试时怎么讲:“GPT 逐词生成:输入已有文本,模型输出下一个词的概率分布,采样选一个词,拼回去继续。训练时所有位置同时算 loss(并行),推理时必须逐词生成(串行)。”
面试官可能追问:“GPT 的训练和推理有什么区别?” → 训练时用 teacher forcing(所有位置同时计算 loss,并行);推理时必须逐词生成(串行)。这就是为什么训练比推理快得多——训练一次前向传播处理整个序列,推理生成 n 个词需要 n 次前向传播。
Q39:什么是预训练+微调范式?为什么有效?
预训练:在海量无标注文本上学习通用语言表示(语法、语义、世界知识)。
微调:在少量标注数据上适配特定任务。
面试时怎么讲:“预训练+微调就是’先学通用语言,再学特定任务’。预训练在海量文本上学语法、语义、世界知识;微调用少量标注数据适配具体任务。学习率要小(2e-5),避免灾难性遗忘。”
有效的三个原因:
- 预训练学到了通用语言表示——不管什么任务都需要理解语言
- 迁移学习——学过英语的人学法语更容易
- 小学习率避免灾难性遗忘——保留预训练知识,缓慢适应新任务
常见误区:以为预训练+微调总是最好的。实际上如果目标任务与预训练数据差异很大(如医学文本),微调效果可能不如从头训练。另外微调学习率过大(如 1e-3)会导致灾难性遗忘——预训练知识被覆盖,模型在新任务上表现反而更差。
实操建议:数据少+任务简单 → 提示词工程;数据少+任务复杂 → LoRA;数据多+任务复杂 → 全量微调。微调学习率:2e-5 到 5e-5,不要超过 1e-4。
面试官可能追问:“全量微调 vs LoRA vs 提示词工程,怎么选?” → 数据少+任务简单 → 提示词工程;数据少+任务复杂 → LoRA;数据多+任务复杂 → 全量微调。优先级:先试提示词工程 → 其次 LoRA → 最后全量微调。
Q40:什么是 Tokenizer?BPE 分词算法的原理?
Tokenizer 把人类的文字翻译成计算机的数字。
**BPE(Byte Pair Encoding)**的原理:
- 初始化:每个字符为一个 token
- 统计所有相邻字符对的出现频率
- 合并频率最高的对(如 e+s → es)
- 重复步骤 2-3,直到达到目标词表大小
优点:词表大小适中(3-5 万),能处理任何未登录词(总能拆成子词)。
面试时怎么讲:“BPE 分词:先把每个字符当 token,然后不断合并出现频率最高的字符对。比如 ’e’ 和 ’s’ 经常一起出现,就合并成 ’es’。重复直到词表够大。优点:词表适中,能处理任何未登录词。”
常见误区:以为 BPE 分词是"按词切分"。实际上 BPE 是按子词切分——“unhappiness” 可能被切成 “un”+“happi”+“ness”。这就是为什么 LLM 能处理任何未登录词——总能拆成已知的子词。
面试官可能追问:“不同模型的分词器可以互换吗?” → 不可以。每个模型用自己的词表训练 BPE,同一个词在不同模型中可能被切成不同的子词。用错分词器会导致乱码或性能下降。
Q41:HuggingFace 的 Pipeline 是什么?
Pipeline 是 HuggingFace 的一行代码推理接口,自动完成预处理、模型加载、后处理:
from transformers import pipeline
classifier = pipeline('sentiment-analysis')
result = classifier("I love this movie!")
# [{'label': 'POSITIVE', 'score': 0.9998}]
支持的任务包括:情感分析、文本生成、问答、NER、零样本分类等。
面试官可能追问:“Pipeline 和直接加载模型有什么区别?” → Pipeline 自动处理了分词、后处理、设备分配等细节,一行代码就能用。直接加载模型需要手动处理这些,但更灵活。生产环境通常用直接加载,快速原型用 Pipeline。
Q42:什么是 Embedding?为什么文本需要转换为向量?
Embedding 把文本转换为固定长度的数字向量。语义相似的文本 → 向量接近(余弦相似度接近 1)。
原因:计算机只能处理数字。把现实世界的东西(图片、文字、声音)转换为向量,就是"表示学习"的核心任务。
常见误区:以为同一个词在所有上下文中的 Embedding 都一样。实际上 Word2Vec/GloVe 确实是静态的(同一个词一个向量),但 BERT/GPT 的 Embedding 是上下文相关的——“bank"在"river bank"和"bank account"中的向量不同。
面试官可能追问:“Embedding 的维度怎么选?” → 常见:128(小模型)、256(中等)、768(BERT-base)、1024(BERT-large)、1536(OpenAI text-embedding-3-small)。维度越大表达能力越强,但计算和存储成本也越高。
Q43:BERT 的 [CLS] token 有什么用?
[CLS] 放在句子开头,用于分类任务的输出。BERT 的最后一层在 [CLS] 位置的输出向量被当作整个句子的"摘要表示”,接一个线性层就能做分类。
常见误区:以为 [CLS] 的输出天然就是句子的"最佳表示"。实际上 [CLS] 只是通过 Self-Attention 聚合了所有位置的信息——它的质量取决于预训练任务。BERT 的 MLM 任务让每个 token 都学会理解上下文,[CLS] 自然也学到了。
面试官可能追问:“为什么不用所有 token 的平均值做句子表示?” → 可以,而且在某些任务上效果更好(如 Sentence-BERT)。[CLS] 的优势是它在预训练时就被"训练"为句子级别的表示,但平均池化(mean pooling)在语义相似度任务上通常更稳定。
Q44:三种 Transformer 架构(Encoder-only、Decoder-only、Encoder-Decoder)的区别和代表模型?
| 架构 | 代表模型 | 注意力方式 | 擅长任务 |
|---|---|---|---|
| Encoder-only | BERT, RoBERTa | 双向(全连接) | 理解、分类、NER |
| Decoder-only | GPT, LLaMA | 单向(因果 Mask) | 生成、对话 |
| Encoder-Decoder | T5, BART | 编码双向 + 解码单向 | 翻译、摘要 |
实操建议:理解类任务(分类、NER、问答)→ Encoder-only(BERT);生成类任务(对话、写作)→ Decoder-only(GPT/LLaMA);输入→输出任务(翻译、摘要)→ Encoder-Decoder(T5)。现代趋势是 Decoder-only 统一一切。
面试时怎么讲:“三种架构:Encoder-only(BERT,双向,擅长理解)、Decoder-only(GPT,单向,擅长生成)、Encoder-Decoder(T5,擅长翻译摘要)。现代趋势是 Decoder-only 统一一切——因为架构更简单,scaling law 更好。”
实操建议:理解类任务(分类、NER、问答)→ Encoder-only(BERT);生成类任务(对话、写作)→ Decoder-only(GPT/LLaMA);输入→输出任务(翻译、摘要)→ Encoder-Decoder(T5)。现代趋势是 Decoder-only 统一一切。
面试官可能追问:“为什么现代大模型都是 Decoder-only?” → ① 架构更简单(只有 Masked Self-Attention + FFN);② Scaling law 更好(同样的参数量,Decoder-only 效果更好);③ 统一接口(理解和生成都用同一个模型)。
5. LLaMA 架构(第 5 篇)
Q45:LLaMA 相比原始 Transformer 有哪些改进?
| 改进 | 替代了什么 | 解决的问题 | 效果 |
|---|---|---|---|
| RMSNorm | LayerNorm | 归一化计算量大 | 计算减少 ~15% |
| RoPE | 正弦位置编码 | 绝对位置,外推差 | 支持相对位置,长序列友好 |
| SwiGLU | ReLU FFN | 表达能力有限 | 基准测试提升 |
| KV Cache | 无缓存 | 重复计算 K/V | 推理加速 seq_len 倍 |
| GQA | MHA/MQA | KV Cache 显存大 | 显存减少 ~4 倍 |
常见误区:以为 LLaMA 的 5 大改进是"全新的发明"。实际上 RMSNorm(2019)、RoPE(2021)、SwiGLU(2020)、KV Cache(2019)、GQA(2023)都是独立提出的改进。LLaMA 的贡献是把这些改进组合在一起,证明了"小模型+更多数据+更好架构"比"大模型+少数据"更有效。
面试官可能追问:“LLaMA 和 GPT 的核心区别?” → 架构类似(都是 Decoder-only),但 LLaMA 用了 RMSNorm+RoPE+SwiGLU+GQA,GPT-3 用的是 LayerNorm+正弦编码+ReLU+MHA。LLaMA 是开源的,GPT 是闭源的。
Q46:RMSNorm 和 LayerNorm 的区别?为什么 RMSNorm 更快?
| LayerNorm(4 步) | RMSNorm(3 步) |
|---|---|
| 1. 计算均值 | 1. 计算均方根 |
| 2. 计算方差 | 2. 归一化 |
| 3. 归一化 | 3. 缩放 |
| 4. 缩放 + 偏置 | — |
RMSNorm 去掉了"减均值"和"偏置"。实验发现效果差别很小,但计算量减少约 15%。
面试时怎么讲:“RMSNorm 比 LayerNorm 少一步减均值,只做归一化+缩放。实验发现效果几乎一样,但计算省 15%。LLaMA、Qwen 都用 RMSNorm。”
实操建议:如果你在训练自己的模型,用 RMSNorm 替代 LayerNorm 可以省 15% 计算且效果不变。如果你在用别人的模型(如 LLaMA),不需要改——它已经是 RMSNorm 了。
面试官可能追问:“RMSNorm 在什么情况下不如 LayerNorm?” → 当输入分布严重偏移时(如训练初期或数据分布变化大),LayerNorm 的"减均值"操作可以更好地稳定数值。但实践中这种场景很少见。
Q47:RoPE 旋转位置编码的原理?和传统位置编码的区别?
RoPE 把词向量的每两个维度看作一个二维平面上的点,位置 $m$ 的词向量旋转 $m \times \theta$ 角度。
关键性质:注意力分数只依赖于相对位置 $(n-m)$,而不是绝对位置。
| 特性 | 正弦位置编码 | RoPE |
|---|---|---|
| 编码方式 | 加到输入上 | 乘到 Q/K 上 |
| 位置类型 | 绝对位置 | 相对位置 |
| 外推能力 | 有限 | 较好 |
实操建议:如果你在训练新模型,用 RoPE(LLaMA/Qwen/Mistral 都用它)。如果你在用别人的模型,不需要改——它已经是 RoPE 了。RoPE 的外推能力可以通过 NTK-aware scaling 进一步增强。
Q48:SwiGLU 激活函数的特点?和 ReLU 的区别?
SwiGLU = Swish + GLU(门控线性单元):
$$ \text{FFN}(x) = (\text{Swish}(x \cdot W_1) \odot x \cdot W_3) \cdot W_2 $$$W_3$ 产生的值像一个"阀门",控制 $W_1$ 的信息通过多少。不像 ReLU 的"硬开关",SwiGLU 是"可调节的阀门"。
实操建议:SwiGLU 已成为现代大模型的标配(LLaMA、Qwen、Mistral 都用它)。如果你在训练新模型,用 SwiGLU 替代 ReLU FFN 可以提升效果,代价是参数量略增(3 个权重矩阵 vs 2 个)。
Q49:KV Cache 的作用?为什么能加速推理?显存开销怎么算?
自回归生成时,每个新 token 都需要计算所有位置的 K 和 V。KV Cache 把之前算过的 K 和 V 缓存起来,下次直接复用。
效果:每个新 token 只需要 1 次前向传播(而不是 seq_len 次),推理速度提升 seq_len 倍。
显存公式:$2 \times \text{层数} \times \text{头数} \times d_k \times \text{序列长度} \times \text{精度字节数}$
LLaMA-7B 单条序列约 1GB,LLaMA-70B(GQA 8 KV 头)约 1.3GB。
常见误区:以为 KV Cache 只加速"注意力计算"($Q \cdot K^T$)。实际上 KV Cache 省掉的是重复的 K/V 线性投影($X \cdot W_K$ 和 $X \cdot W_V$),注意力本身的 $Q \cdot K^T$ 计算仍然需要遍历所有缓存位置。另一个误区:以为 KV Cache 的显存开销可以忽略——当序列长度很长(如 128K)或 batch size 很大时,KV Cache 会成为显存瓶颈,这就是 GQA 和 MQA 的动机。
面试时怎么讲:“自回归生成每个新 token 时,需要计算所有位置的 K 和 V。KV Cache 把之前算过的缓存起来,下次直接复用——省掉了重复的线性投影。代价是显存:LLaMA-7B 单条约 1GB,长序列时会成为瓶颈。”
Q50:GQA(分组查询注意力)和 MHA、MQA 的区别?
| 方案 | Q 头数 / K 头数 / V 头数 | 特点 |
|---|---|---|
| MHA | 32 / 32 / 32 | 质量最好,KV Cache 最大 |
| MQA | 32 / 1 / 1 | KV Cache 最小,质量下降明显 |
| GQA | 32 / 8 / 8 | 每 4 个 Q 头共享一组 KV,质量接近 MHA,速度接近 MQA |
GQA 让 KV Cache 减小约 4 倍(7B:32 Q 头 / 8 KV 组)至 8 倍(70B:64 Q 头 / 8 KV 组),同时模型质量几乎不变。
面试时怎么讲:“MHA 每个 Q 头有独立的 KV,质量最好但 Cache 最大。MQA 所有 Q 共享一个 KV,Cache 最小但质量差。GQA 折中——每 4 个 Q 共享一组 KV,质量接近 MHA,速度接近 MQA。”
实操建议:部署大模型时,如果显存紧张,优先检查是否可以用 GQA。LLaMA-2 和 LLaMA-3 已经默认用 GQA,不需要额外配置。
面试官可能追问:“MHA → MQA → GQA 的演进逻辑是什么?” → MHA 质量最好但 KV Cache 太大 → MQA 极端压缩(所有 Q 共享 1 个 KV)但质量下降 → GQA 折中(每 4 个 Q 共享 1 组 KV),质量接近 MHA,速度接近 MQA。
Q51:Temperature、Top-K、Top-P 采样策略的区别?
Temperature:控制输出的"随机性"。T 越小分布越尖锐(确定),T 越大分布越平坦(随机)。
Top-K:只从概率最高的 K 个词中采样。K=1 等价于贪心搜索。
Top-P(Nucleus Sampling):按概率从高到低排序,累加直到概率之和超过 P。动态调整候选集大小。
| 场景 | Temperature | Top-P |
|---|---|---|
| 代码生成 | 0.0 | 1.0 |
| 一般对话 | 0.7 | 0.9 |
| 创意写作 | 1.0 | 0.95 |
实操建议:代码生成用 Temperature=0(确定性输出,保证正确性);一般对话用 0.7+0.9(平衡);创意写作用 1.0+0.95(多样性)。不要同时设 Temperature 很低和 Top-P 很低——会退化为贪心搜索。
面试官可能追问:“Top-K 和 Top-P 哪个更好?” → Top-P 更好——它根据概率分布动态调整候选集大小。Top-K 的问题是 K 固定,简单问题和复杂问题用同一个 K。实际中通常用 Top-P=0.9 或 0.95。
Q52-54:为什么 LLaMA 用 RMSNorm/RoPE/SwiGLU?
这三个问题的答案都是"问题→方案→代价"分析:
RMSNorm:LayerNorm 计算量大(需要减均值)→ RMSNorm 去掉减均值 → 计算减少 15%,效果几乎不变
RoPE:正弦位置编码只编码绝对位置、外推差 → RoPE 编码相对位置 → 支持长序列,但计算稍复杂
SwiGLU:ReLU 表达能力有限(硬开关)→ SwiGLU 用门控机制 → 基准测试提升,但参数量增加约 50%(用 8/3d 隐藏维度补偿)
面试官可能追问:“为什么不直接用 ReLU?” → ReLU 的"硬开关"(负值全清零)会丢失信息。SwiGLU 的门控是"可调节的阀门",对每个维度独立控制通过量。实验发现 SwiGLU 在所有基准测试上都优于 ReLU。
6. LLM 应用开发(第 6 篇)
Q55:什么是 RAG(检索增强生成)?为什么需要它?
大模型有三大硬伤:知识截止日期、幻觉、无法访问私有数据。
RAG 的解决方案:先帮大模型"查资料",再让它"基于资料回答"。知识可以实时更新,减少幻觉,可以访问私有数据。
面试时怎么讲:“大模型有三大硬伤:知识截止、幻觉、不能访问私有数据。RAG 的方案:先检索相关文档,再让模型基于文档回答。就像开卷考试——不让模型’凭记忆’,而是’查资料’后回答。”
常见误区:以为 RAG 可以完全消除幻觉。实际上如果检索到的文档不相关或有错误,模型仍然会生成错误答案。RAG 的效果高度依赖检索质量——“garbage in, garbage out”。
面试官可能追问:“RAG 的最大挑战是什么?” → ① 检索质量(不相关的文档会误导模型);② chunk_size 选择(太大不精确,太小丢失上下文);③ 多跳推理(需要综合多个文档才能回答的问题)。
实操建议:如果你的知识库更新频繁(如产品文档)→ RAG;如果需要深度适配专业领域(如医学术语)→ 微调;如果只是简单的格式或风格调整 → 提示词工程。优先级:提示词工程 → RAG → 微调。
面试官可能追问:“RAG 和微调哪个更好?” → 没有绝对的好坏。RAG 适合知识频繁更新、需要引用来源的场景;微调适合需要深度适配的场景。实际中常常两者结合:微调让模型更好地理解检索到的内容,RAG 提供最新的知识。
Q56:提示词工程的核心技巧?结构化提示词的四要素?
四要素:
- 角色:告诉模型"你是谁"(如"你是一位资深 Python 工程师")
- 任务:告诉模型"做什么"(如"写一个 FastAPI 接口")
- 格式:告诉模型"怎么输出"(如"输出完整的 Python 代码")
- 约束:告诉模型"边界在哪"(如"使用异步函数,返回 JSON 格式")
面试官可能追问:“提示词越长效果越好吗?” → 不是。提示词太长会稀释关键信息(“Lost in the Middle"现象),且增加 token 费用。最佳实践:精炼、结构化、只包含必要信息。
Q57:什么是 Chain of Thought(思维链)?为什么能提升推理能力?
在提示词中加一句"让我们一步一步思考”,模型会展示中间推理步骤。
原因:激活了模型的"慢思考"模式,被迫展示中间步骤,减少了"跳步"导致的错误。类似于人类"打草稿"比"心算"更准确。
常见误区:以为 CoT 对所有任务都有用。实际上 CoT 主要对需要推理的任务(数学、逻辑、多步决策)有效。对简单的事实检索(如"法国的首都是什么?")反而会降低效率——不需要推理,直接回答就好。
面试官可能追问:“CoT 和 Few-shot 可以同时用吗?” → 可以,而且效果通常更好。在 Few-shot 的示例中展示推理过程(如"第 1 步…第 2 步…所以答案是…"),模型会学到"先推理再回答"的模式。
Q58:Few-shot 和 Zero-shot 的区别?
- Zero-shot:直接让模型做任务,不给示例
- Few-shot:给几个示例,让模型学会模式
Few-shot 的关键:示例的质量和多样性很重要,至少 2-3 个正例和 2-3 个反例。
实操建议:大多数任务先试 Zero-shot,效果不好再加 Few-shot。Few-shot 的示例要覆盖边界情况(如正例+反例+模糊案例)。如果 Few-shot 也不够,考虑微调。
面试官可能追问:“Few-shot 的示例顺序会影响结果吗?” → 会。研究表明示例的顺序、数量、质量都会影响输出。最佳实践:最后一个示例与当前输入最相似(近因效应)。
Q59:LangChain 的核心组件有哪些?
- LLM 调用:统一接口(支持 OpenAI、本地模型、各种 API)
- 提示模板:结构化、可复用的提示词
- 链(Chain):LCEL 管道语法,组合多个组件
- 文档加载与向量存储:PDF/Markdown 解析 + 向量搜索
- RAG 链:检索增强生成的标准实现
- Agent:让模型自主决策
常见误区:以为 LangChain 是必须的。实际上如果你只需要简单的 LLM 调用,直接用 OpenAI SDK 就够了。LangChain 的价值在于复杂的链式调用和 RAG 管道——简单场景用它反而增加复杂度。
面试官可能追问:“LangChain 的最大问题是什么?” → ① 抽象层太多(调试困难);② 版本更新太快(API 经常变);③ 性能开销(中间层增加了延迟)。简单场景建议直接用 SDK。*
Q60:LCEL 管道语法是什么?
LangChain Expression Language,用 | 把组件串联起来:
chain = template | llm | StrOutputParser()
类比 Unix 管道:cat file | grep "error" | sort
常见误区:以为 LCEL 只是语法糖。实际上 LCEL 自动处理了异步、批处理、流式输出、错误重试等复杂逻辑——手动实现这些需要大量代码。
面试官可能追问:“LCEL 和普通函数调用有什么区别?” → LCEL 的
|运算符会自动组合组件的输入/输出类型,支持异步(ainvoke)、批处理(batch)、流式(astream),且可以可视化调试(chain.get_graph())。
Q61:Embedding 的作用?如何计算文本相似度?
Embedding 把文本转换为固定长度的数字向量。语义相似的文本向量接近。
余弦相似度:$\cos(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a} \cdot \mathbf{b}}{|\mathbf{a}| \cdot |\mathbf{b}|}$
值域 [-1, 1],越接近 1 越相似。
面试官可能追问:“余弦相似度和欧氏距离有什么区别?” → 余弦相似度只看方向(夹角),不看大小;欧氏距离同时看方向和大小。文本相似度通常用余弦相似度(因为文本向量的长度不重要,方向才重要)。
Q62:什么是 Function Calling?大模型如何使用外部工具?
Function Calling 让大模型能够"使用工具"。工作流程:
- 用户提问 → 大模型分析,判断需要调用哪个工具
- 大模型生成工具调用指令(函数名 + 参数)→ 外部系统执行
- 工具返回结果 → 大模型整合结果生成回答
关键理解:大模型不直接执行工具,它只是"决策者"。
面试时怎么讲:“Function Calling 三步:① 定义工具(告诉模型有哪些函数可用);② 模型决策(分析问题,输出函数名+参数);③ 外部执行(你自己的代码执行函数,结果返回模型)。模型不执行工具,只决策。”
面试官可能追问:“Function Calling 和 MCP 的区别?” → Function Calling 是各家的"方言"(OpenAI、Anthropic 格式不同),MCP 是统一的"普通话"。MCP 有三大能力:Tools(工具)、Resources(资源)、Prompts(提示模板)。实际中 MCP 正在逐步替代各家的 Function Calling。
Q63:ChatGLM 和 Qwen3 的特点?
ChatGLM:智谱 AI 开发,中文能力强,支持 Function Calling,128K 上下文。
Qwen3:阿里云开发,多尺寸可选(0.6B-72B),深度思考模式(类似 o1),混合推理(简单问题快速模式,复杂问题深度思考)。
实操建议:中文场景优先试 Qwen3(中文能力强,开源);英文场景用 LLaMA/Mistral;需要 Function Calling 用 ChatGLM 或 Qwen3。选模型时先看任务需求,再看参数量。
面试官可能追问:“开源模型和闭源模型怎么选?” → 数据敏感 → 开源模型(本地部署);追求效果 → 闭源模型(GPT-4、Claude);预算有限 → 开源小模型 + LoRA 微调。
Q64:流式输出(Streaming)的原理和优势?
普通输出:等模型生成全部内容后一次性返回 → 用户等待时间长。
流式输出:模型每生成一个 token 就立即返回 → 用户看到文字逐字出现。
底层通过 SSE(Server-Sent Events)或 chunked transfer encoding 实现。
常见误区:以为流式输出会加速生成。实际上流式输出不改变模型的生成速度——总时间是一样的。它只是改善了用户体验(首字延迟降低,用户不用等全部生成完)。
面试官可能追问:“流式输出对后端有什么影响?” → ① 连接保持时间更长(需要 WebSocket 或 SSE);② 错误处理更复杂(生成到一半出错怎么办);③ 无法预知总长度(无法设置 Content-Length)。
7. RAG 检索增强生成(第 7 篇)
Q65:RAG 的完整流程?离线索引和在线查询分别做什么?
离线索引(一次性):文档 → 文本切分 → Embedding → 存入向量数据库
在线查询(每次):用户问题 → 问题 Embedding → 向量数据库中搜索最相似的文档块 → 组装提示词 → 发送给 LLM → 生成回答
面试时怎么讲:“RAG 分离线和在线。离线:文档切块→转成向量→存入向量数据库。在线:用户问题转向量→在数据库中找最相似的文档块→拼成提示词→让 LLM 基于文档回答。”
面试官可能追问:“chunk_size 怎么选?” → 太大(如 2000 字)→ 检索不精确,包含太多无关信息;太小(如 100 字)→ 语义不完整,丢失上下文。经验:500-1000 字,重叠 10-20%。不同文档类型需要不同策略(代码 vs 文档 vs 表格)。
Q66:文档切分策略有哪些?固定长度、递归、语义切分的区别?
| 策略 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 固定长度 | 每 500 字符切一刀 | 简单 | 可能在句子中间切断 |
| 递归 | 按段落→句子→词的优先级切 | 尽量在自然边界处切分 | 块大小不均匀 |
| 语义 | 根据语义相似度自动找切分点 | 每个块语义完整 | 计算量较大 |
实操建议:大多数场景用递归切分(LangChain 的 RecursiveCharacterTextSplitter)就够了。chunk_size=500-1000,overlap=10-20%。如果文档结构复杂(如代码、表格),用语义切分。
常见误区:以为 chunk_size 越小越好。实际上太小(如 100 字)会导致语义不完整,检索到的片段缺乏上下文。太大(如 2000 字)会导致检索不精确,包含太多无关信息。经验:500-1000 字是最佳起点。
Q67:向量数据库的原理?和传统数据库的区别?
传统数据库:精确匹配(WHERE title = '深度学习')
向量数据库:语义相似度搜索(“找到和’深度学习’含义最接近的书”)
核心是 ANN(近似最近邻)算法,用"聪明的策略"加速搜索,牺牲少量精度换取大量速度。
实操建议:小数据(<100 万向量)→ FAISS(内存,快);中等数据 → Chroma/Qdrant(磁盘持久化);大数据+生产环境 → Milvus/Weaviate(分布式)。
面试官可能追问:“向量数据库和传统数据库可以同时用吗?” → 可以,而且应该。向量数据库做语义搜索(“含义相近”),传统数据库做精确过滤(“作者=张三”)。混合检索(语义+关键词)效果最好。
Q68:HNSW 算法的原理?为什么比暴力搜索快?
HNSW(分层可导航小世界图)= 多层索引。
- 最顶层:只有"超级节点",快速定位大致区域
- 中间层:缩小范围
- 最底层:所有节点,精确定位
搜索时从顶层开始,逐层向下。复杂度 $O(\log n)$,比暴力搜索 $O(n \times d)$ 快几个数量级。精度 95-99%。
面试官可能追问:“HNSW 的 M 参数是什么?” → M 是每个节点的最大邻居数。M 越大,图越密集,搜索精度越高但构建越慢、显存越大。经验:M=16 是常用起点。
Q69:混合检索(语义 + 关键词)的优势?
纯语义检索:可能检索到语义相似但关键词不匹配的文档。
纯关键词检索:可能漏掉语义相关但用词不同的文档。
混合检索取长补短:70% 语义 + 30% 关键词,同时考虑"意思相近"和"关键词匹配"。
实操建议:大多数 RAG 场景用混合检索效果最好。LangChain 的 EnsembleRetriever 可以轻松实现。权重从 70% 语义 + 30% 关键词开始调。
面试官可能追问:“BM25 和向量检索的区别?” → BM25 是关键词匹配(精确但不理解语义),向量检索是语义匹配(理解含义但可能漏掉精确关键词)。两者互补。
Q70:多查询检索(Multi-Query)的原理?
一个问题自动生成多个变体表述:
- 原始问题:“什么是 RAG?”
- 变体 1:“解释检索增强生成技术”
- 变体 2:“RAG 的定义和原理”
合并所有查询的检索结果,召回率大幅提升。
面试官可能追问:“Multi-Query 的代价是什么?” → 每次查询需要多次 LLM 调用(生成变体)+ 多次检索,延迟和成本都增加。实际中通常生成 3-5 个变体就够了。
Q71:Corrective RAG 和 Adaptive RAG 的区别?
Corrective RAG:检索后评估文档相关性,不相关就用网络搜索补充,回答后还要评估质量。
Adaptive RAG:先判断问题类型(简单事实/复杂知识/推理),再选择最合适的处理方式(直接回答/检索回答/思维链推理)。
实操建议:大多数场景用标准 RAG 就够了。如果检索质量不稳定 → Corrective RAG(加相关性评估);如果问题类型多样 → Adaptive RAG(动态选择策略)。两者都增加了系统复杂度和延迟。
Q72:GraphRAG 和传统 RAG 的区别?知识图谱的作用?
传统 RAG:把文档切成片段,用向量搜索找最相关的片段。片段之间没有"关系"。
GraphRAG:从文档中提取实体和关系,构建知识图谱,社区检测,为每个社区生成摘要。能回答需要"综合多个信息源"的复杂问题。
面试官可能追问:“GraphRAG 的最大挑战是什么?” → ① 实体提取的准确性(LLM 可能提取错误的实体/关系);② 知识图谱的构建成本(需要大量 LLM 调用);③ 图谱更新(文档变化时需要重新构建)。
Q73:如何评估 RAG 效果?Faithfulness、Relevance、Correctness 分别衡量什么?
| 维度 | 指标 | 衡量什么 |
|---|---|---|
| 检索质量 | Recall@k, Precision@k | 检索到的文档是否包含正确答案 |
| 生成质量 | Faithfulness(忠实度) | 回答是否基于检索到的文档(没有编造) |
| 生成质量 | Relevance(相关性) | 回答是否和问题相关 |
| 生成质量 | Correctness(正确性) | 回答是否正确 |
| 端到端 | Answer Correctness | 最终回答是否正确 |
面试官可能追问:“Faithfulness 和 Correctness 有什么区别?” → Faithfulness 是"回答是否基于检索到的文档"(没有编造),Correctness 是"回答是否正确"。可能 Faithfulness 高但 Correctness 低(文档本身有错),也可能反过来(模型编造了正确答案但没引用来源)。
Q74:RAG vs 微调 vs 提示词工程,分别适合什么场景?
| 方法 | 开发成本 | 知识更新 | 适用场景 |
|---|---|---|---|
| 提示词工程 | 最低 | 不支持 | 简单任务、快速原型 |
| RAG | 中等 | 实时更新 | 知识问答、文档查询 |
| 微调 | 最高 | 需重新训练 | 专业领域、格式要求 |
推荐优先级:先试提示词工程 → 其次 RAG → 最后微调。
面试时怎么讲:“三种方法各有适用场景。提示词工程成本最低,适合快速验证。RAG 适合知识频繁更新的场景(如产品文档)。微调适合深度适配专业领域(如医学术语)。实际中常常组合使用。”
面试官可能追问:“可以同时用 RAG 和微调吗?” → 可以,而且效果通常更好。微调让模型更好地理解检索到的内容(如医学术语),RAG 提供最新的知识。实际中常见组合:先用领域数据微调基础模型,再用 RAG 增强知识覆盖。
8. Agent 开发与生产部署(第 8 篇)
Q75:LoRA 的原理?为什么低秩假设成立?参数量怎么算?
LoRA 的核心洞察:微调时权重的变化量 $\Delta W$ 是低秩的。可以用两个小矩阵近似:$\Delta W \approx A \times B$。
$A$:$(d, r)$,$B$:$(r, d)$,$r$ 通常为 8 或 16。
参数量示例($d=768, r=8$):$A$ 有 6144 个参数,$B$ 有 6144 个参数,总共 12288 个。原始权重有 589824 个参数,减少了 98%。
低秩假设成立的原因:预训练模型已经学到了通用知识,微调只是学"新的任务特定知识",信息量远小于原始知识。
面试时怎么讲:“LoRA 的核心洞察:微调时权重变化量是低秩的。用两个小矩阵 A×B 近似变化量,只训练 A 和 B(参数减少 98%)。推理时合并回原始权重,无额外开销。”
常见误区:以为 LoRA 的效果总是接近全量微调。实际上在需要深度适配的任务(如代码生成、多语言翻译)上,LoRA 的效果可能比全量微调低 1-3%。另外 LoRA 只修改注意力层的权重,对 FFN 层的影响有限。
面试官可能追问:“LoRA 的 r 怎么选?” → 简单任务(情感分类)→ r=8;复杂任务(代码生成)→ r=32-64。r 越大效果越好但参数越多。经验:从 r=8 开始,效果不好再增大。
实操建议:数据量少 → LoRA;数据量充足 → 全量微调。任务简单(如情感分类)→ LoRA;任务复杂(如代码生成)→ 全量微调。
Q76:QLoRA 的原理?为什么能在消费级 GPU 上微调 7B 模型?
QLoRA = 4-bit 量化 + LoRA:
面试时怎么讲:“QLoRA = 先用 4-bit 量化压缩模型(14GB→3.5GB),再加 LoRA 适配器微调。总显存约 6GB,一张 RTX 3060 就够。核心创新:NF4 量化格式(根据正态分布设计的 4-bit 格式)+ 双重量化(量化参数也量化)。”
- 用 4-bit 量化加载大模型(14GB → 3.5GB)
- 在量化模型上添加 LoRA 适配器(只占 0.03GB)
- 只训练 LoRA 参数
总显存约 6GB,一张 RTX 3060 就够了。
Q77:8-bit 和 4-bit 量化的区别?NF4 为什么比 FP4 好?
| 方案 | 模型大小(7B) | 精度损失 |
|---|---|---|
| float16 | 14 GB | 极小 |
| 8-bit | 7 GB | < 1% |
| 4-bit NF4 | 3.5 GB | ~1-2% |
NF4(Normal Float 4)比 FP4 好的原因:大模型的权重分布近似正态分布。NF4 的量化区间根据正态分布的 CDF 划分,数据密集处区间密、数据稀疏处区间疏,量化误差最小化。
实操建议:部署大模型时,优先用 4-bit NF4 量化(显存省 75%,精度损失 <2%)。如果显存极其紧张,用 NF4+双重量化。如果精度要求高,用 8-bit 量化。
面试官可能追问:“量化会影响推理速度吗?” → 4-bit 量化不仅省显存,还能加速推理(因为内存带宽是瓶颈,数据量小了读取更快)。但反量化(4-bit→float16)有少量开销。总体推理速度提升 1.5-2 倍。
实操建议:部署大模型时,优先用 4-bit NF4 量化(显存省 75%,精度损失 <2%)。如果显存极其紧张,用 NF4+双重量化。如果精度要求高,用 8-bit 量化。
Q78:什么是 Agent?和 Chain 的区别?
| 特性 | Chain | Agent |
|---|---|---|
| 流程 | 固定(A→B→C) | 动态决策 |
| 类比 | 工厂流水线 | 真人客服 |
| 适合任务 | 流程明确的任务 | 需要判断和选择的任务 |
面试时怎么讲:“Chain 是固定流程(A→B→C),Agent 是动态决策——根据情况选工具。类比:Chain 是工厂流水线,Agent 是真人客服。Agent 更灵活但更难调试,需要安全机制防止无限循环。”
实操建议:如果任务流程可以画成流程图(如"查数据库→生成报告→发邮件")→ Chain;如果任务需要动态判断(如"根据用户意图选择不同工具")→ Agent。Chain 更稳定,Agent 更灵活但更难调试。
面试官可能追问:“Agent 的最大挑战是什么?” → ① 幻觉(Agent 可能调用错误的工具或传错参数);② 无限循环(Agent 可能反复调用同一工具);③ 安全性(Agent 有执行权限,需要严格的安全机制)。
Q79:Function Calling 的工作流程?
- 用户提问 → 大模型分析问题,判断需要调用哪个工具
- 大模型生成工具调用指令(函数名 + 参数)
- 外部系统执行工具,返回结果
- 大模型整合结果生成最终回答
关键:大模型不直接执行工具,它只是"决策者"。
面试官可能追问:“如果模型调用了错误的工具怎么办?” → 需要安全机制:① 工具白名单(只允许调用预定义的工具);② 参数校验(检查参数是否合法);③ 人工确认(高风险操作需要人类确认)。
Q80:MCP 协议是什么?和 Function Calling 的区别?
MCP(Model Context Protocol)是工具调用的统一标准。
| 对比项 | Function Calling | MCP |
|---|---|---|
| 格式兼容 | 各家格式不同 | 统一标准 |
| 工具适配 | 为每个平台单独适配 | 只需实现一次 |
| 类比 | “方言” | “普通话” |
实操建议:如果你在开发 Agent,优先用 MCP(生态在快速增长)。如果目标平台只支持 Function Calling(如 OpenAI),先用 FC,后续迁移到 MCP。
MCP 有三大能力:Tools(工具)、Resources(资源)、Prompts(提示模板)。
Q81:ReAct 模式的工作流程?Thought/Action/Observation 分别是什么?
ReAct = Reasoning + Acting:
- Thought(思考):分析问题,决定下一步
- Action(行动):调用工具
- Observation(观察):查看工具返回的结果
- 重复 1-3 直到信息足够
- Final Answer:生成最终回答
类比侦探破案:思考→调查→观察线索→再思考→直到破案。
面试时怎么讲:“ReAct = 思考+行动。循环:Thought(分析问题)→ Action(调用工具)→ Observation(看结果)→ 重复直到信息足够 → Final Answer。终止条件:LLM 自行判断或最大步数限制。”
面试官可能追问:“ReAct 的终止条件是什么?怎么防止无限循环?” → 两种方式:① LLM 自行判断"信息足够了"并输出 Final Answer;② 设置最大步数限制(如最多 5 轮)。实际中通常两者结合——防止 LLM 判断失误导致无限循环。
Q82:LangGraph 的 State、Node、Edge 概念?
State(状态):Agent 的"工作台",存放所有中间结果。
Node(节点):Agent 的"工作站",每个负责一个特定任务(分析、搜索、生成)。
Edge(边):工作站之间的"连接"。普通边是固定路径,条件边根据状态动态选择路径。
实操建议:如果你在开发 Agent,优先用 LangGraph(LangChain 生态,文档完善)。如果需要更灵活的控制,直接用状态机。LangGraph 的核心优势是可视化调试和 Human-in-the-Loop 支持。
面试官可能追问:“LangGraph 和 LangChain AgentExecutor 的区别?” → AgentExecutor 是简单的循环(Agent→Tool→Agent),LangGraph 是图结构(支持分支、循环、并行),更灵活。复杂 Agent 用 LangGraph,简单场景用 AgentExecutor。
Q83:多智能体(Supervisor 模式)的架构?
Supervisor(经理)负责分配任务给多个专业 Agent:
- 搜索 Agent:只负责搜索
- 代码 Agent:只负责写代码
- 分析 Agent:只负责数据分析
每个 Agent 的上下文窗口保持"干净",不会被不相关的工具描述干扰。
实操建议:简单任务用单 Agent + 多工具就够了。复杂任务(如"调研→写代码→测试→部署")才需要多智能体。Supervisor 模式最常用——经理 Agent 负责分配任务,专业 Agent 负责执行。
面试官可能追问:“多智能体的最大挑战是什么?” → ① Agent 之间的通信(如何传递上下文而不丢失信息);② 错误传播(一个 Agent 出错会影响整个链);③ 成本(每个 Agent 都要调用 LLM,token 消耗翻倍)。
Q84:全量微调 vs LoRA vs QLoRA 的显存对比?
| 方案 | LLaMA-7B 显存需求 | 参考硬件 |
|---|---|---|
| 全量微调 float32 | ~112 GB | 2 张 A100 80GB |
| 全量微调 float16 | ~56 GB | 1 张 A100 80GB |
| LoRA float16 | ~18 GB | 1 张 RTX 4090 |
| QLoRA 4-bit | ~6 GB | 1 张 RTX 3060 |
QLoRA 的显存分布:4-bit 模型 3.5GB(58%)+ 激活值 1.5-2.5GB(30-42%)+ LoRA/优化器/梯度 0.13GB(2%)。
实操建议:预算有限 → QLoRA(RTX 3060 就够);预算充足 → LoRA float16(RTX 4090);追求极致效果 → 全量微调(A100)。大多数场景 LoRA 就够了。
9. 综合题
Q85:从零搭建 Transformer 需要几步?
串联 Q23-Q34 的知识点,按模块拆解:
- 输入层:Token Embedding + Position Embedding(或 RoPE)→ 词向量 + 位置信息
- Encoder Block(重复 N 次):
- Multi-Head Self-Attention:Q/K/V 线性变换 → 缩放点积 → Softmax → 加权求和
- 残差连接 + LayerNorm
- FFN:Linear(512→2048) → ReLU/SwiGLU → Linear(2048→512)
- 残差连接 + LayerNorm
- Decoder Block(重复 N 次):
- Masked Self-Attention(遮盖未来位置)
- Cross-Attention(Q 来自 Decoder,K/V 来自 Encoder)
- FFN + 残差 + LayerNorm
- 输出层:Linear → Softmax → 预测下一个词的概率分布
显存估算:以 6 层 Encoder、$d_{\text{model}}=512$、$d_{\text{ff}}=2048$ 为例,参数量约 2000 万,float32 下约 80MB。
面试官可能追问:“从零搭建和用预训练模型有什么区别?” → 从零搭建适合学习原理,但训练需要大量数据和算力。实际项目中几乎 always 用预训练模型 + 微调——省时省力省算力。
Q86:大模型训练显存占用如何估算?
串联 Q22、Q49、Q75-Q76 的知识点:
$$ \text{总显存} = \text{模型参数} + \text{梯度} + \text{优化器状态} + \text{激活值} + \text{KV Cache} $$以 LLaMA-7B + Adam + float16 为例:
| 项目 | 计算 | 显存 |
|---|---|---|
| 模型参数 | $7B \times 2$ bytes | 14 GB |
| 梯度 | $7B \times 2$ bytes | 14 GB |
| 优化器状态(Adam) | $7B \times (4+4)$ bytes | 56 GB |
| 激活值 | 取决于 batch size 和序列长度 | 4-20 GB |
| KV Cache | 推理时才需要 | ~1 GB |
| 合计 | 88-105 GB |
降显存方案:
- 混合精度(float16 + float32):优化器状态减半 → 省 ~28 GB
- LoRA:只训练 0.1% 参数 → 梯度和优化器状态几乎为零
- QLoRA:4-bit 量化模型参数 → 14 GB → 3.5 GB
- 梯度累积:减少 batch size → 减少激活值显存
面试官可能追问:“为什么优化器状态占这么多?” → Adam 需要存储每个参数的一阶矩(均值)和二阶矩(方差),每个都是 float32(4 bytes)。7B 参数 × 2 个状态 × 4 bytes = 56 GB。这就是为什么 LoRA 省显存——只训练 0.1% 参数,优化器状态也只占 0.1%。