【机器学习】GridSearchCV(网格搜索+交叉验证)

1,170 阅读20分钟

参考网址

blog.csdn.net/zyh960/arti…

0/前言

在机器学习模型的训练中,需要人工确定的参数称为【超参数】。
比如随机森林中决策树的个数,人工神经网络模型中隐藏层层数和每层的节点个数,正则项中常数大小等等,他们都需要事先指定。

超参数选择不恰当,就会出现欠拟合或者过拟合的问题,模型的效果(性能)就不好。

而在选择超参数的时候,有两个途径:
  <1>一个是凭经验微调。
  <2>用不同的参数组合来训练模型,然后评估模型,最后确定一组效果最好的参数。

微调的一种方法是手工调制超参数,直到找到一个好的超参数组合,这么做的话会非常冗长,你也可能没有时间探索多种组合,所以可以使用Scikit-Learn的GridSearchCV来做这项搜索工作。

1/什么叫网格搜索(grid search)

Grid Search:一种调参手段;穷举搜索。

在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。
这种方法的主要缺点是比较耗时!

所以网格搜索适用于三四个(或者更少)的超参数。
当超参数的数量增长时,网格搜索的计算复杂度会呈现指数增长,这时候则使用随机搜索

用户列出一个较小的超参数值域,这些超参数至于的笛卡尔积(排列组合)为一组组超参数。

网格搜索算法使用【每组超参数】训练模型,并挑选在`验证集`上误差最小(效果最好)的超参数组合。

2/什么是交叉验证(cross val score)

cross 交叉,
val 验证,

cross_val_score是 scikit-learn 库中用于执行交叉验证并计算模型得分的函数。

它的主要思想是将数据集分成多个子集,然后在不同的子集组合上进行训练和验证,以获得对模型性能更可靠和稳定的评估。

例如,常见的交叉验证方法有 `K 折交叉验证(K-Fold Cross-Validation)` ,
假设 `K = 5` ,数据集就会被随机分成 5 份。
第一次,用其中 4 份进行训练train,用剩下的 1 份进行验证test;
第二次换 1 份进行验证,其余 4 份训练,以此类推,重复 5 次。

最后将这 5 次验证的结果综合起来评估模型的性能。

通过 `cross_val_score` ,可以方便地对不同的模型或者同一模型的不同参数设置进行比较和选择。

假设我们有一个线性回归模型,想要评估它在不同数据集划分下的性能,就可以使用 `cross_val_score` 来实现,从而更全面地了解模型的泛化能力。

3/什么是GridSearchCV(网格搜索+交叉验证)

GridSearchCV的名字其实可以拆分为两部分,
GridSearch和CV(cross validation),即网格搜索和交叉验证。
这两个名字都非常好理解。

网格搜索,搜索的是参数,即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在`验证集`上精度最高的参数,这其实是一个训练和比较的过程。

GridSearchCV可以保证在指定的参数范围内找到精度最高的参数,但是这也是网格搜索的缺陷所在,他要求遍历所有可能参数的组合,在面对大数据集和多参数的情况下,非常耗时。

4/gridsearchcv()函数的参数有哪些

GridSearchCV是scikit-learn(sklearn)库中的一个函数,
from sklearn.model_selection import GridSearchCV

