当前位置: 首页 > 科技观察

Python机器学习:超参数调优

时间:2023-03-13 17:15:10 科技观察

1。什么是超参数?超参数(hyperparameters)是机器学习或深度学习算法中需要预先设定的参数。这些参数不是通过训练数据学习的参数;原算法一般只给出超参数的取值范围和意义。根据不同的应用场景,相同算法的相同超参数设置也不同。应该如何设置超参数?似乎没有捷径可走,尝试不同的值,比较不同的结果,取最好的结果。本文整理了不同的尝试方法,如下:RandomSearchGridSearch贝叶斯优化(Bayesianoptimization)2.GridSearchCV暴力耗尽是一种简单有效的寻找最优超参数的方法,但是对于庞大的超参数空间的算法,耗尽会消耗一个很多时间,特别是在多个超参数的情况下。GridSearchCV的做法是缩小超参数值的空间,只搜索人为重要的超参数和有限的固定值。同时结合交叉验证的方法搜索最优超参数。拿lightgbm为例子:importpandasaspdimportnumpyasnpimportmathimportwarningsimportlightgbmaslgbfromsklearn.model_selectionimportGridSearchCVfromsklearn.model_selectionimportRandomizedSearchCVlg=lgb.LGBMClassifier(silent=False)param_dist={"max_depth":[2,3,4,5,7,10],"n_estimators":[50,100,150,200],"min_child_samples“:[2,3,4,5,6]}grid_search=GridSearchCV(estimator=lg,n_jobs=10,param_grid=param_dist,cv=5,scoring='f1',verbose=5)grid_search.fit(X_train,y)grid_search.best_estimator_,grid_search.best_score_#Fitting5foldsforeachof120candidates,totalling600fits#[Parallel(n_jobs=10)]:UsingbackendLokyBackendwith10concurrentworkers.#[Parallel(n_jobs=10)]:Done52tasks|elapsed:2.5els(n_jobs)#[Parab]:Done142tasks|elapsed:6.6s#[Parallel(n_jobs=10)]:Done268tasks|elapsed:14.0s#[Parallel(n_jobs=10)]:Done430tasks|elapsed:25.5s#[Parallel(n_jobs=10)]:Done600outof600|elapsed:40.6sfinished#(LGBMClassifier(max_depth=10,min_child_samples=6,n_estimators=200,#silent=False),0.6359524127649383)从上面可以看出GridSearchCV搜索过程模型估计器:lgb.LGBMClassifierparam_grid:模型的超参数,上面的例子给出了3个参数,取值分别为6,4,5,组合搜索空间为120cv:交叉验证的折数(上例为5折交叉),算法训练总次数为120*5=600scoring:评价模型的索引分数,例如F1值搜索返回:最佳模型best_estimator_和最佳分数https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html#sklearn.model_selection.GridSearchCV3。RandomSearchCV与GridSearchCV一样,RandomSearchCV也是在有限的超参数空间中搜索最优超参数(人为重要的超参数),不同之处在于搜索超参数的值不是固定的,而是一定范围内的随机值。不同超参数值的组合也是随机的。值的随机性可能会弥补固定GridSearchCV超参数值的有限组合,但也可能更糟。Betterthangridsearchinvarioussensesbutstillexpensivetoguaranteegoodcoverageimportpandasaspdimportnumpyasnpimportmathimportwarningsimportlightgbmaslgbfromscipy.statsimportuniformfromsklearn.model_selectionimportGridSearchCVfromsklearn.model_selectionimportRandomizedSearchCVlg=lgb.LGBMClassifier(silent=False)param_dist={"max_depth":range(2,15,1),"n_estimators":range(50,200,4),"min_child_samples":[2,3,4,5,6],}random_search=RandomizedSearchCV(estimator=lg,n_jobs=10,param_distparam_distributions=param_dist,n_iter=100,cv=5,scoring='f1',verbose=5)random_search.fit(X_train,y)random_search.best_estimator_,random_search.best_score_#Fitting5foldsforeachof100candidates,totalling500fits#[Parallel(n_jobs=10)]:UsingbackendLokyBackendwith10concurrentworkers.#[Parallel(n_jobs=10)]:Done52tasks|elapsed:6.6s=1s(0)job]:Done142tasks|elapsed:12.9s#[Parallel(n_jobs=10)]:Done268tasks|elapsed:22.9s#[Parallel(n_jobs=10)]:Done430tasks|elapsed:36.2s#[Parallel(n_jobs=10)]:Done500outof500|elapsed:42.0sfinished#(LGBMClassifier(max_depth=11,min_child_samples=3,n_estimators=198,#silent=False),0.628180299445963)可以看出由上可知,与GridSearchCV基本类似,区别如下:n_iter:随机搜索值的个数param_distributions:搜索值的范围,除了list之外,还可以是uniformuniform等某种分布分布https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html#sklearn.model_selection.RandomizedSearchCV4。贝叶斯优化(Bayesianoptimization),无论是GridSearchCV还是RandomSearchCV,都是在tuner给定的限定范围内搜索全部或部分参数组合情况下模型的最佳性能;可以想象,最优的模型参数依赖于先验模型参数和有限的范围,在某些情况下不一定是最优的,而且对于一个大的候选参数空间的蛮力搜索也是非常耗时的。我们从不同的角度来看待参数搜索的问题:我们的目的是选择一个最优的参数组合,使得训练好的模型在给定的数据集上表现最好,所以可以理解为一个最优的参数组合。优化。我们通常使用梯度下降来迭代计算最优值,但是梯度下降要求优化后的函数是固定可导的,比如交叉熵损失。对于参数搜索问题,我们需要在众多模型(不同的超参数)中找到一个效果最好的模型,判断最好的是否由模型决定,模型是黑盒。是个凸函数,没办法用梯度下降法。在这种情况下,贝叶斯优化是一种解决方案。贝叶斯优化假设搜索模型空间呈高斯分布,利用高斯过程迭代计算新的最优参数,这些参数与当前最优参数相比有望得到提升。一般算法如下:输入:f为模型,M为高斯拟合函数,X为参数,S为参数选择算法AcquisitionFunction初始化数据集D进行高斯分布拟合,即(x,y),x为超参数,y为超参数x的执行结果(如准确率等)每次迭代迭代T次,用D数据集拟合高斯分布函数。根据拟合函数,根据AcquisitionFunction(如Expectedimprovementalgorithm),在parameterSpatially中选择一个优于当前最优解的参数xi。将参数xi代入模型f(训练一个模型),得到对应的yi(新模型的准确率等)(xi,yi)重新加入拟合数据集D,再次迭代。可以看出,贝叶斯优化每次都使用上一次的参数选择。并且GridSearchCV和RandomSearchCV的每次搜索都是独立的。至此,简单介绍一下贝叶斯优化的理论知识。实现贝叶斯优化的第三方库有很多,比如advisor、bayesian-optimization、Scikit-Optimize、GPyOpt等,本文以GPyOpt和bayesian-optimization为例。pipinstallgpyoptpipinstallbayesian-optimizationpipinstallscikit-optimizegpyopt例子importGPyimportGPyOptfromGPyOpt.methodsimportBayesianOptimizationfromsklearn.model_selectionimporttrain_test_splitfromsklearn.model_selectionimportcross_val_scorefromsklearn.datasetsimportload_irisfromxgboostimportXGBRegressorimportnumpyasnpiris=load_iris()X=iris.datay=iris.targetx_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=14)#超参数搜索空间bds=[{'name':'learning_rate','type':'continuous','domain':(0,1)},{'name':'gamma','type':'continuous','domain':(0,5)},{'name':'max_depth','type':'continuous','domain':(1,50)}]#Optimizationobjective模型Fdefcv_score(parameters):parametersparameters=parameters[0]score=cross_val_score(XGBRegressor(learning_rate=parameters[0],gamma=int(parameters[1]),max_depth=int(parameters[2])),X,y,scoring='neg_mean_squared_error').mean()score=np.array(score)returnscore#acquisition就是选择不同的AcquisitionFunctionoptimizer=GPyOpt。methods.BayesianOptimization(f=cv_score,#functiontooptimizedomain=bds,#box-constraintsoftheproblemacquisition_type='LCB',#LCBacquisitionacquisition_weight=0.1)#Explorationexploitationx_best=optimizer.X[np.argmax(optimizer.Y)]print("Bestparameters:learning_rate="+str(x_best[0])+",gamma="+str(x_best[1])+",max_depth="+str(x_best[2]))#Bestparameters:learning_rate=0.4272184438229706,gamma=1.4805727469635759,max_depth=41.8460390442754bayesian-optimization例子fromsklearn.datasetsimportmake_classificationfromxgboostimportXGBRegressorfromsklearn.model_selectionimportcross_val_scorefrombayes_optimportBayesianOptimizationiris=load_iris()X=iris.datay=iris.targetx_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=14)bds={'learning_rate':(0,1),'gamma':(0,5),'max_depth':(1,50)}#Optimizationobjectivedefcv_score(learning_rate,gamma,max_depth):score=cross_val_score(XGBRegressor(learning_ratelearning_rate=learning_rate,gamma=int(gamma),max_depth=int(max_depth)),X,y,scoring='neg_mean_squared_error').mean()score=np.array(score)returnscorerf_bo=贝叶斯优化(cv_score,bds)rf_bo.maximize()rf_bo.max|iter|target|gamma|learni...|max_depth|--------------------------------------------------------------|1|-0.0907|0.7711|0.1819|20.33||2|-0.1339|4.933|0.6599|8.972||3|-0.07285|1.55|0.8247|33.94||4|-0.1359|4.009|0.3994|25.55||5|-0.08773|1.666|0.9551|48.67||6|-0.05654|0.3798|0.0.05654|0.3798|0.1.221||7|-0.08425|0.6883|0.2564|33.25||8|-0.1113|3.071|0.8913|1.051||9|-0.9167|0.0|0.0|2.701||10|-0.05267|0.0538|0.1293|1.32||11|-0.08506|1.617|1.0|32.68||12|-0.09036|2.483|0.2906|33.21||13|-0.08969|0.4662|0.3612|34.74||14|-0.0723|1.295|0.2061|15.043||15|-0.07531|1.903|0.1182|35.11||16|-0.08494|2.977|1.0|34.57||17|-0.08506|1.231|1.0|36.05||18|-0.07023|2.81|0.838|36.16||19|-0.9167|1.94|0.0|36.99||20|-0.09041|3.894|0.9442|35.52||21|-0.1182|3.188|0.01882|35.14||22|-0.08521|0.931|0.05693|31.66||23|-0.1003|2.26|0.07555|31.78||24|-0.1018|0.08563|0.9838|32.22||25|-0.1017|0.8288|0.9947|30.57||26|-0.9167|1.943|0.0|30.2||27|-0.08506|1.518|1.0|35.04||28|-0.08494|3.464|1.0|32.36||29|-0.1224|4.296|0.4472|33.47||30|-0.1017|0.0|1.0|35.86|============================================================={'target':-0.052665895082105285,'params':{'gamma':0.05379782654053811,'learning_rate':0.1292986176550608,'max_depth':1.3198257775801387-只支持贝叶斯优化,如果分数越小越好,可以加一个负号,转化为最大值优化。两者的优化结果不是很一致。可能与实现方式和选择的算法不同,也与初始化的拟合数据集有关。.5.总结本文介绍了三种超参数优化策略,希望对你有所帮助。简单总结如下:GridSearchCV网格搜索,给定超参数和取值范围,遍历所有组合得到最优参数。首先你要给一个先验值,不能取太多,不然组合太多,时间太长。可以尝试启发式方法。RandomSearchCV随机搜索,搜索超参数的值不固定,是一定范围内的随机值贝叶斯优化,利用高斯过程迭代寻找最优参数,每次迭代都是基于前一次迭代的高斯拟合函数,寻找比上一次迭代更好的参数,推荐gpyopt库