• OpenBox(一个高效通用的黑盒优化系统)安装与使用


    黑盒优化

    黑盒优化(BBO)任务的目标是在有限的评估预算内对黑盒目标函数进行优化。 这里的’‘黑盒’’指的是目标函数不具备可分析的性质,因此我们不能使用目标函数的导数等信息。 评估目标函数的代价往往是十分昂贵的。黑盒优化的目标就是尽可能快地找到一个配置,在这个配置下目标函数接近全局最优。

    传统的单目标黑盒优化有很多应用场景,包括;

    • 自动化A/B测试

    • 实验设计

    • 数据库参数调优

    • 自动化超参数调优

    最近,通用的黑盒优化方法已经出现,并应用于众多领域:

    • 处理器体系结构和电路设计

    • 资源分配

    • 自动化化学设计

    通用的黑盒优化方法需要支持更多的传统黑盒优化方法所不支持的功能,比如多目标优化和带约束条件的优化。

    设计原则

    OpenBox是一个高效的通用黑盒优化系统。它的设计有如下特点:

    • 易于使用: 尽可能减少用户干预,使用用户友好的可视化界面来追踪和管理BBO任务。

    • 性能稳定: 支持最新的优化算法。可以自动选择合适的优化算法。

    • 资源管理: 向用户提供基于模型的使用预算的建议,例如,最小化资源预算。

    • 可扩展性: 对输入变量的维度、目标数、任务数、测试数、以及并行度具有可扩展性。

    • 高效性: 能够有效利用并行资源。支持基于迁移学习和多精度的优化方法。

    • 高容错性, 支持任务广泛, 数据隐私保护,…

    下图展示了OpenBox服务的系统概览。

    在这里插入图片描述

    主要组成部分:

    • Service Master 负责节点管理,负载均衡以及容错。

    • Task Database 保存所有任务的历史信息和历史状态。

    • Suggestion Server 给每个任务生成新的配置。

    • REST API 使用RESTful APIs来连接Workers和Suggestion Service。

    • Evaluation workers 由用户拥有和定义任务。

    openbox安装

    要求Python版本大于等于3.7

    conda create -n openbox python=3.7
    conda activate openbox
    pip install openbox
    
    • 1
    • 2
    • 3

    或者使用源码手动安装,源码地址:https://github.com/PKU-DAIR/open-box

    git clone https://github.com/PKU-DAIR/open-box.git && cd open-box
    pip install .
    
    • 1
    • 2

    快速入门

    1.空间定义

    首先定义一个搜索空间。

    from openbox import space as sp
    
    # Define Search Space
    space = sp.Space()
    x1 = sp.Real("x1", -5, 10, default_value=0)
    x2 = sp.Real("x2", 0, 15, default_value=0)
    space.add_variables([x1, x2])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这个例子中,我们创建了一个空的搜索空间,而后向它内部添加了两个实数型(浮点型)变量。 第一个变量 x1 的取值范围是-5到10,第二个变量 x2 的取值范围是0到15。

    OpenBox也支持其它类型的变量。 下面是定义整型和类别型变量的方法:

    from openbox import space as sp
    
    i = sp.Int("i", 0, 100) 
    kernel = sp.Categorical("kernel", ["rbf", "poly", "sigmoid"], default_value="rbf")
    
    • 1
    • 2
    • 3
    • 4

    2.定义优化目标

    第二步,定义要优化的目标函数。 注意, OpenBox 默认 最小化 目标函数。 这里我们提供了 Branin 函数的例子。

    import numpy as np
    
    # Define Objective Function
    def branin(config):
        x1, x2 = config['x1'], config['x2']
        y = (x2-5.1/(4*np.pi**2)*x1**2+5/np.pi*x1-6)**2+10*(1-1/(8*np.pi))*np.cos(x1)+10
        return {'objectives': [y]}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    目标函数的输入是一个从搜索空间采样的配置点,输出为目标值。

    3.优化

    在定义了搜索空间和目标函数后,我们可以运行优化过程:

    from openbox import Optimizer
    
    # Run
    opt = Optimizer(
        branin,
        space,
        max_runs=50,
        surrogate_type='gp',
        task_id='quick_start',
        # Have a try on the new HTML visualization feature!
        # visualization='advanced',   # or 'basic'. For 'advanced', run 'pip install "openbox[extra]"' first
        # auto_open_html=True,        # open the visualization page in your browser automatically
    )
    history = opt.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这里我们创建了一个 Optimizer 实例,传入目标函数 branin 和搜索空间 space。 其余参数的含义是:

    • num_objectives=1 和 num_constraints=0 表明我们的 branin 函数返回一个没有约束条件的单目标值。

    • max_runs=50 表示优化过程共50轮 (优化目标函数50次)。

    • surrogate_type=‘gp’: 对于数学问题,我们推荐用高斯过程 (‘gp’) 作为贝叶斯优化的代理模型。 对于实际的问题,例如超参数优化 (HPO),我们推荐用随机森林 (‘prf’)。

    • task_id 被用来区别不同优化过程。

    • visualization: ‘none’, ‘basic’ 或 ‘advanced’。

    • auto_open_html: 是否自动在浏览器中打开可视化网页。

    接下来,调用 opt.run() 启动优化过程。

    4.可视化

    在优化完成后, opt.run() 返回优化的历史信息。 可以通过调用 print(history) 来看结果:

    print(history)
    
    • 1
    +-------------------------+-------------------+
    | Parameters              | Optimal Value     |
    +-------------------------+-------------------+
    | x1                      | -3.138277         |
    | x2                      | 12.254526         |
    +-------------------------+-------------------+
    | Optimal Objective Value | 0.398096578033325 |
    +-------------------------+-------------------+
    | Num Configs             | 50                |
    +-------------------------+-------------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    调用 history.plot_convergence() 来可视化优化过程:

    import matplotlib.pyplot as plt
    history.plot_convergence(true_minimum=0.397887)
    plt.show()
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    调用 print(history.get_importance()) 来输出参数的重要性:

    print(history.get_importance())
    
    • 1
    +------------+------------+
    | Parameters | Importance |
    +------------+------------+
    | x1         | 0.488244   |
    | x2         | 0.327570   |
    +------------+------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    XGBoost调参

    1.定义超参数空间

    from openbox.utils.config_space import ConfigurationSpace
    from openbox.utils.config_space import UniformFloatHyperparameter, UniformIntegerHyperparameter
    
    def get_config_space():
        cs = ConfigurationSpace()
        n_estimators = UniformIntegerHyperparameter("n_estimators", 100, 1000, q=50, default_value=500)
        max_depth = UniformIntegerHyperparameter("max_depth", 1, 12)
        learning_rate = UniformFloatHyperparameter("learning_rate", 1e-3, 0.9, log=True, default_value=0.1)
        min_child_weight = UniformFloatHyperparameter("min_child_weight", 0, 10, q=0.1, default_value=1)
        subsample = UniformFloatHyperparameter("subsample", 0.1, 1, q=0.1, default_value=1)
        colsample_bytree = UniformFloatHyperparameter("colsample_bytree", 0.1, 1, q=0.1, default_value=1)
        gamma = UniformFloatHyperparameter("gamma", 0, 10, q=0.1, default_value=0)
        reg_alpha = UniformFloatHyperparameter("reg_alpha", 0, 10, q=0.1, default_value=0)
        reg_lambda = UniformFloatHyperparameter("reg_lambda", 1, 10, q=0.1, default_value=1)
        cs.add_hyperparameters([n_estimators, max_depth, learning_rate, min_child_weight, subsample, colsample_bytree, gamma, reg_alpha, reg_lambda])
        return cs
    
    config_space = get_config_space()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.定义目标函数

    目标函数输入为模型超参数,返回值为模型平衡错误率。

    from sklearn.model_selection import train_test_split
    from sklearn.datasets import load_digits
    from sklearn.metrics import balanced_accuracy_score
    from xgboost import XGBClassifier
    
    # prepare your data
    X, y = load_digits(return_X_y=True)
    x_train, x_val, y_train, y_val = train_test_split(X, y, test_size=0.2, stratify=y, random_state=1)
    
    def objective_function(config):
        # convert Configuration to dict
        params = config.get_dictionary()
    
        # fit model
        model = XGBClassifier(**params, use_label_encoder=False)
        model.fit(x_train, y_train)
    
        # predict and calculate loss
        y_pred = model.predict(x_val)
        loss = 1 - balanced_accuracy_score(y_val, y_pred)  # OpenBox minimizes the objective
    
        # return result dictionary
        result = dict(objs=(loss, ))
        return result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3.执行优化

    定义好任务和目标函数以后,就可以调用OpenBox贝叶斯优化框架SMBO执行优化。我们设置优化轮数(max_runs)为100,代表将对XGBoost模型调参100轮。每轮最大验证时间(time_limit_per_trial)设置为180秒,超时的任务将被终止。优化结束后,可以打印优化结果。

    from openbox.optimizer.generic_smbo import SMBO
    bo = SMBO(objective_function,
              config_space,
              max_runs=100,
              time_limit_per_trial=180,
              task_id='tuning_xgboost')
    history = bo.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.可视化

    打印优化结果如下:

    print(history)
    
    +------------------------------------------------+
    | Parameters              | Optimal Value        |
    +-------------------------+----------------------+
    | colsample_bytree        | 0.200000             |
    | gamma                   | 0.000000             |
    | learning_rate           | 0.367678             |
    | max_depth               | 6                    |
    | min_child_weight        | 0.400000             |
    | n_estimators            | 800                  |
    | reg_alpha               | 6.700000             |
    | reg_lambda              | 4.300000             |
    | subsample               | 0.900000             |
    +-------------------------+----------------------+
    | Optimal Objective Value | 0.025083655083655065 |
    +-------------------------+----------------------+
    | Num Configs             | 100                  |
    +-------------------------+----------------------+
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    我们可以绘制收敛曲线,进一步观察结果。

    history.plot_convergence()
    
    • 1

    在这里插入图片描述

    依据此次任务分析超参数重要性如下:

    print(history.get_importance())
    
    +--------------------------------+
    | Parameters        | Importance |
    +-------------------+------------+
    | gamma             | 0.254037   |
    | n_estimators      | 0.081189   |
    | subsample         | 0.076776   |
    | colsample_bytree  | 0.071582   |
    | reg_lambda        | 0.065959   |
    | learning_rate     | 0.052264   |
    | max_depth         | 0.035927   |
    | min_child_weight  | 0.026388   |
    | reg_alpha         | 0.015302   |
    +-------------------+------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    参考

    论文地址:https://arxiv.org/abs/2106.00421
    文档地址:https://open-box.readthedocs.io/zh-cn/latest/index.html

  • 相关阅读:
    查找已注册的 Spring Security 过滤器
    CRM系统销售自动化功能如何提高销售效率
    AOP、IOC、注解、反射
    java 企业工程管理系统软件源码 自主研发 工程行业适用
    【JavaScript】JavaScript 运算符 ① ( 运算符分类 | 算术运算符 | 浮点数 的 算术运算 精度问题 )
    基于python的驾校管理系统的设计与实现
    PMP每日一练 | 考试不迷路-12.5(包含敏捷+多选)
    go的iris框架进行接收post请求参数获取与axios(vue)的数据传入
    vue自定义全局指令v-emoji限制input输入表情和特殊字符
    vscode键盘输入不进去
  • 原文地址:https://blog.csdn.net/weixin_43912621/article/details/134027355