ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI模型面试15题:从评估、微调到工程落地的核心考点解析

AI模型面试15题:从评估、微调到工程落地的核心考点解析

前阵子我帮团队整理技术面题库,陆陆续续面了几十个人,真把“AI模型面试15题”这套东西打磨成了内部笔试之外的必问清单。原因很简单:这几个问题看着基础,实际每个都能往下追两层,背过答案的人会卡壳,真正做过的项目的人反而会越聊越兴奋。下面把每题背后的考察点、回答框架和我自己的评判标准都摊开来讲。准备跳槽的同学可以用来模拟自检,做技术面的朋友也可以直接拿去改造。

这套题并不追求生僻,相反,它刻意选的都是“天天要用的知识”,因为面试要筛的不是百科全书,而是能把模型问题想通、讲清、落地的人。把15题拆开看,刚好覆盖五个维度:机器学习基础、深度学习和微调、工程落地、业务评估、手写代码能力。

1. 基础功底四问:别把“会用”当成“会了”

1.1 分类模型评估怎么回答才不显外行?

面试官开场喜欢问:“你做了一个二分类模型,怎么判断它好不好?”

这个问题的陷阱在于,很多人第一反应是“看准确率”。但准确率有两个致命盲区:类别不平衡时它会被多数类推高;业务代价不对称时它不能反映真实损失。我一般会期待候选人按下面这个顺序展开:先问清楚业务场景,比如这是风控、推荐还是内容识别,误报和漏报的成本分别是多少;再看正负样本分布,如果正样本只占0.1%,准确率基本没有参考价值;最后才落到指标选择上。

这个回答框架的好处是,它展示的不是“我知道一个指标”,而是“我知道指标该怎么服务于决策”。为了更直观看清楚不同指标的用途,可以这样对照:

指标看什么典型场景
Accuracy整体预测正确的比例正负样本均衡、代价对称
Precision预测为正的样本里有多准宁可漏报也不误报的场景
Recall真正例里被找出来多少宁可误报也不能漏报的场景
F1Precision和Recall的调和平均两者都重要时
AUC模型排序能力,不依赖阈值对比模型版本、粗筛模型
PR-AUC正样本极少时排序能力异常检测、欺诈识别

我分享一个真实例子:之前做文本内容识别,负样本占99%,把全部判成负样本准确率也是99%。但业务真正要抓的是那1%的违规内容,所以团队只看坏样本Recall在Precision达到95%前提下能到多少,准确率这个数字从头到尾就不出现在周报里。候选人如果能举出类似“准确率99%但不解决问题”的案例,基本就能过这道关。

实操心得:准备一个你亲手做过的评估案例,把“为什么不用准确率”讲成故事,不要干背公式。面试官问AUC时,最好顺手补一句“AUC只代表排序能力,不代表线上阈值命中效果”,这句话能区分看书和动手。

1.2 过拟合怎么发现、怎么治?

这个问题看似轻松,实际最能暴露新手和老手的差别。新手回答通常直接说“加正则、加Dropout、加早停”,但我会追问“你如何先判断它是过拟合而不是欠拟合?”

正确顺序是先看训练集误差。如果训练集精度也很低,说明模型容量不足或特征不够,这时候加Dropout只会雪上加霜。只有当训练集误差持续下降、验证集误差开始回升时,才能确认过拟合。所以我的答题模板是:先画训练和验证损失曲线,观察两条曲线的gap;再从数据角度缓解,扩样本、数据增强、清理异常标签;最后才是正则、早停、降复杂度这些模型手段。

很多人会漏掉一个点:交叉验证里的划分不当也会制造“伪过拟合”。比如时间序列数据用随机K折,验证集里混进未来信息,会让验证曲线表现失真。能主动提到这一点的人,通常是真的处理过真实数据,而不是只在比赛平台里跑过baseline。

实操心得:我自己排查过拟合时,会先把错误样本拎出来看,很多看起来是过拟合的问题,实际是标签噪声。标签错上几个点,模型再正则也白搭,先把脏标清理掉,比调一星期参数都管用。这个排查顺序改变了我做项目的节奏:先看数据质量,再谈模型调参。

1.3 类别不平衡,别一上来就过采样

这类题我见过太多统一答案:“SMOTE”。但真实项目里SMOTE不是首选,因为你根本不知道合成样本在特征空间里是否可信。我建议的回答分三层:

第一层是重新定义目标。业务到底要优化什么?很多“不平衡”场景其实应该做成排序问题或者分群问题,而不是硬分类。第二层是调整训练策略,class weight、focal loss、阈值移动三件套里,先试class weight最稳妥,因为它不改变样本本身,只改变梯度贡献。第三层才是数据层面的欠采样或过采样,必要时用SMOTE,但要验证合成样本没有引入噪声。

