Sklearn StratifiedKFold交叉验证类样本不足告警及模型拟合失败问题咨询
问题原因
- 任务类型匹配错误:股价预测是典型的回归任务(预测连续的数值结果),但你当前全部使用分类模型训练,直接把连续的股价数值作为分类标签。你的数据集里每个股价数值几乎都是唯一的,每个标签对应只有1条样本,就是告警中提到的「y中样本量最少的类仅有1个成员」的含义。
- 交叉验证方法选择错误:StratifiedKFold是专门为分类任务设计的分层抽样交叉验证,需要保证每个拆分的折里各类别的样本占比和原始数据集一致,你每个类别只有1个样本,根本无法拆分到2个折中,因此触发警告。
- LDA拟合失败原因:线性判别分析(LDA)分类要求每个类别至少有2个样本计算类内散度,你当前数据集样本数远小于类别数,满足不了算法的基本输入要求,因此拟合失败返回nan。
另外你的代码还有一个逻辑错误:当前构造的X和y都是当日股价数值,相当于用股价预测股价,模型无法学习到有效规律,输出结果没有实际意义。
解决方案
方案一:调整为回归任务(更适配股价预测场景,推荐)
- 替换所有分类模型为回归模型,对应导入回归类的算法:
# 导入回归相关模块 from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.svm import SVR from sklearn.model_selection import KFold
- 替换模型列表为回归模型:
models = [] models.append(('LR', LinearRegression())) models.append(('KNN', KNeighborsRegressor())) models.append(('CART', DecisionTreeRegressor())) models.append(('NB', GaussianNB())) models.append(('SVM', SVR()))
- 交叉验证替换为普通KFold,评估指标换成回归类指标:
for name, model in models: kfold = KFold(n_splits=2, random_state=1, shuffle=True) # 回归任务用负均方误差、R2等作为评估指标,不要用准确率 cv_results = cross_val_score(model, X_train, Y_train, cv=kfold, scoring='neg_mean_squared_error') results.append(cv_results) names.append(name) print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
- 补充时序特征:建议用前N天的股价、成交量等数据作为特征,预测下一日的股价,避免用当日数据预测当日数据的逻辑问题。
方案二:坚持做分类任务的调整方法
- 先对连续的股价做分箱处理,转换为离散分类标签:比如按涨跌分为「涨」「跌」两类,或者按价格区间分为低、中、高三类,保证每个分类标签对应的样本数至少大于你设置的
n_splits数值。 - 调整
StratifiedKFold的n_splits参数,确保其小于数据集中最少样本类别的样本数量,比如最小类有3个样本,n_splits最多设置为2。
内容的提问来源于stack exchange,提问作者Drew Olson
相关产品推荐
相关产品推荐

