cross_val_predict
为每条样本产生其不在训练折时的预测,适合诊断和严格堆叠特征。
学习前需要掌握
背景与问题
有时需要每个样本的一份未被该轮模型训练过的预测,用于观察残差、混淆或构建后续开发特征。cross_val_predict 将各验证折预测放回原样本顺序,形成折外预测。
这与返回每折平均分不同,也不是一个最终模型对全部数据的预测。生成结果的实际上是多个不同训练子集上的模型。
概念定义
每条预测来自不同折模型,不是一个最终部署模型的输出集合。
直观理解
每条样本都由没看过它的临时模型作答,最后把答案拼起来。
核心原理
标准使用要求每行恰好出现在一个验证折,形成完整分区。重复 K 折会让每行出现多次,某些时间划分会让早期行从未验证,因此不能不加处理地用于 cross_val_predict。
method 决定返回标签、概率或决策分数。predict_proba 输出列对应类别顺序,读取正类列前必须明确标签;多分类的每行概率应与类别集合匹配,而不是随意取第二列代表“正确概率”。
拼接预测计算的总体指标不一定等于每折指标的简单均值。折大小不同、F1 等非线性指标或每折类别分布不同,都可能导致差异;报告时应说明计算口径。
折外预测可以用于阈值开发或上层模型,但后续选择仍会利用这些标签,不能再把同一组上的最佳结果当作独立评价。堆叠与阈值选择需要额外独立验证或正确嵌套。
数学表达
核心表达
阈值或上层模型若使用这些预测,也需额外独立验证和严格嵌套;不能把拼接预测误称最终模型预测。
变量含义
变量定义与本页概念定义一致,代码中的同名变量保持相同语义。
计算步骤
- 1固定 CV
- 2选择 method
- 3生成 out-of-fold 预测
- 4诊断错误/概率
代码对应位置
示例 1生成完整分区上的二分类折外概率:完整输入、分层器与 Pipeline 生成可核对的折外概率,仅验证接口与覆盖。
案例:每朵花获得一份折外正类概率
取 Iris 的前两类共 100 行,按 3 折分层生成概率。每个样本由没训练过它的那个折模型预测,最终数组形状为 100 × 2,顺序与原始输入一致。
如果随后在这 100 个概率上找出 F1 最好的阈值,那么这批数据已被用于选阈值,所得最高 F1 不能作为独立最终评价。下方只核对形状、类别和概率和,不做阈值优化,也没有输出部署模型。
计算与实现步骤
- 固定 CV
- 选择 method
- 生成 out-of-fold 预测
- 诊断错误/概率
- 额外验证阈值或堆叠
- 训练最终模型
代码实现
示例 1
生成完整分区上的二分类折外概率
example_01.py用途:完整输入、分层器与 Pipeline 生成可核对的折外概率,仅验证接口与覆盖。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
mask = y < 2
X, y = X[mask], y[mask]
cv = StratifiedKFold(3, shuffle=True, random_state=42)
pipeline = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
probability = cross_val_predict(pipeline, X, y, cv=cv, method="predict_proba")
assert np.allclose(probability.sum(axis=1), 1.0)
print("shape:", probability.shape)
print("class_order:", np.unique(y).tolist())
print("positive_probability_count:", len(probability[:, 1]))代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
完整输入、分层器与 Pipeline 生成可核对的折外概率,仅验证接口与覆盖。
X- 完整特征矩阵,每行一个样本、每列一个特征。
y- 目标标签或连续目标值。
Step 1 · 1–6 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScalerStep 2 · 8–17 行
输出中间参数、形状或最终指标,用于核对代码是否符合预期。
X, y = load_iris(return_X_y=True)
mask = y < 2
X, y = X[mask], y[mask]
cv = StratifiedKFold(3, shuffle=True, random_state=42)
pipeline = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
probability = cross_val_predict(pipeline, X, y, cv=cv, method="predict_proba")
assert np.allclose(probability.sum(axis=1), 1.0)
print("shape:", probability.shape)
print("class_order:", np.unique(y).tolist())
print("positive_probability_count:", len(probability[:, 1]))代码与数学原理
减去训练均值并除以训练标准差,对应代码中的 mean/std 或 StandardScaler。
预期输出或运行结果
本地 scikit-learn 1.8.0 的核对输出: shape: (100, 2) class_order: [0, 1] positive_probability_count: 100
常见错误 · 5 条
- 不要在测试集上调用 fit 或 fit_transform;测试集只能复用训练参数。
- 把拼接预测称为同一个最终模型的预测,或直接当成独立最终测试。
- 使用重复划分或不覆盖所有行的时间划分,却忽略每行必须恰好验证一次的要求。
- 不核对类别列顺序,或在同一组折外标签上选阈值并报告最优分数。
- 确认样本轴、特征轴以及 X 与 y 的第一维完全对应。
实际应用
- 诊断概率
- 堆叠训练特征
常见错误
- 把拼接预测称为同一个最终模型的预测,或直接当成独立最终测试。
- 使用重复划分或不覆盖所有行的时间划分,却忽略每行必须恰好验证一次的要求。
- 不核对类别列顺序,或在同一组折外标签上选阈值并报告最优分数。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。