StratifiedKFold必须同时传入X和y,因split()需依据y的类别分布分层划分;y须为1D数组且类别数不少于n_splits,否则会报错或导致某折缺失类别。

StratifiedKFold 能在保持各类别比例的前提下做交叉验证,但直接套用 StratifiedKFold 时容易忽略标签类型、数据对齐或 shuffle 随机性控制——这会导致结果不可复现或验证集分布异常。
为什么不能直接用 StratifiedKFold.split(X)?
它不接受单个参数;必须同时传入特征 X 和标签 y,否则会报 TypeError: split() missing 1 required positional argument: 'y'。且 y 必须是 1D 数组(不能是 DataFrame 的一列未.squeeze(),也不能是多维分类编码后的 one-hot)。
-
y中的类别数不能少于折数(例如 2 分类数据用n_splits=5是合法的,但若某折里某类样本数 - 如果
y是字符串标签(如['cat', 'dog', 'cat']),StratifiedKFold可以处理,无需提前编码 - 但若
y含 NaN,会直接抛ValueError: y cannot contain NaN
如何正确生成训练/验证索引并避免数据泄露?
关键在于:只用索引切分,不直接切分原始数据对象(尤其是当 X 和 y 类型不一致时,比如 X 是 pd.DataFrame,y 是 np.ndarray)。
- 用
sklearn.model_selection.StratifiedKFold实例的.split(X, y)方法获取train_idx,val_idx - 再统一用
X.iloc[train_idx]和y[train_idx](注意:DataFrame 用.iloc,numpy/pd.Series 可直接索引) - 不要写
X[train_idx]—— 若X是 DataFrame,这会触发标签索引而非位置索引,出错或静默错位
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for train_idx, val_idx in skf.split(X, y):
X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
y_train, y_val = y.iloc[train_idx], y.iloc[val_idx] # y 是 Series 时也用 .iloc
shuffle=True 和 random_state 不设会怎样?
默认 shuffle=False,意味着数据按原始顺序划分——如果 y 是按类别排好序的(如前100行全是 0,后100行全是 1),每一折都会严重失衡,StratifiedKFold 的“分层”就失效了。
立即学习“Python免费学习笔记(深入)”;
- 必须显式设
shuffle=True才能保证每折内各类比例接近全局比例 -
random_state不设 → 每次运行折划分都不同 → 实验无法复现;设了才能固定划分顺序 - 即使设了
random_state,若shuffle=False,random_state也不起作用
最常被忽略的是:在调用 .split() 前没检查 y 是否含缺失值或是否为合法 1D 结构——一旦报错,信息不直观,容易误以为是 StratifiedKFold 本身的问题,其实只是输入没清理干净。


















