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

在SMOTE过采样数据上运行随机森林交叉验证与ROC曲线时遇TypeError:'KFold'对象不可迭代

解决KFold对象不可迭代的错误:SMOTE后随机森林交叉验证+ROC曲线绘制

嘿,我来帮你搞定这个问题!你遇到的TypeError: 'KFold' object is not iterable是因为使用KFold的方式不对,我给你拆解一下问题根源和修复方案:

问题核心原因

  • KFold实例本身不可直接迭代:你现在直接遍历kf这个KFold对象是不行的,必须调用split()方法传入你的特征数据,才能生成每一轮交叉验证的训练/测试索引对。
  • 过时的KFold导入路径:sklearn.cross_validation是scikit-learn 0.18版本之前的旧模块,现在已经被整合到sklearn.model_selection里了,导入旧模块不仅没用,还可能引发兼容性问题。
  • 遗漏必要的导入:你的代码里用了RandomForestClassifier和train_test_split,但没导入这些类,运行时也会报错,得补上。

修正后的完整代码

我把所有问题都修复了,还加了一些优化细节,注释里标了关键修改点:

# 补上所有必要的导入
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import KFold, train_test_split  # 合并正确的导入路径
from sklearn.ensemble import RandomForestClassifier  # 新增随机森林类的导入
from sklearn.metrics import roc_curve
from imblearn.over_sampling import SMOTE  # 别忘了SMOTE的导入!

# 假设你的df数据集已经提前加载完成
y = df.school.values
X = df.drop(['school'], axis=1)

# SMOTE过采样处理
oversample = SMOTE()
over_X, over_y = oversample.fit_resample(X, y)

# 初始化KFold,建议加上shuffle和random_state保证结果可复现
kf = KFold(n_splits=10, shuffle=True, random_state=23)

# ROC曲线绘制准备工作
tprs = []
base_fpr = np.linspace(0, 1, 101)
plt.figure(figsize=(5, 5))
ax = plt.gca()
ax.set_aspect('equal', 'datalim')

# 关键修改:用kf.split(over_X)生成可迭代的索引对
for i, (train_idx, test_idx) in enumerate(kf.split(over_X)):
    model = RandomForestClassifier(n_estimators=200, random_state=23)
    # 注意:如果over_X是DataFrame,要用.iloc按位置取行;如果是numpy数组直接用索引即可
    model.fit(over_X.iloc[train_idx], over_y[train_idx])
    y_score = model.predict_proba(over_X.iloc[test_idx])
    fpr, tpr, _ = roc_curve(over_y[test_idx], y_score[:, 1])
    
    plt.plot(fpr, tpr, 'b', alpha=0.15)
    interp_tpr = np.interp(base_fpr, fpr, tpr)
    interp_tpr[0] = 0.0
    tprs.append(interp_tpr)

tprs = np.array(tprs)
mean_tprs = tprs.mean(axis=0)
std = tprs.std(axis=0)
# 修正:避免TPR低于0
tprs_upper = np.minimum(mean_tprs + std, 1)
tprs_lower = np.maximum(mean_tprs - std, 0)

plt.plot(base_fpr, mean_tprs, 'b', label='Mean ROC')
plt.fill_between(base_fpr, tprs_lower, tprs_upper, color='grey', alpha=0.3)
plt.plot([0, 1], [0, 1], 'r--', label='Random Guess')
plt.xlim([-0.01, 1.01])
plt.ylim([-0.01, 1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.legend()
plt.show()

额外说明

  • DataFrame索引取值:如果over_X是Pandas DataFrame,直接用over_X[train_idx]会报错(因为原始数据的索引可能不是连续整数),所以必须用.iloc[train_idx]按位置取行;如果是numpy数组,直接用索引即可。
  • 交叉验证逻辑选择:你之前先做了train_test_split,但后面交叉验证用的是全量过采样数据。如果你的目标是:
    1. 先拆分训练/测试集,在训练集上做交叉验证调参,最后用测试集评估:那应该把kf.split(X_train),并且最终用测试集绘制ROC曲线。
    2. 直接在全量过采样数据上做10折交叉验证评估模型稳定性:那当前代码逻辑是正确的。
  • shuffle参数的重要性:KFold默认不打乱数据,加上shuffle=True和random_state可以让每折的样本分布更均匀,同时保证实验结果可复现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:17:45