一个可以讲的案例:某异常行为检测项目,正样本只有千分之二,直接训练出来的模型Recall极低。我们把问题从“判断是否异常”改成“给异常行为打分排序”,再把阈值调到业务可接受的误报率上,效果立刻不一样。这个思路比任何采样技巧都更能打动面试官,因为它体现的是把算法问题翻译成业务问题的能力。

实操心得:别把“AUC高”当成成功。极端不平衡下ROC曲线会被大量负样本灌水,PR曲线更能反映真实进步。所以我评估这类模型时固定看 recall@precision=0.9 这种业务指标,而不是只看一个孤立的AUC数值。

1.4 特征工程到底问什么、答什么?

特征工程问法很多,但核心无非是:处理缺失值、连续特征离散化、特征选择和特征交叉。候选人不需要背出来“业界十招”,能把链路讲通就行。

我的参考回答是:缺失值先看缺失机制,如果缺失和预测目标有关,直接填充会引入偏差,可以先加“是否缺失”标记,再决定是填充还是删字段;连续特征做离散化,本质是为了引入非线性、方便在线服务做映射,同时降低异常值影响;特征选择不要只靠相关性,还要看特征的历史分布和上线成本,线上没有的特征,离线做再多工程也是白做。

这里有一个面试官高频追问:“为什么离线加了特征,线上却完全没提升?”我最想听到的答案是“回看特征是否用了未来信息,是否只有离线表才有、在线实时取不到”。能说清这件事的人,工程意识基本过关,因为他清楚离线实验和在线系统的边界。

实操心得:特征工程不是为了炫技,是为了降低模型的搜索难度。我常把一句话挂在嘴边:好特征是“把答案的线索摆到桌面上”,而不是“把所有线索一股脑堆在桌上”。面试时如果能用这样一个概括收尾,会让面试官觉得你有方法论。

2. 深度学习与大模型四问:Transformer不是背出来的

2.1 自注意力为什么要除以根号d_k?

在Transformer里,自注意力公式写作 Attention(Q,K,V)=softmax(QK^T/√d_k)V。如果只背公式,不问为什么,那面试是撑不过追问的。答案核心在于数值分布和梯度稳定性:

Q和K的维度是d_k,它们的点积是d_k个独立随机变量的和,方差约为d_k。当d_k较大时,点积结果的方差随之变大,值域被推到softmax的饱和区。softmax在饱和区梯度很小,反向传播时模型很难学。除以√d_k之后,方差被压回1,softmax输入落在一个相对温和的区域,梯度就能稳定流动。

这里可以补一个直观类比:两个人各写了一串向量,点积结果就像把两串数字逐位相乘再求和。维度越宽,结果波动越大,如果不缩放,注意力分数会出现“一个值特别大、其他都趋近于零”的极端局面,模型就退化成在做硬选择,失去了对上下文的细粒度区分能力。

面试官大概率还会追问:“为什么不是除以d_k而是√d_k?”因为除以d_k会把方差压得过小,注意力分布过于平坦,等于失去选择性。所以√d_k是让方差为1的缩放因子,既不给某个位置绝对话语权,也不让所有位置糊成一片。这个推导虽然不难,但能当场讲清的人并不多。

2.2 参数高效微调怎么选型?

大模型面试必问微调:全参微调vs参数高效微调,你在项目里用哪种,为什么?

比如LoRA设计,冻结预训练权重,注入低秩矩阵近似更新。它最大价值是让微调成本从“重新训练一个大模型”降到“训练一个小适配器”,同时每个下游任务只需要存少量增量参数。回答时要带出选择逻辑:数据量小、只想适配特定任务语法,用LoRA或Adapter;需要把模型变成垂直领域专家,数据量也够,才考虑全参微调,但要提前准备好灾难性遗忘的应对方案;在线服务要节省显存和加载成本,用LoRA合并权重,避免部署时带额外分支。

细节上,LoRA的rank和alpha需要实验。我实测的经验是rank=8到16在大多数任务上就够用,不是rank越大越好;alpha通常设为rank的1到2倍。target modules如果只锁住attention里的q、v,和把所有线性层都替换掉,结果会差不少,我一般从q、v开始,看loss变化再扩展。

实操避坑:LoRA微调前先确认基座版本,不同版本之间的分词器或hidden size变了,直接加载会报错或者静默出错。很多翻车不是模型问题,是环境基座不匹配。面试时能讲出这种细节,比背一整套微调流程要更能立住“真做过”的人设。

