网格搜索法(GridSearchCV)简介及应用场景

释放双眼,带上耳机,听听看~!
本文介绍了网格搜索法(GridSearchCV)的原理、适用情况、缺点以及参数说明,帮助读者了解该技术的基本概念及应用场景。

参考网址

blog.csdn.net/zxcvbnm2333…

1/网格搜索法(GridSearchCV)

<1>GridSearchCV:

GridSearchCV可以拆分成GridSearch和CV两部分,即网格搜素和交叉验证。
GridSearch系统地遍历多种参数组合,通过交叉验证确定最佳效果参数。
网格搜索是对参数进行搜索,在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数,这也是一个训练和比较的过程。
交叉验证根据cv参数的设置,设置为k折交叉验证,默认为5折。

<2>Grid Search:

网格搜素是一种调参手段,采用的是·穷举·搜索的方式,即在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。
其原理类似于在数组中找最大值。

<3>适用情况

网格搜索法适用于三四个(或者更少)的超参数。

<4>缺点

对于大数据集和多参数的情况,计算代价非常非常大,面临维度灾难。

<5>参数说明

class sklearn.model_selection.GridSearchCV(estimator, 
                                           param_grid, 
                                           *, 
                                           scoring=None, 
                                           n_jobs=None, 
                                           refit=True, 
                                           cv=None, 
                                           verbose=0, 
                                           pre_dispatch='2*n_jobs',
                                           error_score=nan,
                                           return_train_score=False)
                                           
estimator:选择使用的分类器,并且传入除需要确定最佳参数之外的其他参数。
param_grid:需要最优化的参数取值,值为字典或者列表。
scoring=None:模型评价标准,默认None;根据所选模型不同,评价准则不同。
             比如scoring=”accuracy”或者scoring='roc_auc’等。
             如果是None,则使用estimator的误差估计函数。
n_jobs:进程个数,默认为1。 若
        值为 -1,则用所有的CPU进行运算。
        若值为1,则不进行并行运算,这样的话方便调试。
refit=True:默认为True,程序将会以交叉验证得到的最佳参数组合,重新对所有可用的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。如果scoring参数有多个值,refit必须指定其中一种评价指标。

cv=None:交叉验证参数,默认None,使用五折交叉验证。
verbose=0:verbose:日志冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。
pre_dispatch=‘2*n_jobs’:指定总共分发的并行任务数。当n_jobs大于1时,数据将在每个运行点进行复制,这可能导致OOM,而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次
return_train_score=False:默认为FALSE,cv_results_属性将不包括训练分数。也可设置为‘warn’

<6>demo

from sklearn.model_selection import GridSearchCV 
from sklearn.datasets import load_iris 
from sklearn.svm import SVC 
from sklearn.model_selection import train_test_split 

#把要调整的参数以及其候选值 列出来; 
param_grid = {"gamma":[0.001,0.01,0.1,1,10,100], 
             "C":[0.001,0.01,0.1,1,10,100]} 
             
print("Parameters:{}".format(param_grid)) 
 
grid_search = GridSearchCV(SVC(),param_grid,cv=5) # 实例化一个GridSearchCV类 
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,random_state=10) 
grid_search.fit(X_train,y_train) # 训练,找到最优的参数,同时使用最优的参数实例化一个新的SVC estimator。 

print("Test set score:{:.2f}".format(grid_search.score(X_test,y_test))) 
print("Best parameters:{}".format(grid_search.best_params_)) 
print("Best score on train set:{:.2f}".format(grid_search.best_score_))

<7>以xgboost分类为例说明GridSearch网格搜索

import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.grid_search import GridSearchCV
 

# 导入训练数据
traindata_df = pd.read_csv("https://b2.7b2.com/traindata_4_3.txt",sep = ',')
traindata_df = traindata_df.set_index('instance_id')
trainlabel = traindata_df['is_trade'] # 标签数据
del traindata_df['is_trade']  # 剩下的是特征数据

print(traindata.shape,trainlabel.shape)
 
 
# 分类器使用 xgboost
clf1 = xgb.XGBClassifier()
 
# 设定网格搜索的xgboost参数搜索范围,值搜索XGBoost的主要6个超参数
param_dist = {
        'n_estimators':range(80,200,4),
        'max_depth':range(2,15,1),
        'learning_rate':np.linspace(0.01,2,20),
        'subsample':np.linspace(0.7,0.9,20),
        'colsample_bytree':np.linspace(0.5,0.98,10),
        'min_child_weight':range(1,9,1)
        }

