搜索空间压缩

在高维超参数优化中,搜索空间通常包含大量参数,但只有其中一小部分对目标函数有显著影响。 搜索空间压缩 通过一组压缩步骤组成的流水线来降低搜索空间的有效维度,从而使贝叶斯优化更加高效。

OpenBox 内置了一个压缩框架,该框架支持三类压缩:维度选择范围压缩投影变换

快速示例

启用空间压缩最简单的方式是在创建 AdvisorOptimizer 时设置 compressor_type

from openbox import Advisor, space as sp

cs = sp.Space()
for i in range(20):
    cs.add_variable(sp.Real(f'x{i}', -10, 10))

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    compressor_type='llamatune',
    compressor_kwargs={
        'adapter_alias': 'rembo',
        'le_low_dim': 5,
        'max_num_values': 50,
    },
)

压缩流水线

压缩被组织为有序 步骤 的流水线。每个步骤属于以下三类之一,并由一个短字符串标识。

维度选择步骤

根据参数重要性选择参数子集。

字符串

步骤类

描述

d_shap

SHAPDimensionStep

基于 SHAP 特征重要性的参数选择。支持迁移学习。

d_corr

CorrelationDimensionStep

基于 Spearman/Pearson 相关性的参数选择。支持迁移学习。

d_expert

ExpertDimensionStep

基于专家知识的参数选择。

d_adaptive

AdaptiveDimensionStep

在优化过程中自适应调整选择的参数数量。

范围压缩步骤

将参数取值范围缩小到高价值区域。

字符串

步骤类

描述

r_boundary

BoundaryRangeStep

基于均值 ± σ 的边界范围压缩。

r_shap

SHAPBoundaryRangeStep

SHAP 加权的边界范围压缩。支持迁移学习。

r_kde

KDEBoundaryRangeStep

基于核密度估计的范围压缩。支持迁移学习。

r_expert

ExpertRangeStep

由专家指定的参数范围。

投影步骤

将参数空间变换到低维表示。

字符串

步骤类

描述

p_quant

QuantizationProjectionStep

对大范围整数参数进行量化。

p_rembo

REMBOProjectionStep

随机嵌入贝叶斯优化(REMBO)。

p_hesbo

HesBOProjectionStep

基于哈希的子空间贝叶斯优化(HesBO)。

p_kpca

KPCAProjectionStep

核 PCA 投影。

使用 compressor_type 快捷方式

OpenBox 提供了几种 compressor_type 快捷值,可自动构建压缩流水线。

'llamatune' — 量化 + 投影

灵感来自 LlamaTune 方法。 组合量化与可选的 REMBO 或 HesBO 投影。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    compressor_type='llamatune',
    compressor_kwargs={
        'adapter_alias': 'rembo',  # 'rembo'、'hesbo' 或 'none'
        'le_low_dim': 5,           # 低维目标维度
        'max_num_values': 50,      # 量化最大离散值数
    },
)
  • adapter_alias:投影方法。'rembo' 表示 REMBO,'hesbo' 表示 HesBO, 'none' 表示仅量化。

  • le_low_dim:投影后的目标维度。

  • max_num_values:整数参数量化的最大离散值数。

'shap' — SHAP 维度选择 + 边界范围压缩

使用 SHAP 重要性来选择参数,并可选择压缩其取值范围。 需要 transfer_learning_history 从历史数据中计算 SHAP 重要性。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    transfer_learning_history=source_histories,
    compressor_type='shap',
    compressor_kwargs={
        'topk': 10,
        'top_ratio': 0.8,
        'sigma': 2.0,
    },
)
  • topk:保留的最重要参数数量。

  • top_ratio:用于边界估计的最佳配置比例。

  • sigma:边界宽度(均值 ± sigma × 标准差)。

'expert' — 专家知识维度选择

选择由领域专家指定的参数。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    compressor_type='expert',
    compressor_kwargs={
        'expert_params': ['x0', 'x3', 'x7'],
        'top_ratio': 0.9,
        'sigma': 2.0,
    },
)

