使用 cross_val_score 和 StackingClassifier 或投票分类器获取“nan”
Posted
技术标签:
【中文标题】使用 cross_val_score 和 StackingClassifier 或投票分类器获取“nan”【英文标题】:Getting "nan" with cross_val_score and StackingClassifier or Voting Classifier 【发布时间】:2021-03-09 06:49:18 【问题描述】:我想将 StackingClassifier 和 VotingClassifier 与 StratifiedKFold 和 cross_val_score 一起使用。如果我使用 StackingClassifier 或 VotingClassifier,我会在 cross_val_score 中获得 nan 值。如果我使用任何其他算法而不是 StackingClassifier 或 VotingClassifier,cross_val_score 可以正常工作。 我正在使用 python 3.8.5 和 sklearn 0.23.2。
将代码更新为工作示例。请使用来自 kaggle Parkinsons Dataset 的 Parkinons 数据集这是我一直在研究的数据集,下面是我遵循的确切步骤。
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn import preprocessing
from sklearn import metrics
from sklearn import model_selection
from sklearn import feature_selection
from imblearn.over_sampling import SMOTE
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import StackingClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import RandomForestClassifier
import warnings
warnings.filterwarnings('ignore')
dataset = pd.read_csv('parkinsons.csv')
FS_X=dataset.iloc[:,:-1]
FS_y=dataset.iloc[:,-1:]
FS_X.drop(['name'],axis=1,inplace=True)
select_k_best = feature_selection.SelectKBest(score_func=feature_selection.f_classif,k=15)
X_k_best = select_k_best.fit_transform(FS_X,FS_y)
supportList = select_k_best.get_support().tolist()
p_valuesList = select_k_best.pvalues_.tolist()
toDrop=[]
for i in np.arange(len(FS_X.columns)):
bool = supportList[i]
if(bool == False):
toDrop.append(FS_X.columns[i])
FS_X.drop(toDrop,axis=1,inplace=True)
smote = SMOTE(random_state=7)
Balanced_X,Balanced_y = smote.fit_sample(FS_X,FS_y)
before = pd.merge(FS_X,FS_y,right_index=True, left_index=True)
after = pd.merge(Balanced_X,Balanced_y,right_index=True, left_index=True)
b=before['status'].value_counts()
a=after['status'].value_counts()
print('Before')
print(b)
print('After')
print(a)
SkFold = model_selection.StratifiedKFold(n_splits=10, random_state=7, shuffle=False)
estimators_list = list()
KNN = KNeighborsClassifier()
RF = RandomForestClassifier(criterion='entropy',random_state = 1)
DT = DecisionTreeClassifier(criterion='entropy',random_state = 1)
GNB = GaussianNB()
LR = LogisticRegression(random_state = 1)
estimators_list.append(LR)
estimators_list.append(RF)
estimators_list.append(DT)
estimators_list.append(GNB)
SCLF = StackingClassifier(estimators = estimators_list,final_estimator = KNN,stack_method = 'predict_proba',cv=SkFold,n_jobs = -1)
VCLF = VotingClassifier(estimators = estimators_list,voting = 'soft',n_jobs = -1)
scores1 = model_selection.cross_val_score(estimator = SCLF,X=Balanced_X.values,y=Balanced_y.values,scoring='accuracy',cv=SkFold)
print('StackingClassifier Scores',scores1)
scores2 = model_selection.cross_val_score(estimator = VCLF,X=Balanced_X.values,y=Balanced_y.values,scoring='accuracy',cv=SkFold)
print('VotingClassifier Scores',scores2)
scores3 = model_selection.cross_val_score(estimator = DT,X=Balanced_X.values,y=Balanced_y.values,scoring='accuracy',cv=SkFold)
print('DecisionTreeClassifier Scores',scores3)
输出
Before
1 147
0 48
Name: status, dtype: int64
After
1 147
0 147
Name: status, dtype: int64
StackingClassifier Scores [nan nan nan nan nan nan nan nan nan nan]
VotingClassifier Scores [nan nan nan nan nan nan nan nan nan nan]
DecisionTreeClassifier Scores [0.86666667 0.9 0.93333333 0.86666667 0.96551724 0.82758621
0.75862069 0.86206897 0.86206897 0.93103448]
我查看了 *** 上的其他一些相关帖子,但无法解决我的问题。我无法理解我哪里出错了。
【问题讨论】:
你能做一个最小的工作示例吗?检查this *** help page 以获取信息。关于数据集,sklearn
中也有很多开放数据集,您可以使用它们来演示您的问题。
@flyingdutchman 更新了最小的工作示例。
如果我下载你的示例数据,我会得到一个文件parkinsons.data
,我将其重命名为parkinsons.csv
。然后我运行您的代码并收到以下错误:ValueError: Unknown label type: 'continuous'
。该错误是由以下行引起的:File "code.py", line 47 Balanced_X,Balanced_y = smote.fit_sample(FS_X,FS_y)
你是如何得到你的输出的?您是否事先修改了帕金森数据?我认为你可以改进你的例子。它还不是最小的。尝试举一个例子,其中删除一行或变量将导致您的问题不会发生。
抱歉。我忘记了我已将状态列(这是目标功能)移动到 parkinsons.csv 的最右边。问题是文件不能直接在这里上传。不管怎样,我把 Parkinsons.csv 上传到我的 Google Drive
这里是Jupyter notebook
【参考方案1】:
传递给StackingClassifier
或VotingClassifier
的estimators_list
不正确。 documentation on sklearn for StackingClassifier 说:
将堆叠在一起的基础估算器。列表的每个元素都定义为字符串元组(即名称)和估计器实例。可以使用 set_params 将估算器设置为“drop”。
所以正确的列表如下所示:
KNN = KNeighborsClassifier()
DT = DecisionTreeClassifier(criterion="entropy")
GNB = GaussianNB()
estimators_list = [("KNN", KNN), ("DT", DT), ("GNB", GNB)]
您的帕金森数据的完整最小工作示例可能如下所示:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import StackingClassifier
dataset = pd.read_csv("parkinsons.csv")
FS_X = dataset.drop(["name", "status"], axis=1)
FS_y = dataset["status"]
estimators_list = [("KNN", KNeighborsClassifier()), ("DT", DecisionTreeClassifier(criterion="entropy")), ("GNB", GaussianNB())]
SCLF = StackingClassifier(estimators=estimators_list)
X_train, X_test, y_train, y_test = train_test_split(FS_X, FS_y)
SCLF.fit(X_train, y_train)
print("SCLF: ", accuracy_score(y_test, SCLF.predict(X_test)))
【讨论】:
@flyingducthman,感谢您的评论。我前段时间在 Scikit-Learn 上得到了答案。以上是关于使用 cross_val_score 和 StackingClassifier 或投票分类器获取“nan”的主要内容,如果未能解决你的问题,请参考以下文章
使用带有管道和 GridSearch 的 cross_val_score 进行嵌套交叉验证