# GridSearchCV参数说明,clf1设置训练的学习器
# param_dist字典类型,放入参数搜索范围
# scoring = 'neg_log_loss',精度评价方式设定为“neg_log_loss“
# n_iter=300,训练300次,数值越大,获得的参数精度越大,但是搜索时间越长
# n_jobs = -1,使用所有的CPU进行训练,默认为1,使用1个CPU

grid = GridSearchCV(clf1,
                    param_dist,
                    cv = 3,
                    scoring = 'neg_log_loss',
                    n_iter=300,
                    n_jobs = -1)
 
# 在训练集上训练
grid.fit(traindata.values, np.ravel(trainlabel.values))

# 返回最优的训练器
best_estimator = grid.best_estimator_
print(best_estimator) # 最好的模型
# 输出最优训练器的精度

<8>以SVR为例说明GridSearch网格搜索

# 以两个超参数的调优过程为例:

from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split

iris_data = load_iris()
X_train,X_test,y_train,y_test = train_test_split(iris_data.data,
                                                 iris_data.target, 
                                                 random_state=0)

# grid search start
best_score = 0

for gamma in [0.001,0.01,1,10,100]:
    for c in [0.001,0.01,1,10,100]:
        # 对于每种参数可能的组合,进行一次训练
        svm = SVC(gamma=gamma,C=c)
        svm.fit(X_train,y_train)
        score = svm.score(X_test,y_test)
        # 找到表现最好的参数
        if score > best_score:
            best_score = score
            best_parameters = {'gamma':gamma,"C":c}

print('Best socre:{:.2f}'.format(best_score))
print('Best parameters:{}'.format(best_parameters))

# 输出结果:
#Best socre:0.97
#Best parameters:{'gamma': 0.001, 'C': 100}
上面调参存在的问题是什么呢?
原始数据集划分成训练集和测试集以后,其中测试集除了用作调整参数,也用来测量模型的好坏;
这样做导致最终的评分结果比实际效果好。(因为测试集在调参过程中,送到了模型里,而我们的目的是将训练模型应用到unseen data上)。
解决方法是什么呢?
对训练集再进行一次划分,分为训练集和验证集,
这样划分的结果就是:原始数据划分为3份,分别为:训练集,验证集和测试集;
其中训练集用来模型训练,验证集用来调整参数,而测试集用来衡量模型表现好坏。

网格搜索法(GridSearchCV)简介及应用场景

from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split

iris_data = load_iris()
# X_train,X_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,random_state=0)
X_trainval,X_test,y_trainval,y_test = train_test_split(iris_data.data,iris_data.target,random_state=0)
X_train ,X_val,y_train,y_val = train_test_split(X_trainval,y_trainval,random_state=1)
# grid search start
best_score = 0
for gamma in [0.001,0.01,1,10,100]:
    for c in [0.001,0.01,1,10,100]:
        # 对于每种参数可能的组合,进行一次训练
        svm = SVC(gamma=gamma,C=c)
        svm.fit(X_train,y_train)
        score = svm.score(X_val,y_val)
        # 找到表现最好的参数
        if score > best_score:
            best_score = score
            best_parameters = {'gamma':gamma,"C":c}

# 使用最佳参数,构建新的模型
svm = SVC(**best_parameters)

# 使用训练集和验证集进行训练 more data always resultd in good performance
svm.fit(X_trainval,y_trainval)

# evalyation 模型评估
test_score = svm.score(X_test,y_test)

print('Best socre:{:.2f}'.format(best_score))
print('Best parameters:{}'.format(best_parameters))
print('Best score on test set:{:.2f}'.format(test_score))
结果:
Best socre:0.96
Best parameters:{'gamma': 0.001, 'C': 10}
Best score on test set:0.92
然而,这种简洁的grid search方法,其最终的表现好坏与初始数据的划分结果有很大的关系,
为了处理这种情况,我们采用交叉验证cv的方式来减少偶然性。
# 针对任何一种参数组合,我们都进行交叉验证,然后计算均值
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split,cross_val_score

