网格搜索、随机搜索和贝叶斯调参总结与实践

网格搜索

网格搜索时应用最广泛的超参数搜素算法,网格搜索通过查找搜索范围内的所有点,来确定最优值。一般是通过给出较大的搜索范围以及较小的步长,网格搜索时一定可以找到全局最大值或全局最小值的。

但是网格搜索有一个较大的问题时:它十分消耗计算资源,特别是需要调优的超参数比较多的时候。因此在实践比赛中,需要调参的模型数量与对应的超参数比较多,而设计的数据量又比较大,因此相当消耗时间。此外,由于给出的超参数的组合比较多,因此一般都会固定多数参数,分布对1~2个超参数进行调节,这样能够减少时间但是难以自动进行。而且由于目标参数一般是非凸的,因此容易陷入局部最小值。

from sklearn.model_selection import GridSearchCV

#定义自己的网格搜索函数
def GridSearch(clf, params, X, y):
    gscv = GridSearchCV(clf, params, scoring='neg_mean_squared_error', n_jobs=1, cv=5)
    gscv.fit(X, y)
    print("The best result: ", gscv.cv_results_)
    print("The best params: ", gscv.best_params_)

#实验
params_sklearn = {
        "boosting_type" : 'gbdt',
        'max_depth':3,
        "learning_rate" : 0.1,
        "objective" : "binary",
        "min_child_samples" : 20,
        "metric" : ['binary_logloss','auc'],
        "verbose" : -1,
        'reg_lambda': 0.1,
        'reg_alpha': 0.2,
        "random_state": 420,
}
gbm = lgb.LGBMClassifier(**params_sklearn)
#网格搜索的参数
params_grid = {
    'num_leaves':range(30,50),
    'max_depth': range(4,8),
}
gscv = GridSearch(gbm, params_grid, train, y_train)
#The best params:  {'max_depth': 6, 'num_leaves': 40}
#Timing 16.8s

随机搜索

与网格搜索相比,随机搜索并未尝试所有参数值,而是从指定的分布中采样固定数量的参数设置。它的理论依据是,如果随即样本点集足够大,那么也可以找到全局的最大或最小值,或它们的近似值。通过对搜索范围的随机取样,随机搜索一般会比网格搜索要快一些。但是和网格搜索的快速版(非自动版)相似,结果也是没法保证的。

当超参数的搜索空间很大时,最好使用RandomizedSearchCV 。这个类的使用方法和类 GridSearchCV 很相似,但它不是尝试所有可能的组合,而是通过选择每个超参数的一个随机值的特定数量的随机组合。

#随机搜索,和网格搜索代码一致,除了更改GridSearchCV为RandomizedSearchCV

from sklearn.model_selection import RandomizedSearchCV

#定义自己的网格搜索函数
def RandomizedSearch(clf, params, X, y):
    rscv = RandomizedSearchCV(clf, params, scoring='neg_mean_squared_error', n_jobs=1, cv=5)
    rscv.fit(X, y)
    print("The best result: ", rscv.cv_results_)
    print("The best params: ", rscv.best_params_)

#实验
params_sklearn = {
        "boosting_type" : 'gbdt',
        'max_depth':3,
        "learning_rate" : 0.1,
        "objective" : "binary",
        "min_child_samples" : 20,
        "metric" : ['binary_logloss','auc'],
        "verbose" : -1,
        'reg_lambda': 0.1,
        'reg_alpha': 0.2,
        "random_state": 420,
}
gbm = lgb.LGBMClassifier(**params_sklearn)
#网格搜索的参数
params_randm = {
    'num_leaves':range(30,50),
    'max_depth': range(4,8),
}
rscv = RandomizedSearch(gbm, params_randm, train, y_train)

#The best params:  {'num_leaves': 49, 'max_depth': 7}
#Timing:2.8s

贝叶斯优化

