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
相关产品推荐
相关产品推荐

