释放双眼,带上耳机,听听看~!
本文介绍了网格搜索法(GridSearchCV)的原理、适用情况、缺点以及参数说明,帮助读者了解该技术的基本概念及应用场景。
参考网址
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份,分别为:训练集,验证集和测试集;
其中训练集用来模型训练,验证集用来调整参数,而测试集用来衡量模型表现好坏。
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中等概率采样;
对a、b两步中得到的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_
本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。