使用 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】:

传递给StackingClassifierVotingClassifierestimators_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”的主要内容,如果未能解决你的问题,请参考以下文章

使用 cross_val_score 评估多项式回归

使用 Cross_Val_score 的原因

使用Cross_Val_score的原因

使用带有管道和 GridSearch 的 cross_val_score 进行嵌套交叉验证

手动和 cross_val_score 预测的 Python 不同结果

cross_val_score 和 gridsearchCV 是如何工作的?