You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

连续值目标做分层5折交叉验证报单样本类别过少,该如何实现?

错误原因

你触发报错是因为sklearn的分层逻辑默认将每个不同的y取值视为独立类别,要求每个类别至少有2个样本才能完成拆分,而你的y是连续型变量,存在大量仅出现1次的取值,因此直接传stratify=y会触发报错。

方案1:合并低频次bin(推荐,适配原生sklearn分层交叉验证)

该方案可以满足你合并小样本bin的需求,不需要依赖第三方包,逻辑可控:

import pandas as pd
import numpy as np
from sklearn.model_selection import StratifiedKFold

# 步骤1:统计y各取值的出现频次
y_series = pd.Series(y)
value_counts = y_series.value_counts()

# 步骤2:合并小样本取值,5折交叉验证要求每个分层组至少有5个样本
# 对y的唯一值排序后做相邻合并
unique_y = np.sort(value_counts.index)
y_map = {}
current_group = None
current_group_cnt = 0
for val in unique_y:
    cnt = value_counts[val]
    if current_group is None:
        current_group = val
        current_group_cnt = cnt
    else:
        if current_group_cnt < 5:
            # 当前组样本数不足5,合并当前值到该组
            y_map[val] = current_group
            current_group_cnt += cnt
        else:
            current_group = val
            current_group_cnt = cnt
    y_map[val] = current_group
# 生成分层专用的标签
stratify_y = y_series.map(y_map).values

# 直接使用原生StratifiedKFold实现5折分层交叉验证
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for train_idx, val_idx in skf.split(x, stratify_y):
    x_train, x_val = x[train_idx], x[val_idx]
    y_train, y_val = y[train_idx], y[val_idx]
    # 此处写入你的模型训练、验证逻辑

如果不需要严格按取值合并,也可以用更简单的等频分箱生成分层标签:

# q为分箱数量,可根据总样本量调整,确保每个箱样本数≥5即可
stratify_y = pd.qcut(y, q=20, labels=False, duplicates='drop')

方案2:基于verstack的scsplit实现5折交叉验证

verstack的scsplit原生支持连续值分层拆分,不需要提前合并小样本bin,通过循环拆分即可实现5折验证:

from verstack import scsplit
import numpy as np

# 生成全量样本索引
all_idx = np.arange(len(x))
remaining_idx = all_idx.copy()
folds = []

for i in range(5):
    if i == 4:
        # 最后一折直接取剩余所有样本
        folds.append(remaining_idx)
        break
    # 每次从剩余样本中拆分1/(剩余折数)作为验证集
    test_size = 1/(5 - i)
    _, val_idx, _, _ = scsplit(remaining_idx, y[remaining_idx],
                              stratify=y[remaining_idx],
                              test_size=test_size,
                              random_state=42)
    folds.append(val_idx)
    remaining_idx = np.setdiff1d(remaining_idx, val_idx)

# 遍历5折训练
for val_idx in folds:
    train_idx = np.setdiff1d(all_idx, val_idx)
    x_train, x_val = x[train_idx], x[val_idx]
    y_train, y_val = y[train_idx], y[val_idx]
    # 此处写入你的模型训练、验证逻辑

内容的提问来源于stack exchange,提问作者Mona Jalal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:57:03