主要思想是:给定优化的目标函数(广义的函数,只需要指定输入和输出即可,无需知道内部结构以及数学性质),通过不断地添加样本点来更新目标函数地后验分布。简单来说,就是考虑和上一次参数地信息,从而更好地调整当前地参数。

贝叶斯优化与常规的网格搜索或者随机搜索的区别是:

  • 贝叶斯调参采用高斯过程,考虑之前的参数信息,不断地更新先验;网格搜索未考虑之前地参数信息
  • 贝叶斯调参迭代次数少,速度快,网格搜索速度慢,参数多时容易导致维度爆炸。
  • 贝叶斯调参针对非凸问题依旧稳健,网格搜索针对非凸问题容易陷入局部最小值。
#设定贝叶斯优化的黑盒函数LGB_bayesian
def LGB_bayesian(
    num_leaves,  # int
    min_data_in_leaf,  # int
    learning_rate,
    min_sum_hessian_in_leaf,    # int  
    feature_fraction,
    lambda_l1,
    lambda_l2,
    min_gain_to_split,
    max_depth):
    
    # LightGBM expects next three parameters need to be integer. So we make them integer
    num_leaves = int(num_leaves)
    min_data_in_leaf = int(min_data_in_leaf)
    max_depth = int(max_depth)

    assert type(num_leaves) == int
    assert type(min_data_in_leaf) == int
    assert type(max_depth) == int

    param = {
        'num_leaves': num_leaves,
        'max_bin': 63,
        'min_data_in_leaf': min_data_in_leaf,
        'learning_rate': learning_rate,
        'min_sum_hessian_in_leaf': min_sum_hessian_in_leaf,
        'bagging_fraction': 1.0,
        'bagging_freq': 5,
        'feature_fraction': feature_fraction,
        'lambda_l1': lambda_l1,
        'lambda_l2': lambda_l2,
        'min_gain_to_split': min_gain_to_split,
        'max_depth': max_depth,
        'save_binary': True, 
        'seed': 1337,
        'feature_fraction_seed': 1337,
        'bagging_seed': 1337,
        'drop_seed': 1337,
        'data_random_seed': 1337,
        'objective': 'binary',
        'boosting_type': 'gbdt',
        'verbose': 1,
        'metric': 'auc',
        'is_unbalance': True,
        'boost_from_average': False,
        "verbosity":-1

    }    
    
    
    lgb_train = lgb.Dataset(train,
                           label=y_train)
    lgb_valid = lgb.Dataset(test,label=y_test,reference=lgb_train)   

    num_round = 500
    gbm= lgb.train(param, lgb_train, num_round, valid_sets = [lgb_valid],callbacks=[lgb.early_stopping(stopping_rounds=5)])   
    predictions = gbm.predict(test,num_iteration=gbm.best_iteration)
    score = roc_auc_score(y_test, predictions)
    
    return score
bounds_LGB = {
    'num_leaves': (5, 20), 
    'min_data_in_leaf': (5, 20),  
    'learning_rate': (0.01, 0.3),
    'min_sum_hessian_in_leaf': (0.00001, 0.01),    
    'feature_fraction': (0.05, 0.5),
    'lambda_l1': (0, 5.0), 
    'lambda_l2': (0, 5.0), 
    'min_gain_to_split': (0, 1.0),
    'max_depth':(3,15),
}

#将它们全部放在BayesianOptimization对象中
from bayes_opt import BayesianOptimization
LGB_BO = BayesianOptimization(LGB_bayesian, bounds_LGB, random_state=13)
print(LGB_BO.space.keys)#显示要优化的参数
import warnings
import gc
pd.set_option('display.max_columns', 200)

init_points = 5
n_iter = 5
print('-' * 130)

with warnings.catch_warnings():
    warnings.filterwarnings('ignore')
    LGB_BO.maximize(init_points=init_points, n_iter=n_iter, acq='ucb', xi=0.0, alpha=1e-6)

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