用于系统地遍历多种参数组合,通过交叉验证确定最佳超参数的组合,从而得到效果最好的模型。
其主要参数包括:
  1. estimator

    • 类型:estimator object
    • 说明:这是需要调优的模型估计器(如分类器、回归器等)。该估计器必须有一个score方法,或者可以通过scoring参数指定一个评分标准。
  2. param_grid

    • 类型:dict or list of dictionaries
    • 说明:这是需要优化的参数的取值范围,以字典或字典列表的形式给出。字典的键是参数名(字符串),值是参数需要尝试的值(列表、范围等)。
  3. scoring

    • 类型:string, callable, list/tuple, dict or None, default: None
    • 说明:模型评价标准。如果为None,则使用估计器的默认评分标准。也可以指定为字符串(如'accuracy'、'roc_auc','precision', 'recall'等)或可调用对象,用于评估模型的性能。
  4. cv

    • 类型:int, cross-validation generator or an iterable, optional
    • 说明:交叉验证的分割策略。默认为None,即使用3折交叉验证。也可以指定一个整数来指定折叠数,或者使用交叉验证生成器。
  5. n_jobs

    • 类型:int or None, optional (default=None)
    • 说明:并行数。如果为-1,则使用所有可用的CPU核心。如果为1,则不使用并行计算。如果为None,则使用默认值(即1,除非在joblib.parallel_backend上下文中被更改)。
  6. verbose

    • 类型:integer
    • 说明:控制日志冗长度。值越大,输出的信息越多。默认为0,表示不输出训练过程。
    • verbose=2
  7. iid

    • 类型:bool, default=False
    • 注意:在较新版本的scikit-learn中,此参数已被弃用,并将在未来版本中移除。之前的版本中,如果为True,则假定每个样本的权重是相等的,并且损失是样本损失的简单平均。现在建议总是将此参数设置为False,因为默认情况下,损失是所有折叠损失的平均值。
  8. refit

    • 类型:boolean, string, or callable, default=True
    • 说明:在交叉验证完成后,是否使用最佳参数重新拟合整个数据集。默认为True。
  9. pre_dispatch

    • 类型:int, or string, optional
    • 说明:控制在并行执行期间调度的作业数。如果为整数,则它指定了总共分发的并行任务数。如果为字符串,则它可以是'2*n_jobs'的形式,表示预分派的任务数是n_jobs的两倍。
  10. error_score

    • 类型:'raise' (default) 或者 numeric
    • 说明:如果模型拟合中发生错误,则将此值赋给分数。如果设置为'raise',则会引发错误。
  11. return_train_score

    • 类型:bool, default=False
    • 说明:如果为True,则cv_results_字典中将包含训练分数。这可能会增加计算成本,因为需要为每个候选参数组合训练额外的模型。

4/gridsearchcv()的使用

下面代码,我们要通过网格搜索,来确定2个超参数的值,一个是n_estimators,一个是max_features。
决策树的个数, 树的最大深度。

GridSearch会挑选出最适合的超参数值。
from sklearn.model_selection import GridSearchCV

# 初始化一个模型,这里以随机森林的回归为例子
forest_reg = RandomForestRegressor() 

# 参数组合
param_grid_dict = { 'n_estimators': [3, 10, 30],
                    'max_features': [2, 4, 6, 8],
                    'bootstrap':[False], 
                    'n_estimators': [3, 10],
                    'max_features': [2, 3, 4]
              ]

grid_search = GridSearchCV(estimator=forest_reg, 
                           param_grid=param_grid_dict,
                           cv=5, 
                           scoring='neg_mean_squared_error',
                           verbose=2,  
                           n_jobs=-1   
                           ) 
# 训练模型
grid_search.fit(x, y)

print(grid_search.best_params_)  # 最好的超参数组合
print(grid_search.best_score_)   # 最好的得分
print(grid_search.best_estimator_) # 最好的模型

# 自定义回调函数,打印每一组超参数的结果
def print_results(  grid_search  ):  
    print("Best: %f using %s" % (grid_search.best_score_, grid_search.best_params_))  
      
    # 在【训练集】上的效果
    means = grid_search.cv_results_['mean_train_score'] 
    stds = grid_search.cv_results_['std_train_score']   
    
    # 在【测试集】上的效果
    means = grid_search.cv_results_['mean_test_score'] 
    stds = grid_search.cv_results_['std_test_score']   
    
    # 超参数组合
    params = grid_search.cv_results_['params']  
    
    for mean, stdev, param in zip(means, stds, params):  
        print("%f (%f) with: %r" % (mean, stdev, param))  

# 打印结果  
print_results(  grid_search  )

sklearn 根据param_grid的值,首先会评估3×4=12种n_estimators和max_features的组合方式,

接下来在会在bootstrap=False的情况下(默认该值为True),评估2×3=612种n_estimators和max_features的组合方式。

所以最终会有12+6=18种不同的超参数组合方式,而每一种组合方式要在训练集上训练5次,所以一共要训练18×5=90次,当训练结束后,你可以通过best_params_获得最好的组合方式。

如果GridSearchCV初始化时,refit=True(默认的初始化值),
在交叉验证时,一旦发现最好的模型(estimator),将会在整个训练集上重新训练,这通常是一个好主意,因为使用更多的数据集会提升模型的性能。