2.3 温度、Top-p、Top-k怎么搭配用?

生成式模型面试里,“讲一下温度和Top-p”属于送分题,但送分题最容易暴露死记硬背。Temperature是作用在logits上的缩放,温度越高概率分布越平滑,采样结果越发散;温度越低越接近贪心,但过低会退化到重复套话。Top-p是把累积概率超过阈值的候选词筛出来,再重新归一化。Top-k是按logits从大到小截断前k个,二者可以叠加。

一个合格回答要落到场景上:代码生成或者数学题,建议低温度0.2到0.3,目的是稳定少幻觉;开放聊天、营销文案,0.7到1.0适合探索多样性;抽取式任务直接温度0,因为不需要创造性。

面试官如果接着问“为什么温度高了会胡说八道”,你要能解释温度不会让模型掌握新知识,只是让低概率候选获得更多采样机会。低概率词在训练数据里出现得少,本身可靠性就差,采样到它们当然更容易出错。这本质上不是在改变模型的“知识”,而是在改变“探索的胆子”。

实操心得:评测生成质量千万别忘了固定随机种子、固定采样参数。我见过同一份prompt在两次评测里因为温度不同导致结论完全反过来,最后查了半天才发现是测试脚本默认temperature=0.8,另一个跑的是0.2。做对比实验时,除了对比项之外的一切变量都要焊死。

2.4 灾难性遗忘怎么缓解?

微调任务最容易踩的坑就是“在这个domain上变得好用,但通用能力断崖式下跌”。考察点就是候选人有没有全局意识,眼睛只盯着下游指标,迟早要还账。

缓解方案从轻到重可以这么排:混合通用语料,在下游数据里掺入10%到30%的通用数据,能明显稳住基础能力;回放机制,从老任务采样一部分数据,和当前任务一起训练;低秩约束,用LoRA这类参数高效方法,本质是限制参数更新扰动,也可以减轻遗忘;损失约束,在微调损失之外加一项与旧模型输出分布的KL散度,让它别偏离太多。

可以补充一个实际案例:我做过一个客服问答方向的微调,只喂业务对话,结果模型连“今天天气怎么样”都不想答了。后来把单轮常识问答数据按2:8和业务数据混合进去,通用对话能力回来了一些,垂直意图识别也没下降。这个故事虽然简单,但比念十遍“回放、正则”都更有说服力。

3. 工程落地三问:模型能跑通和能上线是两回事

3.1 模型上线前,哪几类数据泄漏必须查?

数据泄漏漏一轮,线下指标全是虚的。常见有三种:时间泄漏,特征里用了预测时刻的未来信息,比如用全天点击量预测上午的点击行为;目标泄漏,训练特征直接或间接包含答案,比如做违约预测,却把“是否已经逾期”放进了特征;预处理泄漏,先用全体数据算均值或做标准化,再切分训练验证,验证集会“偷看”训练集的信息。

我建议候选人给出一个查泄漏的checklist:每个特征字段都要标注产生时间戳;保存特征时严格使用历史窗口;划分必须在任何统计计算之前;去重和异常值清理也要防止同一用户出现在两个集合。

这里面试官很吃一个细节:同一用户反复出现在训练集和测试集,会导致模型“记住人”而不是“学到规律”。能在回答里主动提到“按用户去重切分”的人,说明真的独立搭过训练数据管线。线上模型上线后效果差,有相当大比例是这类泄漏没堵住。

3.2 线上模型效果变差,怎么定位?

这个问题考察的是排查体系的完整度,而不是某个酷炫算法。我推荐一个系统化排查顺序:

  • 确认是哪个指标掉了,点击率、转化率还是延迟,先把症状定义清楚。
  • 分维度下钻,渠道、地域、用户新老、设备,先定位影响范围。
  • 计算分布漂移,统计线上实时特征和训练集特征的PSI/KL,看哪些特征变化最大。
  • 看上游依赖,标签口径是否变了、特征服务是否有bug、实验环境是否被其他策略污染。
  • 回放模型,拿同批线上日志喂给新旧两个模型,看是数据问题还是模型问题。

一个可以说的经验:某一次线上点击率掉了5%,查完发现不是模型坏了,而是上游特征服务发布新版本后把某些字符串字段解析成了空值,模型输入大量缺省,分布一变,预测全偏。这类问题不是重训能解决的,先把上线信息的质量管好再谈新模型。

现象优先排查方向验证方式
单指标下跌上游数据变更、特征缺失回放线上日志对比新旧模型
局部人群下跌流量分配、人群漂移分维度下钻
全量普跌训练分布过期、环境变化PSI/KS分布监控

