从 Hydra 迁移指南
本指南帮助你将现有项目从 Hydra 迁移到 Hyperparameter。我们将介绍两者的关键差异,并提供对照示例。
为什么要迁移?
| 方面 | Hydra | Hyperparameter |
|---|---|---|
| 性能 | 纯 Python(循环中较慢) | Rust 后端(快 6-850 倍) |
| 依赖 | 重型(antlr4, omegaconf 等) | 极简(仅需 toml) |
| 配置风格 | 自上而下(到处传递 cfg) |
自下而上(注入到函数中) |
| 作用域 | 静态(启动时组装) | 动态(运行时可变) |
快速对比
定义参数
Hydra:
# config.yaml
model:
hidden_size: 256
dropout: 0.1
# main.py
import hydra
from omegaconf import DictConfig
@hydra.main(config_path=".", config_name="config")
def main(cfg: DictConfig):
print(cfg.model.hidden_size) # 256
Hyperparameter:
# config.toml
[model]
hidden_size = 256
dropout = 0.1
# main.py
import hyperparameter as hp
@hp.param("model")
def build_model(hidden_size=128, dropout=0.0):
print(hidden_size) # 256 (来自配置文件)
if __name__ == "__main__":
cfg = hp.config("config.toml")
with hp.scope(**cfg):
build_model()
配置组合(多文件)
Hydra:
# config.yaml
defaults:
- model: resnet
- dataset: imagenet
- _self_
# model/resnet.yaml
name: resnet50
layers: 50
Hyperparameter:
import hyperparameter as hp
# 加载并合并多个配置(后面的文件覆盖前面的)
cfg = hp.config(["base.toml", "model/resnet.toml", "dataset/imagenet.toml"])
with hp.scope(**cfg):
train()
变量插值
Hydra (OmegaConf):
Hyperparameter:
两者都支持相同的 ${key} 语法!
Schema 校验
Hydra (使用 dataclass):
from dataclasses import dataclass
from hydra.core.config_store import ConfigStore
@dataclass
class ModelConfig:
hidden_size: int = 256
dropout: float = 0.1
cs = ConfigStore.instance()
cs.store(name="model_config", node=ModelConfig)
Hyperparameter:
from dataclasses import dataclass
import hyperparameter as hp
@dataclass
class ModelConfig:
hidden_size: int = 256
dropout: float = 0.1
# 直接校验,无需 ConfigStore
cfg = hp.config("config.toml", schema=ModelConfig)
print(cfg.hidden_size) # IDE 自动补全可用!
命令行覆盖
Hydra:
Hyperparameter:
python train.py -D model.hidden_size=512 -D model.dropout=0.2
# 或配合配置文件:
python train.py -C config.toml -D model.hidden_size=512
动态作用域(Hyperparameter 独有)
这是 Hydra 很难做到的:
import hyperparameter as hp
@hp.param("layer")
def create_layer(dropout=0.1):
return f"Layer with dropout={dropout}"
# 不同层使用不同的 dropout —— 无需修改代码!
with hp.scope(**{"layer.dropout": 0.1}):
layer1 = create_layer() # dropout=0.1
with hp.scope(**{"layer.dropout": 0.5}):
layer2 = create_layer() # dropout=0.5
迁移清单
- [ ] 配置文件: 将 YAML 转换为 TOML/JSON(或安装 PyYAML 后继续使用 YAML)
- [ ] 装饰器: 将
@hydra.main替换为@hp.param+hp.launch() - [ ] 配置访问: 将
cfg.x.y替换为hp.scope.x.y | default或函数注入 - [ ] 配置组合: 将
defaults列表替换为hp.config([file1, file2]) - [ ] 变量插值: 相同的
${key}语法可直接使用 - [ ] 命令行: 将位置参数覆盖替换为
-D key=value
你将获得
- 性能提升: 动态访问快 6 倍,注入模式快 850 倍
- 简洁性: 无需 ConfigStore,无需
@hydra.main样板代码 - 灵活性: 动态作用域,适应复杂控制流
- 轻量级: 更少依赖,更快启动
你将暂时失去
- Sweeper 插件: 无内置 Optuna/Ax 集成(但可轻松手动实现)
- Launcher 插件: 无 SLURM/submitit 集成
- 输出管理: 无自动
outputs/date/time目录 - Tab 补全: 无配置选项的 Shell 自动补全
这些功能可能会根据社区反馈在未来版本中添加。