构建自定义流水线

要实现完全控制,可使用 compressor_type='pipeline' 配合步骤字符串。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    transfer_learning_history=source_histories,
    compressor_type='pipeline',
    compressor_kwargs={
        'step_strings': ['d_shap', 'r_boundary', 'p_rembo'],
        'step_params': {
            'd_shap': {'topk': 10},
            'r_boundary': {'top_ratio': 0.8, 'sigma': 2.0},
            'p_rembo': {'low_dim': 5, 'seed': 42},
        },
    },
)

也可以通过 steps 键传入预构建的步骤对象:

from openbox.compressor import SHAPDimensionStep, BoundaryRangeStep

steps = [
    SHAPDimensionStep(strategy='shap', topk=10),
    BoundaryRangeStep(method='boundary', top_ratio=0.8, sigma=2.0),
]

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    transfer_learning_history=source_histories,
    compressor_type='pipeline',
    compressor_kwargs={'steps': steps},
)

直接构造 Compressor 并传入

也可以直接构造 Compressor 实例,并通过 compressor 参数传给 AdvisorSHAPDimensionStepKDEBoundaryRangeStep 需要历史数据来计算重要性与范围,请像使用 'shap' 快捷方式一样传入 transfer_learning_history

from openbox.compressor import Compressor, SHAPDimensionStep, KDEBoundaryRangeStep

steps = [
    SHAPDimensionStep(strategy='shap', topk=10),
    KDEBoundaryRangeStep(top_ratio=0.8, kde_coverage=0.6),
]
compressor = Compressor(config_space=cs, steps=steps)

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    transfer_learning_history=source_histories,
    compressor=compressor,
)

空间概念

当搜索空间压缩激活时,OpenBox 会使用多个空间:

  • 原始空间 — 用户定义的完整配置空间。

  • 采样空间 — 采集函数优化器用于提出新配置的空间。

  • 代理空间 — 用于代理模型训练和预测的空间,是流水线的最终输出。

  • 反投影空间 — 第一个投影步骤之前的空间,用于将投影后的配置映射回原始空间进行评估。

原始空间
    ↓ [维度选择]
降维空间
    ↓ [范围压缩]
范围压缩空间
    ↓ [投影]
压缩空间
    ├── 采样空间:用于生成新配置
    └── 代理空间:用于模型训练

自适应压缩

AdaptiveDimensionStep 可以根据更新策略在优化过程中动态调整所选参数的数量。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    compressor_type='pipeline',
    compressor_kwargs={
        'step_strings': ['d_adaptive'],
        'step_params': {
            'd_adaptive': {
                'importance_calculator': 'shap',
                'update_strategy': 'periodic',
                'update_strategy_kwargs': {'period': 10},
                'initial_topk': 15,
                'reduction_ratio': 0.2,
                'min_dimensions': 5,
            },
        },
    },
)

在优化循环中触发自适应更新:

for i in range(max_iter):
    config = advisor.get_suggestion()
    result = objective(config)
    observation = Observation(config=config, objectives=result['objectives'])
    advisor.update_observation(observation)

    updated = advisor.update_compression(advisor.history)
    if updated:
        print(f'第 {i} 次迭代时压缩策略已更新')

更新策略

策略

行为

'periodic'

每 N 次迭代更新一次,减少维度。

'stagnation'

优化停滞时增加维度。

'improvement'

连续改善后减少维度。

'hybrid'

组合周期性、停滞和改善策略。

与迁移学习的集成

空间压缩与迁移学习自然配合。当提供 transfer_learning_history 时,压缩器会使用源任务数据来:

  1. 计算参数重要性(用于 SHAP/相关性维度选择)。

  2. 估计取值范围(用于边界/KDE 范围压缩)。

  3. 将源任务历史转换到压缩空间,供代理模型使用。

advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    transfer_learning_history=source_histories,
    surrogate_type='tlbo_rgpe_gp',
    compressor_type='shap',
    compressor_kwargs={'topk': 10, 'top_ratio': 0.8},
)