排查心得:给线上问题定位时,先不要急着怀疑算法。大量线上指标恶化其实是数据管道问题、实验污染问题,模型本身并没有变。学会把“模型背锅”的可能性放在最后,是工程成熟度的标志。

3.3 推理延迟太高,先优化哪个环节?

如果候选人做过在线推理,这道题他能聊十分钟。我建议按分层排查:先看预处理,文本要不要截断、重复prompt的公共前缀缓存能不能复用;再看模型前向,动态形状导致无法预分配显存、序列过长导致计算量平方级增长,量化、批处理、算子融合、KV cache都是手段;最后看后处理与服务依赖,解码策略是否复杂、有没有外部RPC串行调用。

别一上来就谈分布式推理。面试官更想听你能不能先找瓶颈:用profiler看耗时分布,是GPU算力瓶颈还是数据搬运瓶颈?是单请求延迟重要还是吞吐重要?这两个维度决定了你选“加大batch”还是“增加并发”还是“换小模型”。

举个例子:在某个生成类服务里,我们把后处理的超时重试逻辑改了,延迟p99从1.2s降到600ms,比量化模型收益还大。很多人一谈性能就想着量化,往往忽略外围代码里的串行阻塞。先量化每一层耗时,再动手优化,才是稳的路径。

4. 业务思维两问:模型要给业务回答问题,而不是只出指标

4.1 A/B实验怎么设计才科学?

这道题关键在“怎么回答才不算拍脑袋”。我的常规框架是:先定主指标,一个OEC,比如业务真正关心的转化率或收益,不能同时挑七八个“显著”指标吹结果;再确保实验可信,AA分组验证、样本量估算、实验周期覆盖一个完整业务周期;最后考虑多重比较,看太多指标、做太多次中途观测,都可能制造假显著。

经常被追问的细节是样本量计算。可以用简单方式说明:业务指标本身的方差越大,需要的样本量越大;预期提升幅度越小,需要的样本量越大。样本量不够就别急着下结论,一个常见的错误是上线第三天看到涨了2%就欢呼,其实那可能只是随机波动。

一个真实的翻车经历:我们当时上线一个模型,离线AUC涨了1.5%,顺手开了个A/B,第一周转化率涨了3%,大家很高兴,第二周变成跌1%。后来复盘发现第一周新模型分配到了高质量流量,样本不够均衡。所以我现在要求所有实验在分析前先加一层“流量均衡性检查”,对比实验组和对照组在核心画像维度上的分布一致性。

4.2 损失函数选不好,训练白忙一场?

把这个当成业务问题来答,别光罗列公式。回归任务里,MSE对异常值很敏感,MAE梯度恒定但收敛慢,Huber是两者的折中,适合带噪声数据;分类任务里,CrossEntropy只管“分对分错”,Focal Loss会把难样本权重提上来,正负样本极度不平衡时,损失函数本身就可以参与平衡;排序任务里,pointwise适合打分,pairwise比大小,listwise整体优化NDCG。

关键答题技巧是,要说出“你选某个损失是因为它和线上考核指标更接近”。比如业务考核的是AUC,那训练目标就别执着于MSE的绝对值;业务考核的是NDCG,那pointwise可能不够,至少要pairwise损失。

场景常用损失注意点
回归,噪声小MSE收敛快,对异常敏感
回归,有离群点Huber需要调delta
二分类,类别均衡CrossEntropy配合softmax
二分类,极不平衡Focal Loss调gamma,别默认值硬套
排序,追求整体顺序Listwise实现复杂,数据准备成本高

一个小坑:很多人用Focal Loss时不调gamma,结果难样本被过度放大,模型反而震荡。我一般从gamma=2往下调,同时配合类别权重一起看,并在验证集上观察是否真的把难样本找对了。

5. 手写代码两问:光会说不如能算

5.1 逻辑回归训练循环,5分钟写出来

有些候选人聊起来头头是道,一写代码就露馅。我最常让人写的是逻辑回归,因为它短、考基础、能看出工程风格。参考代码如下:

