• 机器学习中参数优化调试方法


    1  超参数优化

    图片

    调参即超参数优化,是指从超参数空间中选择一组合适的超参数,以权衡好模型的偏差(bias)和方差(variance),从而提高模型效果及性能。常用的调参方法有:

    • 人工手动调参

    • 网格/随机搜索(Grid / Random Search)

    • 贝叶斯优化(Bayesian Optimization)

    图片

    注:超参数 vs 模型参数差异 超参数是控制模型学习过程的(如网络层数、学习率);模型参数是通过模型训练学习后得到的(如网络最终学习到的权重值)。

    2  人工调参

    手动调参需要结合数据情况及算法的理解,选择合适调参的优先顺序及参数的经验值。

    不同模型手动调参思路会有差异,如随机森林是一种bagging集成的方法,参数主要有n_estimators(子树的数量)、max_depth(树的最大生长深度)、max_leaf_nodes(最大叶节点数)等。(此外其他参数不展开说明) 对于n_estimators:通常越大效果越好。参数越大,则参与决策的子树越多,可以消除子树间的随机误差且增加预测的准度,以此降低方差与偏差。对于max_depth或max_leaf_nodes:通常对效果是先增后减的。取值越大则子树复杂度越高,偏差越低但方差越大。

    图片

    3 网格/随机搜索

    图片

    • 网格搜索(grid search),是超参数优化的传统方法,是对超参数组合的子集进行穷举搜索,找到表现最佳的超参数子集。

    • 随机搜索(random search),是对超参数组合的子集简单地做固定次数的随机搜索,找到表现最佳的超参数子集。对于规模较大的参数空间,采用随机搜索往往效率更高。

    1. import numpy as np
    2. from sklearn.model_selection import GridSearchCV
    3. from sklearn.model_selection import RandomizedSearchCV
    4. from sklearn.ensemble import RandomForestClassifier
    5. # 选择模型 
    6. model = RandomForestClassifier()
    7. # 参数搜索空间
    8. param_grid = {
    9.     'max_depth': np.arange(1201),
    10.     'n_estimators': np.arange(15010),
    11.     'max_leaf_nodes': np.arange(210010)
    12. }
    13. # 网格搜索模型参数
    14. grid_search = GridSearchCV(model, param_grid, cv=5, scoring='f1_micro')
    15. grid_search.fit(x, y)
    16. print(grid_search.best_params_)
    17. print(grid_search.best_score_)
    18. print(grid_search.best_estimator_)
    19. # 随机搜索模型参数
    20. rd_search = RandomizedSearchCV(model, param_grid, n_iter=200, cv=5, scoring='f1_micro')
    21. rd_search.fit(x, y)
    22. print(rd_search.best_params_)
    23. print(rd_search.best_score_)
    24. print(rd_search.best_estimator_)

    4 贝叶斯优化

    贝叶斯优化(Bayesian Optimization) 与网格/随机搜索最大的不同,在于考虑了历史调参的信息,使得调参更有效率。(但在高维参数空间下,贝叶斯优化复杂度较高,效果会近似随机搜索。)

    图片

    4.1 算法简介

    贝叶斯优化思想简单可归纳为两部分:

    • 高斯过程(GP):以历史的调参信息(Observation)去学习目标函数的后验分布(Target)的过程。

    • 采集函数(AC):由学习的目标函数进行采样评估,分为两种过程:1、开采过程:在最可能出现全局最优解的参数区域进行采样评估。2、勘探过程:兼顾不确定性大的参数区域的采样评估,避免陷入局部最优。

    4.2 算法流程

    1. for循环n次迭代:
    2.     采集函数依据学习的目标函数(或初始化)给出下个开采极值点 Xn+1;
    3.     评估超参数Xn+1得到表现Yn+1;
    4.     加入新的Xn+1、Yn+1数据样本,并更新高斯过程模型;

    图片

    1. """
    2. 随机森林分类Iris使用贝叶斯优化调参
    3. """
    4. import numpy as np
    5. from hyperopt import hp, tpe, Trials, STATUS_OK, Trials, anneal
    6. from functools import partial
    7. from hyperopt.fmin import fmin
    8. from sklearn.metrics import f1_score
    9. from sklearn.ensemble import RandomForestClassifier
    10. def model_metrics(model, x, y):
    11.     """ 评估指标 """
    12.     yhat = model.predict(x)
    13.     return  f1_score(y, yhat,average='micro')
    14. def bayes_fmin(train_x, test_x, train_y, test_y, eval_iters=50):
    15.     """
    16.     bayes优化超参数
    17.     eval_iters:迭代次数
    18.     """
    19.     
    20.     def factory(params):
    21.         """
    22.         定义优化的目标函数
    23.         """
    24.         fit_params = {
    25.             'max_depth':int(params['max_depth']),
    26.             'n_estimators':int(params['n_estimators']),
    27.             'max_leaf_nodes'int(params['max_leaf_nodes'])
    28.             }
    29.         # 选择模型
    30.         model = RandomForestClassifier(**fit_params)
    31.         model.fit(train_x, train_y)
    32.         # 最小化测试集(- f1score)为目标
    33.         train_metric = model_metrics(model, train_x, train_y)
    34.         test_metric = model_metrics(model, test_x, test_y)
    35.         loss = - test_metric
    36.         return {"loss": loss, "status":STATUS_OK}
    37.     # 参数空间
    38.     space = {
    39.         'max_depth': hp.quniform('max_depth'1201),
    40.         'n_estimators': hp.quniform('n_estimators'2501), 
    41.         'max_leaf_nodes': hp.quniform('max_leaf_nodes'21001)
    42.             }
    43.     # bayes优化搜索参数
    44.     best_params = fmin(factory, space, algo=partial(anneal.suggest,), max_evals=eval_iters, trials=Trials(),return_argmin=True)
    45.     # 参数转为整型
    46.     best_params["max_depth"] = int(best_params["max_depth"])
    47.     best_params["max_leaf_nodes"] = int(best_params["max_leaf_nodes"])
    48.     best_params["n_estimators"] = int(best_params["n_estimators"])
    49.     return best_params
    50. #  搜索最优参数
    51. best_params = bayes_fmin(train_x, test_x, train_y, test_y, 100)
    52. print(best_params)
  • 相关阅读:
    Bellman-Ford算法
    强烈推荐!超低温冰箱监控教程
    如何用Java+SpringBoot+Vue构建一个靓车汽车销售网站?
    关于使用pytorch-lightning版本过低的一些问题
    Android 四大组件 -- service
    常用胶水介绍
    vi 连线板.
    2023-05-04:用go语言重写ffmpeg的scaling_video.c示例,用于实现视频缩放(Scaling)功能。
    Redis缓存序列化配置
    通过uboot命令开启核隔离
  • 原文地址:https://blog.csdn.net/qq_39312146/article/details/133937571