正确做法是先用train_test_split固定测试集,再对训练集按样本数递增切片并逐轮重训模型;训练误差在当前子集上计算,测试误差始终在固定测试集上评估,横轴必须为实际样本数。

怎么用 train_test_split 控制训练集大小画趋势图
核心是固定测试集、逐步增大训练集,而不是随机切分多次——否则测试误差波动大,趋势看不清。
常见错误是每次调用 train_test_split 都重采样测试集,导致测试误差上下跳,误以为模型不稳定。正确做法是先一次性分离出**固定的测试集**,再对训练部分做递增切片。
- 先用
train_test_split(X, y, test_size=0.2, random_state=42)拿到固定X_test和y_test - 对剩下的
X_train_full/y_train_full,按比例(如 0.1, 0.2, ..., 1.0)取前 N 行,用X_train_full[:n]切片,别用train_test_split再分 - 每轮都用同一套
X_test/y_test评估,确保测试误差可比
训练误差和测试误差怎么算才不误导
训练误差必须在「当前训练子集」上算,不是在原始全量训练集上;测试误差始终在固定测试集上算。否则训练误差虚低,过拟合现象压根出不来。
典型翻车点:用 model.fit(X_train_full, y_train_full) 一次训完,再拿不同子集去 predict——这根本不是“小数据训练”,只是在做预测子集,误差曲线会异常平滑,完全掩盖过拟合。
- 每轮都要重新
model.fit(X_train_sub, y_train_sub),其中X_train_sub是当前大小的子集 - 训练误差用
model.score(X_train_sub, y_train_sub)(或mean_squared_error等),不是X_train_full - 测试误差统一用
model.score(X_test, y_test),保持分母一致
用 matplotlib.pyplot.plot 画两条线要注意什么
横轴是训练样本数(不是比例),纵轴是误差值;两条线必须共用同一横坐标序列,否则对不齐。很多人直接画“比例 vs 误差”,结果 x 轴刻度不等距,视觉上扭曲收敛速度。
性能影响不大,但兼容性差在:如果用 sklearn.model_selection.learning_curve,它默认返回的是带 cv 折叠的均值和标准差,不适合这里单次训练+固定测试的场景,容易多绕弯。
- 横坐标用实际样本数列表:
n_samples = [int(0.1 * len(X_train_full)), int(0.2 * len(X_train_full)), ...] - 训练误差和测试误差分别存两个 list,长度和
n_samples严格一致 - 画图时明确写
plt.plot(n_samples, train_errors, label="Train error")和plt.plot(n_samples, test_errors, label="Test error")
learning_curve 能不能直接拿来画这个图
能,但默认行为不符合需求:它做 k 折交叉验证,训练集大小是按 fold 切的,且测试误差是各 fold 在各自验证集上的平均,不是你手控的固定测试集。结果就是测试误差线毛刺多、趋势模糊,还可能因 fold 划分引入额外方差。
如果你硬要用,必须关掉 cv 的随机性、强制单折、并把 test_size 固死——但这么改还不如手动循环清晰。真正省事的场景是诊断模型容量,不是画教科书式过拟合曲线。
- 不要设
cv=5,改用cv=ShuffleSplit(n_splits=1, test_size=0.2, random_state=42) - 传入的
X和y应该是原始全量数据,不是已切分好的训练集 - 返回的
train_scores和test_scores是二维数组,需取[:, 0]提取唯一 fold 的结果
过拟合趋势图的关键不在画得漂亮,而在训练集增长方式和测试集稳定性——这两点一松动,图就失去诊断价值。很多人花半小时调样式,却没发现横坐标是比例、测试集每次都在变。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