import numpy as np def sigmoid(z): # 数值稳定的sigmoid return np.where(z >= 0, 1 / (1 + np.exp(-z)), np.exp(z) / (1 + np.exp(z))) def compute_loss(y, prob): eps = 1e-12 return -np.mean(y * np.log(prob + eps) + (1 - y) * np.log(1 - prob + eps)) def train(X, y, lr=0.1, epochs=100, batch_size=32): n, d = X.shape w = np.zeros(d) b = 0.0 for epoch in range(epochs): idx = np.random.permutation(n) for i in range(0, n, batch_size): batch_idx = idx[i:i + batch_size] X_b, y_b = X[batch_idx], y[batch_idx] prob = sigmoid(np.dot(X_b, w) + b) grad_w = np.dot(X_b.T, (prob - y_b)) / len(y_b) grad_b = np.mean(prob - y_b) w -= lr * grad_w b -= lr * grad_b if epoch % 10 == 0: prob = sigmoid(np.dot(X, w) + b) print(f"epoch {epoch}, loss {compute_loss(y, prob):.4f}") return w, b

这里值得说的细节:sigmoid在z很小时直接用 1/(1+exp(-z)) 可能溢出,写成np.where版本更稳;梯度推导要会写,因为sigmoid的导数和交叉熵正好相消,所以prob-y这个形式不是记出来的,是推出来的。能现场推导一次的人,记忆会深刻很多。

写完之后面试官常追加一句“如果loss没有下降,你检查哪里?”可以答:检查数据是否归一化、学习率是否过大、标签是否错位,不要一上来就调模型结构。这个回答比“调学习率”更完整,因为它是按可能性排序的。

5.2 top-k采样怎么写才不bug多?

大模型方向的提问会变成手写一个采样函数。参考实现:

import numpy as np def temperature_top_k_sampling(logits, k=50, temperature=1.0): # logits: 一维向量,代表每个token的得分 if temperature == 0: return int(np.argmax(logits)) probs = np.exp(logits / temperature) probs = probs / np.sum(probs) if k is not None and k > 0: top_k_idx = np.argsort(probs)[::-1][:k] top_k_probs = probs[top_k_idx] top_k_probs = top_k_probs / np.sum(top_k_probs) return int(np.random.choice(top_k_idx, p=top_k_probs)) return int(np.random.choice(len(probs), p=probs))

这题考的是三点:知道采样是在概率分布上做选择;知道温度要先作用到logits再softmax;知道Top-k截断后需要重新归一化。大部分只会调API的人,到这就会卡住。

实操心得:写这种代码时别着急,面试官更关心你的边界处理。比如temperature=0要特判、概率相加要用浮点误差兜底、np.random.choice的p参数必须和为1。这些小细节最能看出你是不是天天在写生成代码,而不是只会调现成接口。

6. 项目拷问与复盘:最后一题往往是“你自己”

6.1 被追问到空白处时,怎么稳住?

技术面末尾经常是“讲一个你最满意的项目”,然后连环追问。这个环节没有标准答案,但有一个很稳的应对框架:STAR。先交代Situation,当时要解决什么问题,背景数据规模多大;再讲Task,你负责的是哪一块,和谁协作;然后是Action,为什么选这个方案,当时的备选项是哪些;最后是Result,带来了什么可量化的变化,注意量化要真实可解释。

既然面试官会追问数字,那简历上每个指标都要能扛三连问:这个数怎么算的?为什么它重要?它变化一个点对业务意味着什么?答不上来,前面印象分全扣。

我自己面试别人时会特别留意候选人讲“失败项目”。能把“自己哪一步拍脑袋拍错了”说清楚的人,通常比把所有项目都包装成成功的人靠谱得多。所以不用怕暴露问题,要主动说出“如果重来,我会先做特征校验而不是直接调模型”。这种反思能力,比把项目讲得天花乱坠更能建立信任。

6.2 15题背后的复盘方法论

最后说点方法论角度的事。这15题不是题目清单,而是四个能力维度的抽样:原理理解、工程落地、业务思维和动手能力。我建议准备面试的人做一个错题本,每次模拟面之后,把自己没答好的问题按这四类归类,然后补对应的功课。

工程能力不够就补“上线监控和数据泄漏”,原理不够就回去推自注意力和损失函数梯度,业务不够就找两个曾经的项目重新算一遍收益,动手不够就每天在本地写一个二十行的小函数。我第一次做技术面评审时也很紧张,后来发现面试官真正想要的是一个“遇到问题知道怎么拆解”的人,而不是背完所有面经的“行走知识库”。把这15题当成自检,比当成押题价值大得多。

最后说两句我自己的体会。这个行业变化很快,但面试底层逻辑一直没变:你能不能在有限信息下做出合理判断,并且把判断讲得让人信服。很多候选人问我有没有捷径,我的答案永远是“拿自己真实项目反复拆解”。把每个项目的背景、指标、替代方案、失败原因都理清楚,面试官问什么你都能回到自己的主线上来。这套“AI模型面试15题”也只是帮你暴露盲区,真正能救你的,还是你动手做过的那几个项目。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进