对半网格搜索HalvingSearchCV

对半网格搜索的概念

对半网格搜索算法设计了一个精妙的流程,可以很好的权衡子集的大小与计算效率问题,我们来看具体的流程:

1、首先从全数据集中无放回随机抽样出一个很小的子集 d 0 d_0 d0,并在 d 0 d_0 d0上验证全部参数组合的性能。根据 d 0 d_0 d0上的验证结果,淘汰评分排在后1/2的那一半参数组合


2、然后,从全数据集中再无放回抽样出一个比 d 0 d_0 d0大一倍的子集 d 1 d_1 d1,并在 d 1 d_1 d1上验证剩下的那一半参数组合的性能。根据 d 1 d_1 d1上的验证结果,淘汰评分排在后1/2的参数组合


3、再从全数据集中无放回抽样出一个比 d 1 d_1 d1大一倍的子集 d 2 d_2 d2,并在 d 2 d_2 d2上验证剩下1/4的参数组合的性能。根据 d 2 d_2 d2上的验证结果,淘汰评分排在后1/2的参数组合……

持续循环。如果使用S代表首次迭代时子集的样本量,C代表全部参数组合数,则在迭代过程中,用于验证参数的数据子集是越来越大的,而需要被验证的参数组合数量是越来越少的:

迭代次数 子集样本量 参数组合数
1 S C
2 2S 1 2 \frac{1}{2} 21C
3 4S 1 4 \frac{1}{4} 41C
4 8S 1 8 \frac{1}{8} 81C
……
(当C无法被除尽时,则向上取整)

备选参数组合只剩下一组,或剩余可用的数据不足,循环就会停下,具体地来说, 1 n \frac{1}{n} n1C <= 1或者nS > 总体样本量,搜索就会停止。在实际应用时,哪一种停止条件会先被触发,需要看实际样本量及参数空间地大小。同时,每次迭代时增加的样本量、以及每次迭代时不断减少的参数组合都是可以自由设定的。
在这种模式下,只有在不同的子集上不断获得优秀结果的参数组合能够被留存到迭代的后期,最终选择出的参数组合一定是在所有子集上都表现优秀的参数组合。这样一个参数组合在全数据上表现优异的可能性是非常大的,同时也可能展现出比网格/随机搜索得出的参数更大的泛化能力。

开始搜索

import re
import sklearn
import numpy as np
import pandas as pd
import matplotlib as mlp
import matplotlib.pyplot as plt
import time
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import KFold, HalvingGridSearchCV, cross_validate, RandomizedSearchCV

这次我们选择有2w9条数据的数据集

#导入波士顿房价数据
data = pd.read_csv(r"D:\Pythonwork\datasets\House Price\train_encode.csv",index_col=0)
#查看数据
data.head()
X = data.iloc[:,:-1]
y = data.iloc[:,-1]

对半网格搜索HalvingSearchCV_第1张图片
对半网格搜索的类如下所示:

class sklearn.model_selection.HalvingGridSearchCV(estimator, param_grid, *, factor=3, resource=‘n_samples’, max_resources=‘auto’, min_resources=‘exhaust’, aggressive_elimination=False, cv=5, scoring=None, refit=True, error_score=nan, return_train_score=True, random_state=None, n_jobs=None, verbose=0)

全部参数如下所示:

Name Description
estimator 调参对象,某评估器
param_grid 参数空间,可以是字典或者字典构成的列表
factor 每轮迭代中新增的样本量的比例,同时也是每轮迭代后留下的参数组合的比例
resource 设置每轮迭代中增加的验证资源的类型
max_resources 在一次迭代中,允许被用来验证任意参数组合的最大样本量
min_resources 首次迭代时,用于验证参数组合的样本量r0
aggressive_elimination 是否以全部数被使用完成作为停止搜索的指标,如果不是,则采取措施
cv 交叉验证的折数
scoring 评估指标,支持同时输出多个参数
refit 挑选评估指标和最佳参数,在完整数据集上进行训练
error_score 当网格搜索报错时返回结果,选择’raise’时将直接报错并中断训练过程
其他情况会显示警告信息后继续完成训练
return_train_score 在交叉验证中是否显示训练集中参数得分
random_state 控制随机抽样数据集的随机性
n_jobs 设置工作时参与计算的线程数
verbose 输出工作日志形式
# 定义参数空间
param_grid_simple = {"criterion": ["squared_error","poisson"]
                     , 'n_estimators': [*range(20,100,5)]
                     , 'max_depth': [*range(10,25,2)]
                     , "max_features": ["log2","sqrt",16,32,64,"auto"]
                     , "min_impurity_decrease": [*np.arange(0,5,10)]
                    }
#建立回归器、交叉验证
reg = RFR(random_state=83,verbose=True,n_jobs=-1)
cv = KFold(n_splits=5,shuffle=True,random_state=83)

#定义对半搜索
search = HalvingGridSearchCV(estimator=reg
                            ,param_grid=param_grid_simple
                            ,factor=1.5
                            ,min_resources=500
                            ,scoring = "neg_mean_squared_error"
                            ,verbose = True
                            ,random_state=83
                            ,cv = cv
                            ,n_jobs=-1)
#训练对半搜索评估器
#=====【TIME WARNING: 30~50min】=====#
start = time.time()
search.fit(X,y)
end = time.time() - start
print(end/60)

对比随机网格搜索

HPO方法 随机搜索 对半搜索
搜索空间/全域空间 800/1536 1536/1536
运行时间(分钟) 103.20 25.638(↓)
搜索最优(RMSE) 1055.555 1068.281
重建最优(RMSE) 1054.359 1082.916

可以看到,随机网格搜索的结果略微占优,但能够尝试的参数组合只有800个,且耗费的时间是对半搜索的4倍(1小时45分钟)。对于对半搜索,我们可以继续精细化调整整体的参数空间,进一步寻找更优的参数,但面对上万样本量的数据集,随机搜索的运算速度不足以支撑精细化调参,就更别提网格搜索了。之后,我们会给大家更详细地讲解更快速、更高效的优化方法。

你可能感兴趣的:(python,机器学习,人工智能)