iris_data = load_iris()
# X_train,X_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,random_state=0)
X_trainval,X_test,y_trainval,y_test = train_test_split(iris_data.data,iris_data.target,random_state=0)
X_train ,X_val,y_train,y_val = train_test_split(X_trainval,y_trainval,random_state=1)
# grid search start
best_score = 0
for gamma in [0.001,0.01,1,10,100]:
    for c in [0.001,0.01,1,10,100]:
        # 对于每种参数可能的组合,进行一次训练
        svm = SVC(gamma=gamma,C=c)
        # 5 折交叉验证
        scores = cross_val_score(svm,X_trainval,y_trainval,cv=5)
        score = scores.mean()
        # 找到表现最好的参数
        if score > best_score:
            best_score = score
            best_parameters = {'gamma':gamma,"C":c}

# 使用最佳参数,构建新的模型
svm = SVC(**best_parameters)

# 使用训练集和验证集进行训练 more data always resultd in good performance
svm.fit(X_trainval,y_trainval)

# evalyation 模型评估
test_score = svm.score(X_test,y_test)

print('Best socre:{:.2f}'.format(best_score))
print('Best parameters:{}'.format(best_parameters))
print('Best score on test set:{:.2f}'.format(test_score))
结果:
Best socre:0.97
Best parameters:{'gamma': 0.01, 'C': 100}
Best score on test set:0.97

2/随机搜索(RandomizedSearchCV)

<1>原理:

随机搜索并未尝试所有参数值,而是从指定的分布中采样固定数量的参数设置。
它的理论依据是,如果随机样本点集足够大,那么也可以找到全局的最大或最小值,或它们的近似值。
通过对搜索范围的随机取样,随机搜索一般会比网格搜索要快一些。但是和网格搜索的快速版(非自动版)相似,结果也是没法保证的。

<2>RandomizedSearchCV的使用方法

其实是和GridSearchCV一致的,但它以随机在参数空间中采样的方式代替了GridSearchCV对于参数的网格搜索,在对于有连续变量的参数时,RandomizedSearchCV会将其当做一个分布进行采样进行这是网格搜索做不到的,它的搜索能力取决于设定的n_iter参数。

<3>RandomSearchCV的搜索策略如下:

对于搜索范围是distribution的超参数,根据给定的distribution随机采样;
对于搜索范围是list的超参数,在给定的list中等概率采样;
对ab两步中得到的n_iter组采样结果,进行遍历。
如果给定的搜索范围均为list,则不放回抽样n_iter次。

<4>适用情况:

数据规模大,精确的结果难以在一定时间计算出。
结果的些许的不精确能够被接受。
求取的结果是最优化(optimization)问题,有一个成本计算模型

<5>参数说明

class sklearn.model_selection.RandomizedSearchCV(estimator, 
                                                 param_distributions,
                                                 *, 
                                                 n_iter=10, 
                                                 scoring=None, 
                                                 n_jobs=None, 
                                                 refit=True, 
                                                 cv=None, 
                                                 verbose=0,
                                                 pre_dispatch='2*n_jobs', 
                                                 random_state=None,
                                                 error_score=nan,
                                                 return_train_score=False)
参数和GridSearchCV类似。

<6>demo

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform
iris = load_iris()
logistic = LogisticRegression(solver='saga', tol=1e-2, max_iter=200,
...                               random_state=0)
distributions = dict(C=uniform(loc=0, scale=4),
...                      penalty=['l2', 'l1'])
clf = RandomizedSearchCV(logistic, distributions, random_state=0)
search = clf.fit(iris.data, iris.target)
search.best_params_
{'C': 2..., 'penalty': 'l1'}

3/二者的对比

1.相较于网格搜索,随机搜索的速度更快,精度稍微提升或降。
1.当超参数的搜索空间很大时,更推荐使用RandomizedSearchCV。
1.使用随机搜索方法的难点在于确定参数的分布范围,这需要对所使用的模型有足够的了解。

4/使用多种评估指标

在网格搜索中使用多种评估指标
scoring = {'AUC': 'roc_auc', 'Accuracy': make_scorer(accuracy_score)} 

# Setting refit='AUC', refits an estimator on the whole dataset with the 
# parameter setting that has the best cross-validated AUC score. 
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), 
              param_grid={'min_samples_split': range(2, 403, 10)}, 
              scoring=scoring, 
              refit=True, 
              return_train_score=True) 
gs.fit(X, y) 
results = gs.cv_results_
本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

使用卷积神经网络(CNN)构建图像分类模型

2023-12-15 19:42:14

AI教程

YOLOv1:一种基于卷积网络的物体识别方法

2023-12-15 19:52:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索