为什么我的交叉验证分数仅为 0

数据挖掘 分类 监督学习
2022-02-25 12:14:32

我正在尝试使用带有以下代码的 iris 数据集的Catboost包:

from sklearn.datasets import load_iris  
iris = load_iris()
from catboost import CatBoostClassifier
model = CatBoostClassifier(iterations=50, 
                      learning_rate=0.1, depth=4, 
                      loss_function='MultiClass')
from sklearn.model_selection import cross_val_score
scores = cross_val_score(model, iris.data, iris.target)
print(scores)

输出是:

[0. 0. 0.]

为什么分数只有0?我预计它们会接近 1。我尝试调整参数,但结果仍然相同。这些是错误而不是分类准确度吗?感谢您的洞察力。


编辑:似乎 with CatBoostClassifier,cross_val_score()使用KFold()而不是StratifiedKFold(), 因为添加功能解决了这个问题cv=StratifiedKFold()cross_val_score

使用 sklearn 的分类器,例如LogisticRegressionor SVC,默认cross_val_score使用StratifiedKFold见这里)。

1个回答

我认为问题可能在于,cross_val_score()在参数cv的默认选项中,文档说:

cv : int,交叉验证生成器或可迭代的,可选确定交叉验证拆分策略。cv 的可能输入是:

无,使用默认的 3 折交叉验证,整数,指定(分层)KFold 中的折叠数,用作交叉验证生成器的对象。一个可迭代的产量火车,测试拆分。对于整数/无输入,如果估计器是分类器并且 y 是二元或多类,则使用 StratifiedKFold。在所有其他情况下,使用 KFold。

所以我的猜测是,如果cv未指定,则拆分是在没有分层的情况下完成的。再加上默认情况下,在 iris 数据集中,目标是完全排序的(50 个标签 0,然后是 50 个标签 1,然后是 50 个标签 2),这意味着在每 3 k 折中,您将使用两个类进行训练并预测第三个,这就是为什么分数是 0。

两种解决方案:

A)洗牌数据:

from sklearn.datasets import load_iris  
import pandas as pd
iris = load_iris()
from catboost import CatBoostClassifier
model = CatBoostClassifier(iterations=50, 
                      learning_rate=0.1, depth=4, 
                      loss_function='MultiClass')
from sklearn.model_selection import cross_val_score
df = pd.DataFrame({'X0':iris.data[:,0],'X1':iris.data[:,1], 'X2':iris.data[:,2],'X3':iris.data[:,3],'Y':iris.target})
df = df.sample(frac=1).reset_index(drop=True)
scores = cross_val_score(model, df[['X0', 'X1', 'X2', 'X3']], df['Y'])
print(scores)

出去:

[0.96 0.94 0.94]

B)修改cv参数:

from sklearn.datasets import load_iris  
iris = load_iris()
from catboost import CatBoostClassifier
model = CatBoostClassifier(iterations=50, 
                      learning_rate=0.1, depth=4, 
                      loss_function='MultiClass')
from sklearn.model_selection import cross_val_score

scores = cross_val_score(model, iris.data, iris.target, cv = 4)
print(scores)

出去:

[1.         0.92105263 0.91891892 0.78378378]