以上面有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历,搜索,所以叫grid search。 

网格搜索的评价指标

图片.png

GridSearchCV()函数的参数主要包括以下几类:

必需参数

-`estimator`: 这是要进行参数搜索的机器学习算法。它应该是一个scikit-learn模型。
-`param_grid`: 这是一个字典或者字典的列表,用于定义要搜索的参数以及他们的范围。每个字典代表一个模型参数组合,并将在整个数据集上评估。
-`cv`: 这是一个交叉验证策略。它应该是一个scikit-learn的`cv`实现,如`KFold``StratifiedKFold``ShuffleSplit`等。

可选参数

-`param_grid`: 可以是字典或者字典的列表,用于定义要搜索的参数及其范围。每个字典代表一个模型参数组合,并在整个数据集上评估。
-`scoring`: 这是一个字符串或调用函数,用于指定一个评价函数,该函数返回一个分数,以评估模型的性能。默认是`'accuracy'`。
-`n_jobs`: 这是进行模型训练的并行数量。默认是`-1`,表示使用所有可用的CPU。
-`pre_dispatch`: 这是在所有并行工作完成之前预先派发的样本数量。默认是`2 * (n_jobs + 1)`。
-`verbose`: 这是控制日志输出的级别。默认是`0`,表示没有输出。
-`error_score`: 这是当一个管道在训练或预测时遇到错误时返回的分数。默认是`raise`,表示抛出异常。
-`return_train_score`: 这是一个布尔值,决定是否在交叉验证迭代中返回训练分数。默认是`False`。

请注意,每个具体模型可能有其特定的参数,这些参数可以在`GridSearchCV()`中进一步调整。

GridSearchCV()和cross_val_score()的区别

<1>功能侧重点

-  `GridSearchCV` 主要用于超参数的搜索和选择。它会在给定的超参数范围内进行穷举搜索,并通过交叉验证来评估每个超参数组合的性能,最终返回最优的超参数组合以及对应的模型。
-  `cross_val_score` 主要用于评估模型在不同数据划分下的性能得分。它不进行超参数的搜索,而是直接在给定的超参数和模型下,通过交叉验证计算模型的得分,评估模型的好坏。

<2>输出结果

-  `GridSearchCV` 返回最优的超参数组合、对应的模型,以及在交叉验证中得到的最佳得分。
-  `cross_val_score` 返回的是一组模型在不同交叉验证折上的得分,是一个列表。

<3>灵活性

-   `GridSearchCV` 可以同时搜索多个超参数,并自动选择最优的组合。
-   `cross_val_score` 通常用于对已确定超参数的模型进行性能评估,相对来说灵活性稍弱于 `GridSearchCV` 在超参数搜索方面的表现。

图片.png

scoring参数的取值有什么

'accuracy':准确率,用于分类问题,计算预测值和真实值相同的样本数除以总样本数。
'precision':精确率,用于分类问题,在所有预测为正例的样本中,实际为正例的样本数量占比。 
'recall':召回率,用于分类问题,在所有实际为正例的样本中,预测为正例的样本数量占比。  
'f1':F1 分数,通过计算准确率和召回率的加权平均来衡量分类模型性能。
'roc_auc':ROC 曲线下的面积,用于分类问题,通过计算正例样本的真阳性率和负例样本的假阳性率来衡量分类模型性能。   
'neg_mean_squared_error':均方误差的负值,用于回归问题,均方误差计算的是预测值与真实值之间差异的平方的平均值,取负值是为了使优化目标变为最大化评分(因为通常希望误差越小越好)。

'r2':R2 分数,用于回归问题,表示模型对数据的拟合程度,取值范围为 011 表示模型完美拟合数据。

这些只是一些常见的取值,具体可用的取值还取决于所使用的模型和评估需求。
`scoring`参数也可以接受自定义的评分函数或可调用对象,
只要其函数签名符合`scorer(estimator, X, y)`的形式,
其中`estimator`是要评估的模型,`X`是特征数据,`y`是真实标签。

例如,对于随机森林分类器,如果你想根据准确率来选择最优参数,可以设置`scoring='accuracy'`;
如果你更关注精确率,可以设置`scoring='precision'`等。

