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

RFECV对象无grid_scores_属性及替换cv_results_后报错求助

解决RFECV中grid_scores_属性不存在及cv_results_绘图报错问题

问题详情

使用sklearn进行特征选择时,运行RFECV相关代码触发AttributeError: 'RFECV' object has no attribute 'grid_scores_';按照建议替换为cv_results_后,又出现TypeError: unhashable type: 'dict'。

原代码

from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold
import warnings
warnings.filterwarnings('ignore')

rfc = RandomForestClassifier(random_state=101)
rfecv = RFECV(estimator=rfc, step=1, cv=StratifiedKFold(5), scoring='accuracy')
rfecv.fit(X_train, y_train)

print('Optimal number of features: {}'.format(rfecv.n_features_))

plt.figure(figsize=(16, 9))
plt.title('Recursive Feature Elimination with Cross-Validation', fontsize=18, fontweight='bold', pad=20)
plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_, color='#303F9F', linewidth=3)
plt.show()

原报错信息

AttributeError                            Traceback (most recent call last)
Cell In[36], line 5
      3 plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
      4 plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
----> 5 plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_, color='#303F9F', linewidth=3)
      6 plt.show()

AttributeError: 'RFECV' object has no attribute 'grid_scores_'

替换grid_scores_为cv_results_后的代码及报错

替换后的绘图代码:

plt.figure(figsize=(16, 9))
plt.title('Recursive Feature Elimination with Cross-Validation', fontsize=18, fontweight='bold', pad=20)
plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
plt.plot(range(1, len(rfecv.cv_results_) + 1), rfecv.cv_results_, color='#303F9F', linewidth=3)
plt.show()

报错信息:

TypeError                                 Traceback (most recent call last)
Cell In[37], line 5
      3 plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
      4 plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
----> 5 plt.plot(range(1, len(rfecv.cv_results_) + 1), rfecv.cv_results_, color='#303F9F', linewidth=3)
      6 plt.show()

File ~\anaconda3\Lib\site-packages\matplotlib\pyplot.py:2812, in plot(scalex, scaley, data, *args, **kwargs)
   2810 @_copy_docstring_and_deprecators(Axes.plot)
   2811 def plot(*args, scalex=True, scaley=True, data=None, **kwargs):
-> 2812     return gca().plot(
   2813         *args, scalex=scalex, scaley=scaley,
   2814         **({"data": data} if data is not None else {}), **kwargs)

File ~\anaconda3\Lib\site-packages\matplotlib\axes\_axes.py:1688, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
   1445 """
   1446 Plot y versus x as lines and/or markers.
   1447 
   (...)
   1685 (``'green'``) or hex strings (``'#008000'``).
   1686 """
   1687 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-> 1688 lines = [*self._get_lines(*args, data=data, **kwargs)]
   1689 for line in lines:
   1690     self.add_line(line)

File ~\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:311, in _process_plot_var_args.__call__(self, data, *args, **kwargs)
    309     this += args[0],
    310     args = args[1:]
-> 311 yield from self._plot_args(
    312     this, kwargs, ambiguous_fmt_datakey=ambiguous_fmt_datakey)

File ~\anaconda3\Lib\site-packages\matplotlib\axes\_base.py:501, in _process_plot_var_args._plot_args(self, tup, kwargs, return_kwargs, ambiguous_fmt_datakey)
    499     self.axes.xaxis.update_units(x)
    500 if self.axes.yaxis is not None:
-> 501     self.axes.yaxis.update_units(y)
    503 if x.shape[0] != y.shape[0]:
    504     raise ValueError(f"x and y must have same first dimension, but "
    505                      f"have shapes {x.shape} and {y.shape}")

File ~\anaconda3\Lib\site-packages\matplotlib\axis.py:1675, in Axis.update_units(self, data)
   1673 neednew = self.converter != converter
   1674 self.converter = converter
-> 1675 default = self.converter.default_units(data, self)
   1676 if default is not None and self.units is None:
   1677     self.set_units(default)

File ~\anaconda3\Lib\site-packages\matplotlib\category.py:105, in StrCategoryConverter.default_units(data, axis)
    103 # the conversion call stack is default_units -> axis_info -> convert
    104 if axis.units is None:
-> 105     axis.set_units(UnitData(data))
    106 else:
    107     axis.units.update(data)

File ~\anaconda3\Lib\site-packages\matplotlib\category.py:181, in UnitData.__init__(self, data)
    179 self._counter = itertools.count()
    180 if data is not None:
-> 181     self.update(data)

File ~\anaconda3\Lib\site-packages\matplotlib\category.py:214, in UnitData.update(self, data)
    212 # check if convertible to number:
    213 convertible = True
-> 214 for val in OrderedDict.fromkeys(data):
    215     # OrderedDict just iterates over unique values in data.
    216     _api.check_isinstance((str, bytes), value=val)
    217     if convertible:
    218         # this will only be called so long as convertible is True.

TypeError: unhashable type: 'dict'

解决方案

问题根源

sklearn版本迭代后,RFECV的grid_scores_属性被移除,替代的cv_results_是一个字典,包含了交叉验证的所有结果数据,不能直接传入plt.plot(),需要提取其中的平均测试分数字段。

修改后的绘图代码

将绘图部分的rfecv.grid_scores_替换为rfecv.cv_results_['mean_test_score'],这是对应原grid_scores_的平均交叉验证准确率数据:

plt.figure(figsize=(16, 9))
plt.title('Recursive Feature Elimination with Cross-Validation', fontsize=18, fontweight='bold', pad=20)
plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
# 提取平均测试分数进行绘图
plt.plot(range(1, len(rfecv.cv_results_['mean_test_score']) + 1), 
         rfecv.cv_results_['mean_test_score'], 
         color='#303F9F', linewidth=3)
plt.show()

完整可运行代码

from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

rfc = RandomForestClassifier(random_state=101)
rfecv = RFECV(estimator=rfc, step=1, cv=StratifiedKFold(5), scoring='accuracy')
rfecv.fit(X_train, y_train)

print('Optimal number of features: {}'.format(rfecv.n_features_))

plt.figure(figsize=(16, 9))
plt.title('Recursive Feature Elimination with Cross-Validation', fontsize=18, fontweight='bold', pad=20)
plt.xlabel('Number of features selected', fontsize=14, labelpad=20)
plt.ylabel('% Correct Classification', fontsize=14, labelpad=20)
plt.plot(range(1, len(rfecv.cv_results_['mean_test_score']) + 1), 
         rfecv.cv_results_['mean_test_score'], 
         color='#303F9F', linewidth=3)
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:37:04