-
索引
🔣 函数及参数
🔑 公式
🗣 案例
📌 名词解释
📖 摘抄
-
1 随机网格搜索的基本原理
📖 影响枚举网格搜索运算速度的因素
1 参数空间的大小:参数空间越大,需要建模的次数越多
2 数据量的大小:数据量越大,每次建模时需要的算力和时间越多
🗣 案例:全域参数空间VS部分参数空间(示意图)
n_e_list=range(50,350,50) m_d_list=range(2,7) comb=pd.DataFrame([(n_estimators, max_depth) for n_estimators in n_e_list for max_depth in m_d_list]) # 创建n_e_list和m_d_list的笛卡尔乘积 fig,[ax1,ax2]=plt.subplots(1,2,dpi=100) ax1.scatter(comb.iloc[:,0],comb.iloc[:,1]) ax1.set_title('GridSearch') ax2.scatter(comb.iloc[:,0],comb.iloc[:,1]) ax2.scatter([50,250,200,200,300,100,150,150],[4,2,6,3,2,3,2,5],cmap='red',s=50) ax2.set_title('RandomSearch') plt.show()
📌 随机网格搜索
随机抽取参数子空间,并在自空间中进行搜索的方法。
对比枚举网格搜索的优势:
- 运算速度快
- 覆盖空间大
- 最小损失与枚举网络的最小损失很接近
📖 随机网格搜索的抽样特点
随机网格搜索采用“循环迭代”。
在这一次迭代中随机抽取1组参数进行建模,下一次迭代再随机抽取1组参数进行建模。由于这种随机抽样是不放回的,因此不会出现两次抽中同一组参数的问题。
可以控制随机网格搜索的迭代次数,来控制整体被抽出的参数子空间的大小,这种做法往往被称为“赋予随机网格搜索固定的计算量,当全部计算量被消耗完毕之后,随机网格搜索就停止”。
随机网格搜索在实际运行时,并不是先抽样出子空间,再对子空间进行搜索。
-
2 随机网格搜索实现
🔣 skelarn中随机网格搜索
from sklearn.model_selection import RandomizedSearchCV 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, # 当网格搜索报错时返回结果,选择'raise'时将直接报错并中断训练过程,其他情况会显示警告信息后继续完成训练 return_train_score=False, # 是否显示训练集中参数得分 )
Name Description estimator 调参对象,某评估器 param_distributions 全域参数空间,可以是字典或者字典构成的列表 n_iter 迭代次数,迭代次数越多,抽取的子参数空间越大 scoring 评估指标,支持同时输出多个参数 n_jobs 设置工作时参与计算的线程数 refit 挑选评估指标和最佳参数,在完整数据集上进行训练 cv 交叉验证的折数 verbose 输出工作日志形式 pre_dispatch 多任务并行时任务划分数量 random_state 随机数种子 error_score 当网格搜索报错时返回结果,选择’raise’时将直接报错并中断训练过程,其他情况会显示警告信息后继续完成训练 return_train_score 在交叉验证中是否显示训练集中参数得分 🔣 案例:随机网格在随机森林上的应用_房价数据集
📖 在相同的参数空间、模型下,随机网格搜索速度比普通网格搜索速度更快。
运行时间≈n_iter/全域空间组合数*网格搜索
from sklearn.ensemble import RandomForestRegressor as RFR from sklearn.model_selection import KFold param_grid_simple = {'n_estimators': range(50,150,10) , 'max_depth': range(10,25,2) , "max_features": ["sqrt",16,32,64,"auto"] , "min_impurity_decrease": np.arange(0,5,2) } #计算参数空间大小 def count_space(param): no_option = 1 for i in param_grid_simple: no_option *= len(param_grid_simple[i]) print(no_option) count_space(param_grid_simple) # 训练模型 model = RFR(random_state=7,verbose=True,n_jobs=4) cv = KFold(n_splits=5,shuffle=True,random_state=7) search = RandomizedSearchCV(estimator=model ,param_distributions=param_grid_simple ,n_iter = 600 #子空间的大小是全域空间的一半左右 ,scoring = "neg_mean_squared_error" ,verbose = True ,cv = cv ,random_state=1412 ,n_jobs=-1 ) search.fit(X,y) search.best_estimator_ # 查看模型参数结果 # RandomForestRegressor(max_depth=18, max_features=16, min_impurity_decrease=0, # n_jobs=4, random_state=7, verbose=True) abs(search.best_score_)**0.5 # 查看模型RMSE分数 # 29160.978459432965 # 查看最优参数的模型效果 from sklearn.model_selection import cross_validate ad_reg=RFR(max_depth=18 , max_features=16 , min_impurity_decrease=0 , random_state=7 , n_jobs=-1) 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) result_post_adjusted = cross_validate(ad_reg,X,y ,cv=cv ,scoring="neg_mean_squared_error" ,return_train_score=True ,verbose=True ,n_jobs=-1) print("训练RMSE:{:.3f}".format(RMSE(result_post_adjusted,"train_score"))) print("测试RMSE:{:.3f}".format(RMSE(result_post_adjusted,"test_score"))) rebuild_on_best_param(ad_reg) # 训练RMSE:10760.565 # 测试RMSE:28265.808
-
3 连续型参数空间
📖 连续型可能来带更好的取值
网格搜索:只能使用组合好的参数组合点;
随机搜索:接受“分布”作为输入如上图所示,对于网格搜索,如果损失函数的最低点位于两组参数之间,在这种情况下,枚举网格搜索是不可能找到最小值的;但对于随机网格搜索,由于是一段分布上随机选择参数点,因此在同样的参数空间中,取到更好的值的可能性更大。
📖 当参数空间中包含某个分布的时候,无法估计全域参数空间的大小。
🗣 案例:对min_impurity_decrease进行连续分布搜索
📖 随机搜索中使用连续型分布的效果
对比网格搜索,同样搜索空间下,运行速度更快,搜索与重建交叉验证结果RMSE略优;
对比小空间网格搜索,运行时间较长,RMSE略优;
对比大空间网格搜索,运行时间较长,RMSE略劣(模型效果不一定)。效果:连续型随机网格>大空间随机网格>随机网格>网格搜索
运算速度:网格搜索>连续型随机网格>大空间随机网格>随机网格当枚举网格搜索所使用的全域参数空间足够大/足够密集时,枚举网格搜索的最优解是随机网格搜索的上限,因此理论上随机网格搜索不会得到比枚举网格搜索更好的结果。
param_grid_simple={'n_estimators':range(50,150,10) ,'max_depth':range(10,25,2) ,'max_features':range(10,20,2) ,'min_impurity_decrease':scipy.stats.uniform(0,50)} model=RFR(random_state=7) cv=KFold(n_splits=5,shuffle=True,random_state=7) search=RandomizedSearchCV(estimator=model ,param_distributions=param_grid_simple ,n_iter=600 ,scoring='neg_mean_squared_error' ,cv=cv ,random_state=7 ,n_jobs=4) search.fit(X,y) search.best_estimator_ # RandomForestRegressor(max_depth=18, max_features=16, # min_impurity_decrease=34.80143424780533, random_state=7) abs(search.best_score_)**0.5 # 29155.5402993104 rebuild_on_best_param(search.best_estimator_) # 训练RMSE:10733.842 # 测试RMSE:28285.986