另外,不同的机器学习任务(分类、回归等)和模型可能适用不同的评估指标,
你需要根据具体情况选择合适的`scoring`值来衡量模型的性能。
同时,还可以参考相应模型和评估指标的文档,以了解更多关于指标的计算方法和适用场景的详细信息。
    
    

什么是正样本

在随机森林模型以及大多数分类问题中,精确率的计算是针对被模型预测为正样本的情况。

关于正样本的定义,这通常是根据具体问题由您自己来确定的。
在很多情况下,如果将标签为 1 的样本定义为正样本,那么在计算精确率时,就是针对模型预测为 1 的样本进行计算。

但需要注意的是,正样本和负样本的标签设定完全取决于问题的背景和您的定义。
例如,在某些场景中,可能会将标签为 0 的样本定义为正样本。

举个例子,如果您正在构建一个模型来预测客户是否会购买某种产品,您可能会将购买(标签为 1)定义为正样本,未购买(标签为 0)定义为负样本。
此时,精确率就是在模型预测为购买(即预测标签为 1)的样本中,实际购买(真实标签为 1)的样本所占的比例。

在随机森林模型中,正样本的定义完全取决于您所处理的具体问题和业务需求。

以下是一些常见的定义正样本的方式和示例:

1. 二分类问题中的明确类别:

-   疾病诊断:患有某种疾病(标签为 1)为正样本,未患该疾病(标签为 0)为负样本。
-   信用评估:信用违约(标签为 1)为正样本,信用良好(标签为 0)为负样本。

1. 基于业务重要性:

-   营销活动响应:对营销活动做出积极响应(如购买产品、参与活动等,标签为 1)为正样本,未响应(标签为 0)为负样本。
-   客户流失预测:客户流失(标签为 1)为正样本,客户留存(标签为 0)为负样本。

1. 稀有事件:

-   欺诈检测:发生欺诈行为(标签为 1)为正样本,正常交易(标签为 0)为负样本。

1. 目标达成:

-   销售预测:达到或超过销售目标(标签为 1)为正样本,未达到销售目标(标签为 0)为负样本。


总之,正样本的定义应该与您希望模型重点关注和准确预测的情况相对应,并且在整个模型的构建、评估和应用过程中保持一致。
   

随机森林模型训练的时候,如何告诉模型,label取什么值的时候,是正样本

 在随机森林模型训练中,通常需要在数据预处理阶段明确指定正样本的标签值。
 
 具体的实现方式会依赖于你所使用的编程语言和机器学习库。
 一般来说,你需要确保训练数据集中的标签列明确标识了每个样本的类别。
 
例如,在 Python 中使用`scikit-learn`库时,假设你的数据集`X`包含特征,`y`包含对应的标签,那么`y`中的值就表示了样本的类别。
你可以根据问题的具体定义,将表示正样本的标签值设置为相应的数值或类别。

比如,如果正样本用`1`表示,负样本用`0`表示,那么在训练随机森林模型时,模型会根据`y`中这些标签值的分布来学习区分正样本和负样本的模式。

在实际应用中,正样本的定义完全取决于问题的背景和需求。
例如,在疾病诊断中,可能将患有某种疾病的样本标记为正样本(例如用`1`表示);
在信用评估中,可能将信用违约的样本标记为正样本(也用`1`表示)等等。

在训练模型之前,要确保数据集中的标签准确无误地反映了正样本和负样本的定义,这样模型才能学习到正确的模式并进行有效的预测。
同时,还可以根据数据的特点,如样本不平衡等情况,考虑使用一些技术,如调整样本权重等,来更好地训练模型。

mean_test_score是啥意思

mean_test_score在机器学习和数据科学领域,
特别是在使用交叉验证(Cross-Validation)进行模型评估时,是一个非常重要的概念。
它通常出现在使用诸如`GridSearchCV``RandomizedSearchCV`等Scikit-learn库中的交叉验证工具时。
以下是关于`mean_test_score`的详细解释:

定义

