为什么GridSearchCV模型结果与我手动调整的模型不同?

时间:2019-12-15 17:39:38

标签: python machine-learning scikit-learn data-analysis grid-search

这是我在这里的第一个问题,希望我做对了,

我正在研究在kaggle上很受欢迎的钛酸数据集,如果您想检查A Data Science Framework: To Achieve 99% Accuracy

第5.2部分介绍了如何进行网格搜索和调整超参数。让我在对问题特别了解之前与您分享相关代码;

这正在使用GridSearchCV调整模型:

cv_split = model_selection.ShuffleSplit(n_splits = 10, test_size = .3, train_size = .6, random_state = 0)
#cv_split = model_selection.KFold(n_splits=10, shuffle=False, random_state=None)

param_grid = {'criterion': ['gini', 'entropy'],
'splitter': ['best', 'random'], #splitting methodology; two supported strategies - default is best
'max_depth': [2,4,6,8,10,None], #max depth tree can grow; default is none
'min_samples_split': [2,5,10,.03,.05], #minimum subset size BEFORE new split (fraction is % of total); default is 2
'min_samples_leaf': [1,5,10,.03,.05], #minimum subset size AFTER new split split (fraction is % of total); default is 1
'max_features': [None, 'auto'], #max features to consider when performing split; default none or all
'random_state': [0] }

tune_model = model_selection.GridSearchCV(tree.DecisionTreeClassifier(), param_grid=param_grid, scoring = 'roc_auc', return_train_score = True ,cv = cv_split)
tune_model.fit(data1[data1_x_bin], data1[Target])`

    tune_model.best_params_

result is: 

    {'criterion': 'gini',
     'max_depth': 4,
     'max_features': None,
     'min_samples_leaf': 5,
     'min_samples_split': 2,
     'random_state': 0,
     'splitter': 'best'}

并根据代码,培训和测试的准确性调整以下内容:

print(tune_model.cv_results_['mean_train_score'][tune_model.best_index_], tune_model.cv_results_['mean_test_score'][tune_model.best_index_])

此输出:0.8924916598172832 0.8767742588186237

出于好奇,我想使用从GridSearchCV获得的参数制作自己的DecisionTreeClassifier(),

dtree = tree.DecisionTreeClassifier(criterion = 'gini',max_depth = 4,max_features= None, min_samples_leaf= 5, min_samples_split= 2,random_state = 0,  splitter ='best')

results = model_selection.cross_validate(dtree, data1[data1_x_bin],  data1[Target],return_train_score = True, cv  = cv_split)

相同的超参数,相同的交叉验证数据框,不同的结果。为什么?

print(results['train_score'].mean(), results['test_score'].mean())

0.8387640449438202 0.8227611940298509

那是tune_model结果:

0.8924916598172832 0.8767742588186237

差异甚至不小。如果您问我,两个结果应该相同

我不知道有什么不同?有什么不同,所以结果也不同?

我尝试用k折叠而不是随机拆分进行交叉验证,

在两种情况下,我尝试使用不同的random_state值,也尝试过random_state = None,

结果仍然不同。

有人可以解释一下区别吗?

编辑:顺便说一句,我还想检查测试样本结果:

dtree.fit(data1[data1_x_bin],data1[Target])
dtree.score(test1_x_bin,test1_y), tune_model.score(test1_x_bin,test1_y)

输出:(0.8295964125560538, 0.9033059266872216)

相同的模型(决策树分类器),相同的超参数,结果截然不同

(显然它们不是相同的模型,但我不知道如何以及为什么)

2 个答案:

答案 0 :(得分:3)

更新

默认情况下,cross_validate使用estimators评分方法作为评估其性能的默认方法(您可以通过指定scoring的{​​{1}} kw参数来更改其性能)。 cross validate类的评分方法使用准确性作为其评分指标。在GridSearchCV DecisionTreeClassifier中用作得分指标。在两种情况下使用相同的分数度量会得出相同的分数。例如。如果roc_auc的得分指标更改为cross_validate,则您在模型之间观察到的得分差异将消失。

roc_auc

关于得分指标:

得分度量的选择决定了如何评估模型的性能。

想象一个模型应该预测交通信号灯是否为绿色(交通信号灯为绿色-> 1,交通信号灯不是绿色-> 0)。该模型会产生两种类型的错误。它表示交通信号灯是绿色,尽管它不是绿色(假阳性),或者说交通信号灯不是绿色,尽管它是绿色(假阴性)。在这种情况下,假阴性会很丑陋,但其后果是可以忍受的(有人必须在交通信号灯处等待的时间比必要的时间长)。另一方面,误报将带来灾难性的后果(有人将交通灯通过红色,因为它被归类为绿色)。为了评估模型的性能,将选择分数度量,其权衡假阳性比假阴性更高(即,将它们归类为“更差”的错误)。 准确性在这里将是不合适的指标,因为假阴性和假阳性会将得分降低的程度相同。例如, precision 更适合作为得分指标。该度量标准权衡误报为1的误报和误报为0的误报(误报的数量对模型的精度没有影响)。要获得良好的概览,请参见here,以了解误报,误报,精度,召回率,准确性等内容。 F得分的beta参数(另一个得分指标)可用于设置与假阴性相比应如何对假阳性进行加权(有关更详细的解释,请参见here)。有关results = model_selection.cross_validate(dtree, data1[data1_x_bin], data1[Target], scoring = 'roc_auc' ... ) 得分的更多信息,请参见here(它是根据混淆矩阵的不同统计数据得出的。)

总而言之,这意味着相同的模型相对于一个得分指标可以表现得很好,而相对于另一个得分指标却表现不佳。在您描述的情况下,由GridSearchCV优化的决策树与之后实例化的树是相同的模型。两者都产生相同的准确性或相同的roc_auc分数。用于比较数据集上不同模型性能的评分标准取决于您认为对模型性能特别重要的标准。如果唯一的标准是正确分类了多少个实例,那么准确性可能是一个不错的选择。


旧主意(查看评论):

您为roc_aucdtree)指定了一个随机状态,但没有为GridSearchCV中使用的决策树指定随机状态。在那使用相同的随机状态,让我知道是否可以解决问题。

dtree = tree.DecisionTreeClassifier(random_state = 0 ...

答案 1 :(得分:0)

我是新来的,看来我不能在您的答案中评论超过15个字符,无论如何,让我在这里使用,

zwithouta,你是我的英雄!我不了解默认值/ kw评分,显然roc_auc的效果比默认值好,例如%5的精度更高。 (非常大)

也许我应该了解更多有关计分的知识,也许您能给我一个资料/建议吗?

对于其他读者,这是更改:

results = model_selection.cross_validate(dtree, data1[data1_x_bin],  data1[Target],return_train_score = True, cv  = cv_split ) 

results = model_selection.cross_validate(dtree, data1[data1_x_bin],  data1[Target],return_train_score = True, cv  = cv_split,scoring = 'roc_auc')