使用scikit-learn learning_curve时单类别错误的成因排查咨询
解决ValueError: The number of classes has to be greater than one; got 1的问题
嘿,这个问题我之前也碰到过!虽然你确认标签包含R和N两类,但错误的根源其实出在交叉验证的子集划分上——某个交叉验证fold的训练子集(或者验证集)里只抽到了单一类别。
为什么会出现这种矛盾的情况?
learning_curve针对分类任务默认用StratifiedKFold来划分交叉验证集,它会尽量让每个fold的类别比例和整体数据一致,但你指定了很小的训练样本量(train_sizes=[50,80,110]),如果你的数据本身类别不平衡,或者随机抽样时运气不好,就会出现某一个fold的小训练子集里只有一类标签的情况。比如假设你的R占比90%,抽50个样本时,完全有可能某一次全抽到R,这时候SVM就没法做分类训练了,直接抛出这个错误。
怎么验证这个猜想?
你可以手动跑一段代码,检查每个交叉验证fold里小训练子集的标签分布:
from sklearn.model_selection import StratifiedKFold import numpy as np skf = StratifiedKFold(n_splits=5) for fold_idx, (train_idx, test_idx) in enumerate(skf.split(X, y), 1): train_y = y[train_idx] print(f"第{fold_idx}个fold的训练集类别:{set(train_y)}") # 检查不同训练样本量下的类别情况 for size in [50, 80, 110]: subset_y = train_y[:size] print(f" 取前{size}个样本的类别:{set(subset_y)},样本数:{len(subset_y)}")
如果输出里出现某一行的类别只有一种,那就实锤了问题所在。
可行的解决方案
- 调大训练样本量:把
train_sizes里的50换成更大的数值,比如100,确保小样本子集也能覆盖两类标签。 - 开启分层抽样+打乱:给
learning_curve加上shuffle=True和stratify=y参数,强制抽样时保持类别比例:
train_sizes, train_scores, valid_scores = learning_curve( SVC(kernel='linear'), X, y, train_sizes=[50, 80, 110], cv=5, shuffle=True, random_state=42, # 固定随机种子,结果可复现 stratify=y )
- 先做数据平衡:如果你的数据类别不平衡特别严重(比如一类占比95%以上),可以先用过采样(SMOTE)或欠采样平衡数据,再跑学习曲线。
内容的提问来源于stack exchange,提问作者SFC
相关产品推荐
相关产品推荐

