楼层: 首页/ 软件技术/ Python 机器学习与深度学习/ 常见坑与 30 道高频面试题
16

常见坑与 30 道高频面试题

Pitfalls & 30 Interview Questions

最后把所有坑和面试题过一遍。建议打印出来,面试前一晚读一遍。

七大常见坑

坑说明
数据泄漏切分前做预处理。永远先 split 再 fit。
类别不平衡accuracy 骗人。看 PR-AUC / F1 / class_weight。
特征缩放时机树模型不用缩;线性/SVM/NN 必须缩。
梯度消失/爆炸ReLU + 合理初始化 + BatchNorm + 梯度裁剪。
学习率不对loss=NaN 先降 lr 到 1e-4。
batch 太大泛化差、显存爆。
只看训练 loss必须看验证 loss,早停。

数据泄漏完整示例

# 常见数据泄漏场景: # 1. 切分前标准化 X_scaled = scaler.fit_transform(X) # 错:测试集信息泄漏 X_train, X_test = train_test_split(X_scaled, y) # 2. 切分前做特征选择 selector = SelectKBest(k=10).fit(X, y) # 错 X_selected = selector.transform(X) X_train, X_test = train_test_split(X_selected, y) # 3. 时间序列随机打乱 X_train, X_test = train_test_split(X, y, shuffle=True) # 错:未来进训练集 # 应该用 TimeSeriesSplit # 4. 目标编码泄漏 df["city_target"] = df.groupby("city")["target"].transform("mean") # 错:用全量 target # 应该在交叉验证折内做目标编码 # 5. 测试集参与增强 # 数据增强只应该在训练集做,验证/测试集只做 resize + normalize

类别不平衡处理方案

方法说明
class_weightsklearn 模型自带,按类别频率加权,最简单。
过采样 SMOTE少数类合成新样本,注意只在训练折做。
欠采样随机删多数类,数据够大时用。
阈值调整不把 0.5 当决策边界,按业务调。
换指标看 PR-AUC / F1 / 混淆矩阵,别看 accuracy。

模型选择偏差

论试了 10 个模型选最好的

如果你在测试集上试了 10 个模型选最好的,这个"最好"是有偏的——你碰巧选到了在这个测试集上运气好的那个。正确做法:用验证集选模型,测试集只碰一次。或者用嵌套交叉验证(外层选模型,内层调参)。

梯度消失与爆炸:为什么深层网络难训

# 假设网络有 10 层,每层激活函数导数小于 1 # 链式法则连乘 10 次:0.5^10 ≈ 0.001,梯度消失 # 如果导数大于 1:1.5^10 ≈ 57,梯度爆炸 # 对策: # 1. ReLU:正区间导数恒为 1,不饱和 # 2. 合理初始化:Xavier(方差 = 2/(n_in+n_out)),He(ReLU 用) # 3. BatchNorm:每层输入标准化,让梯度分布稳定 # 4. 残差连接:梯度可以"抄近路"传到前面 # 5. 梯度裁剪:torch.nn.utils.clip_grad_norm_(params, 1.0)

常见坑速查表

现象可能原因 & 对策
loss = NaN学习率太大 / 数据有 NaN / 除零。先降 lr 到 1e-4。
训练 loss 不降学习率太小 / 模型太简单 / 数据没标准化。
训练好测试差过拟合:加正则、Dropout、早停、加数据。
训练测试都差欠拟合:换复杂模型、加特征、减少正则。
GPU out of memory减小 batch_size / 用混合精度 / 关掉 no_grad。

过拟合识别:怎么看学习曲线

# 训练 loss 和验证 loss 的关系: # 1. 两条都降,验证 loss 稳定 = 正常 # 2. 训练 loss 降,验证 loss 升 = 过拟合(早停) # 3. 两条都不降 = 欠拟合(换模型/加特征) # 4. 两条都高 = 数据/标签有问题 # 代码里每轮记录 history = {"train_loss": [], "val_loss": []} for epoch in range(30): # ... 训练 ... history["train_loss"].append(train_loss) history["val_loss"].append(val_loss) # 画出来 plt.plot(history["train_loss"], label="train") plt.plot(history["val_loss"], label="val") plt.legend() plt.show()

30 道高频面试题(折叠答案)

面试 · 30 道速刷

1. 监督学习和无监督学习区别?

答案

有标签 vs 无标签。前者学 X→y,后者自己找结构。

2. 过拟合怎么办?

答案

加数据、简化模型、正则化、Dropout、早停、数据增强。

3. 偏差和方差哪个对应过拟合?

答案

高方差。

4. L1 和 L2 区别?

答案

L1 稀疏、L2 小而不零。

5. 为什么用交叉熵不用 MSE 做分类?

答案

Sigmoid+MSE 非凸;交叉熵梯度形状好。

6. precision 和 recall 怎么权衡?

答案

移阈值,画 PR 曲线。

7. ROC-AUC 0.5 是什么意思?

答案

瞎猜。

8. 决策树为什么会过拟合?

答案

不限制深度会背答案。

9. 随机森林为什么比单棵树强?

答案

样本+特征双重随机,降方差。

10. Bagging 和 Boosting 区别?

答案

并行 vs 串行;降方差 vs 降偏差。

11. XGBoost 比 GBDT 多了什么?

答案

正则化、二阶泰勒、缺失值、并行。

12. LightGBM 为什么快?

答案

直方图算法 + Leaf-wise + GOSS。

13. SVM 为什么要标准化?

答案

用距离,量纲影响结果。

14. 什么是支持向量?

答案

离超平面最近的样本。

15. 核技巧是什么?

答案

低维算内积等价高维。

16. 朴素贝叶斯为什么朴素?

答案

假设特征条件独立。

17. KNN 怎么选 K?

答案

交叉验证。

18. K-Means 怎么选 K?

答案

肘部法则 + 轮廓系数。

19. DBSCAN 优点?

答案

不用定 K,任意形状,识别噪声。

20. PCA 为什么要标准化?

答案

找方差方向,量纲影响。

21. t-SNE 能当预处理吗?

答案

不能,只可视化。

22. 为什么需要激活函数?

答案

否则多层还是线性。

23. ReLU 好在哪?

答案

不饱和、快、稀疏。

24. 梯度消失怎么办?

答案

ReLU、合理初始化、BatchNorm、残差。

25. 反向传播是什么?

答案

链式法则逐层求导。

26. SGD / Adam / AdamW 区别?

答案

SGD 朴素;Adam 自适应学习率;AdamW 拆开权重衰减。

27. BatchNorm 为什么有效?

答案

每层输入标准化,收敛快。

28. 学习率怎么调?

答案

1e-3 起步,warmup + 余弦退火,loss=NaN 就降 lr。

29. BERT 和 GPT 区别?

答案

双向编码器 vs 单向解码器。

30. LoRA 为什么省显存?

答案

冻结原模型,只训低秩小矩阵。