8
常见坑与最佳实践
Pitfalls & Best Practices
AI 圈的坑比基础语法多——因为你面对的是数据、模型、GPU 一堆东西。下面八个坑,每个都让无数人熬夜过。
坑 1:NumPy 广播不匹配
# (3,) 的向量和 (3,3) 的矩阵相加会广播,但
a = np.array([1, 2]) # shape (2,)
b = np.array([[1], [2], [3]]) # shape (3,1)
# a + b 会变成 (3,2),不是你以为的 (3,)
# 报错 ValueError: operands could not be broadcast together 时
# 先 print(a.shape, b.shape) 看形状对不对
# 调试技巧:拿不准广播结果,先小数据试
np.array([1,2]) + np.array([[10],[20]])
# array([[11, 12],
# [21, 22]])
坑 2:Pandas SettingWithCopyWarning
这个警告啥意思
你先 df[df["age"] > 18]["age"] = 0 想改一列,Pandas 警告你"这可能是个副本,你改的不是原表"。正确写法:用 .loc:df.loc[df["age"] > 18, "age"] = 0。别用链式索引改数据。
坑 3:数据泄漏
论最隐蔽的坑
如果你在切分训练/测试集之前就做了标准化、填缺失值、特征选择——那测试集的信息已经"漏"进训练过程了。你本地准确率 99%,上线变成 60%。正确做法:先 train_test_split,再用训练集 fit scaler,然后 transform 训练集和测试集。特征工程全部在训练集上 fit。
坑 4:过拟合
| 现象 | 怎么办 |
|---|---|
| 训练集准确率 99%,测试集 70% | 典型过拟合——模型背答案了。 |
| 对策 1 | 加数据(最有效)。 |
| 对策 2 | 简化模型(减少层数/参数)。 |
| 对策 3 | 正则化:L1/L2、Dropout。 |
| 对策 4 | 早停(early stopping):验证集 loss 不降就停。 |
# PyTorch 里的早停思路:记最好的验证 loss,连续 N 轮不改善就停
best_val = float("inf")
patience = 5
bad_epochs = 0
for epoch in range(50):
# ... 训练 ...
val_loss = evaluate()
if val_loss < best_val:
best_val = val_loss
bad_epochs = 0
torch.save(model.state_dict(), "best.pth")
else:
bad_epochs += 1
if bad_epochs >= patience:
print("早停!")
break
坑 5:类别不平衡
如果 99% 的样本都是"正常",1% 是"异常",那模型啥也不学、全猜"正常",准确率也是 99%。这时候 accuracy 是假的——看 precision、recall、F1,或者用混淆矩阵。处理方法:过采样少数类(SMOTE)、欠采样多数类、调整 class_weight。
# 方法1:sklearn 模型自带 class_weight(最简单)
model = RandomForestClassifier(
class_weight="balanced", random_state=42
)
# 方法2:SMOTE 过采样少数类(pip install imbalanced-learn)
from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X_train, y_train)
# 然后用 X_res, y_res 训练
坑 6:PyTorch 梯度没清零
# 每轮训练开头一定要 zero_grad(),否则梯度会累加
# 下面这段是错的(少了 optimizer.zero_grad()):
# for x, y in loader:
# out = model(x)
# loss = criterion(out, y)
# loss.backward()
# optimizer.step() ← 梯度是上几轮累加的,模型会飞
# 正确:每个 batch 开头
optimizer.zero_grad()
out = model(x)
loss = criterion(out, y)
loss.backward()
optimizer.step()
坑 7:CPU 和 GPU 张量混着算
# model 在 GPU 上,数据在 CPU 上,会报 RuntimeError
# RuntimeError: Expected all tensors to be on the same device
images = images.to(device)
labels = labels.to(device)
model = model.to(device)
# 三者必须在同一个设备上
记
AI 项目最佳实践
① 先跑通最小流程:别一上来就搞大模型,先用 100 条数据跑通训练-评估。
② 永远固定 random_state,否则结果不可复现。
③ 用 Jupyter 探索,用 .py 文件训练——探索期交互,正式训练用脚本。
④ 看数据先于看模型:画几张图、describe 一下,80% 的问题在数据里。
⑤ baseline 先行:先用最简单的模型(逻辑回归、随机森林)跑出基线,再折腾深度学习。