本章内容:
- 对半网格搜索的原理、运行流程(理论说明)
- sklearn中HalvingGridSearchCV参数说明
- 🤷?♀?案例:对半网格搜索_房价数据集_python
索引
1(理论)对半网格搜索的原理与流程
📖 对半网格搜索主要解决 数据量较大导致的运算时间长的问题
📖 对半网格搜索原理 通过每次抽取部分数据集,达到减少每次建模使用的数据量,从而减少计算量。 需要注意的是,为了保证减少的数据量能有效反映整体的数据情况,故抽取的少量数据集分布需要和整体数据分布一致。
📖 对半网格流程
1、首先从全数据集中无放回随机抽样出一个很小的子集 𝑑0 ,并在 𝑑0 上验证全部参数组合的性能。根据 𝑑0 上的验证结果,淘汰评分排在后1/2的那一半参数组合。(因为数据集很小,所以哪怕验证全部参数组合也比较快)
2、然后,从全数据集中再无放回抽样出一个比 𝑑0 大一倍的子集 𝑑1 ,并在 𝑑1 上验证剩下的那一半参数组合的性能。根据 𝑑1 上的验证结果,淘汰评分排在后1/2的参数组合
3、再从全数据集中无放回抽样出一个比 𝑑1 大一倍的子集 𝑑2 ,并在 𝑑2 上验证剩下1/4的参数组合的性能。根据 𝑑2 上的验证结果,淘汰评分排在后1/2的参数组合……
4、当备选参数组合只剩下1组,或剩余可用数据不足时,循环搜索停止。
📖 对半网格搜索的局限
-
对半搜索在开始时选择的数据集,筛选掉了最多的参数组合;如果最初的数据集与整体数据集差异较大,则最后选择的参数效果则不佳。 -
为了避免这个问题,最初的数据集数据量不能太小,且整体数据的样本量要很大。 -
如果整体数据样本较小,可能对半网格搜索效果往往不如普通网格搜索效果。
2 sklearn中HalvingGridSearchCV参数说明
🔣 HalvingGridSearchCV参数说明
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingGridSearchCV
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 | 输出工作日志形式 |
-
factor 每轮迭代中新增的样本量的比例,同时也是每轮迭代后留下的参数组合的比例。例如,factor=3时,下一轮迭代的样本量会是上一轮的3倍,每次迭代后有1/3的参数组合被留下。该参数通常取3时效果比较好。 -
resource 设置每轮迭代中增加的验证资源的类型,输入为字符串。默认是样本量,输入为"n_samples",也可以是任意集成算法当中输入正整数的弱分类器,例如"n_estimators",那么每次迭代后树的棵树增加factor倍。 -
min_resource 首次迭代时,用于验证参数组合的样本量r0。可以输入正整数,或两种字符串"smallest",“exhaust”。
-
输入正整数n,表示首次迭代时使用n个样本。 -
输入"smallest",则根据规则计算r0: ?? 当资源类型是样本量时, 对回归类算法,r0 = 交叉验证折数n_splits * 2当资源类型是样本量时; 对分类算法,r0 = 类别数量n_classes_ * 交叉验证折数n_splits * 2; 当资源类型不是样本量时,等于1; -
输入"exhaust",则根据迭代最后一轮的最大可用资源倒退r0。 例如,factor=2, 样本量为1000时,一共迭代3次时,则最后一轮迭代的最大可用资源为1000,倒数第二轮为500,倒数第三轮(第一轮)为250。此时r0 = 250。"exhaust"模式下最有可能得到好的结果,不过计算量会略大,计算时间会略长。
📖 如何判断停止迭代的条件是哪种?
-
f
a
c
t
o
r
?
m
i
n
_
r
e
s
o
u
r
c
e
i
>
数
据
集
factor*min\_resource^i>数据集
factor?min_resourcei>数据集,计算得到i为数据量支持的迭代次数
-
参
数
组
合
数
/
/
f
a
c
t
o
r
i
<
1
参数组合数//factor^i<1
参数组合数//factori<1,计算得到i为参数组合支持的迭代次数
以上两种方法的i中,较小的i对应的情况为迭代停止的条件。
比如
i
i
<
i
2
i_i<i_2
ii?<i2?,那么停止迭代的条件为:使用全部的数据量; 这种情况下的迭代次数并不支持跑完整个参数组合,也就是可能最优的参数组合没来得及进行试验,迭代就已经停止了。
🔣 aggressive_elimination参数
- 该参数用于解决数据量较小,不足以支持跑完整个参数组合的情况;
- 参数设置为True时,会重复使用首次迭代时的样本量,直到剩下的数据足以支撑样本量的增加直到只剩下最后一组备选参数。
- 参数设置为False时,以全部样本被用完作为搜索结束的指标。
局限:由于使用首次迭代样本,该样本集与整体数据集差异最大;故使用次数越多,结果可能偏差越大。
?? 权衡迭代次数与计算量时,需要考虑的点:
-
min_resources的值不能太小,且在全部迭代过程结束之前,我们希望使用尽量多的数据 -
迭代完毕之后,剩余的验证参数组合不能太多,10以下最佳,如果无法实现,则30以下也可以接受 -
迭代次数不能太多,否则时间可能会太长
🗣 如何判断首次样本量: 首先,打印每次迭代的样本数、参数组合数量:
factor = 1.5
n_samples = X.shape[0]
min_resources = 500
space = 1440
for i in range(100):
if (min_resources*factor**i > n_samples) or (space//factor**i < 1):
break
print(i+1,"本轮迭代样本:{}".format(min_resources*factor**i)
,"本轮验证参数组合:{}".format(space//factor**i + 1))
- i:表示迭代停止时,共计进行的迭代次数
- 迭代样本量:表示有多少样本被用于计算,越接近总体数据量越好
- 参数组合:表示参数空间中有多少组合被剩下了,越小越好。
- factor越大越好;min_resources越大越好
🤷?♀?3 案例:对半随机网格搜索_房价数据集_python
📖 对半随机网格搜索VS随机网格搜索 运行时间:对半搜索时间更短 模型效果:随机网格搜索略优
🔣 案例:对半随机网格搜索_房价数据集_python
data=pd.read_csv(r'C:\Users\EDZ\test\ML-2 courseware\Lesson 9.随机森林模型\datasets\House Price\big_train.csv',index_col=0)
X=data.iloc[:,:-1]
y=data.iloc[:,-1]
X.head()
param_grid_simple={'n_estimators':range(60,120,5)
,'max_depth':range(10,25,2)
,'max_features':['sqrt',16,32]
,'min_impurity_decrease':range(5,30,5)}
def count_space(param_grid_simple):
no_option=1
for i in param_grid_simple:
no_option*=len(param_grid_simple[i])
return no_option
count_space(param_grid_simple)
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.model_selection import KFold
model=RFR(random_state=7)
cv=KFold(n_splits=5,shuffle=True,random_state=7)
search=HalvingGridSearchCV(estimator=model
,param_grid=param_grid_simple
,factor=1.5
,min_resources=500
,scoring='neg_mean_squared_error'
,n_jobs=4
,random_state=7
,cv=cv
)
search.fit(X,y)
search.best_estimator_
abs(search.best_score_)**0.5
from sklearn.model_selection import cross_validate
def RMSE(cvresult,key):
return (abs(cvresult[key])**0.5).mean()
def rebuild_on_best_param(ad_reg):
cv=KFold(n_splits=5,shuffle=True,random_state=7)
res_post_adjusted=cross_validate(ad_reg,X,y
,cv=cv
,scoring='neg_mean_squared_error'
,return_train_score=True
,n_jobs=-1)
print('训练RMSE:{:.3f}'.format(RMSE(res_post_adjusted,'train_score')))
print('测试RMSE:{:.3f}'.format(RMSE(res_post_adjusted,'test_score')))
rebuild_on_best_param(search.best_estimator_)
|