mean_test_score表示在交叉验证过程中,模型在测试集(或验证集)上的平均得分。这个得分是根据你指定的评分方法scoring参数(如准确率、召回率、F1分数、AUC等)计算得到的。通过交叉验证,数据集被分割成多个子集,模型在这些子集上依次进行训练和测试,最终得到的mean_test_score是模型在所有测试子集上得分的平均值。

作用

  1. 评估模型性能mean_test_score提供了一个综合的指标,用于评估模型在不同数据子集上的泛化能力。较高的mean_test_score通常意味着模型具有较好的泛化性能。
  2. 参数调优:在进行超参数调优时(如使用网格搜索),mean_test_score被用来确定最优的超参数组合。通过比较不同参数组合下的mean_test_score,可以选择得分最高的参数组合作为最优配置。

示例

假设你正在使用GridSearchCV对随机森林分类器的n_estimators(树的数量)和max_depth(树的最大深度)进行网格搜索,并指定了准确率作为评分方法。交叉验证过程结束后,你可以通过访问GridSearchCV对象的cv_results_属性来获取所有参数组合下的测试结果,其中mean_test_score列将显示每个参数组合在测试集上的平均准确率。

注意事项

  1. 评分方法mean_test_score的具体含义取决于你指定的评分方法。不同的评分方法可能会产生不同的结果和解释。
  2. 交叉验证折数mean_test_score是基于交叉验证的折数计算得到的。折数越多,mean_test_score通常越稳定,但计算成本也越高。
  3. 过拟合与欠拟合:虽然mean_test_score有助于评估模型的泛化能力,但过高的得分也可能是过拟合的迹象。因此,在解释mean_test_score时,还需要结合其他指标(如训练集上的得分、模型的复杂度等)进行综合考虑。

综上所述,mean_test_score是交叉验证过程中用于评估模型性能的一个重要指标,它提供了模型在不同数据子集上得分的平均值,有助于我们更全面地了解模型的泛化能力。

std_test_score是什么意思

`std_test_score`在机器学习和数据科学领域,
特别是在使用交叉验证(Cross-Validation)进行模型评估时,是一个关键的统计量。
它代表了在交叉验证过程中,模型在测试集(或验证集)上得分的标准差。
这个标准差是基于模型在所有交叉验证折(folds)上的测试得分计算得到的,用于衡量这些得分之间的离散程度或变异性。

以下是关于`std_test_score`的详细解释:

定义

std_test_score是模型在交叉验证过程中测试集上得分的标准差。它反映了模型性能在不同测试子集之间的稳定性。标准差越小,说明模型在不同测试子集上的表现越一致,性能越稳定;反之,标准差越大,则表明模型性能在不同测试子集上波动较大,可能存在过拟合或欠拟合的风险。

作用

  1. 评估模型稳定性std_test_score提供了一个直接的指标来评估模型性能的稳定性。在比较不同模型或不同参数组合时,除了关注平均测试得分(mean_test_score)外,还应考虑得分的标准差。
  2. 参数调优辅助:在进行超参数调优时,std_test_score可以作为选择最优参数组合的辅助指标。虽然通常我们主要依据平均测试得分来选择参数,但在平均测试得分相近的情况下,标准差较小的参数组合可能更具优势,因为它表明模型性能更稳定。

示例

假设你正在使用GridSearchCV对某个机器学习模型的超参数进行网格搜索,并指定了交叉验证折数为5。交叉验证过程结束后,你可以通过访问GridSearchCV对象的cv_results_属性来获取所有参数组合下的测试结果。其中,std_test_score列将显示每个参数组合在测试集上得分的标准差。你可以结合mean_test_scorestd_test_score来综合评估不同参数组合的性能和稳定性。

注意事项

  • 标准差的意义:虽然标准差本身并不直接反映模型性能的优劣,但它提供了关于模型性能稳定性的重要信息。在评估模型时,应综合考虑平均测试得分和标准差。
  • 交叉验证折数:交叉验证折数会影响std_test_score的计算结果。折数越多,标准差通常越小(但计算成本也越高),因为更多的测试子集有助于更准确地估计模型性能的变异性。然而,折数过多也可能导致过拟合交叉验证本身的风险增加。
  • 结合其他指标:在评估模型时,除了关注mean_test_scorestd_test_score外,还应结合其他指标(如训练集上的得分、模型的复杂度、运行时间等)进行综合考虑。