Python Hydra库使用介绍
本文最后更新于:2022年7月21日 下午
Python Hydra库使用介绍
Python的Hydra
库是一个开源的配置管理库,能够动态创建一个可继承的的配置系统,十分灵活,能够用来管理深度学习中许多的参数。
Hydra库由Facebook开发,文档:Getting started | Hydra,GitHub:facebookresearch/hydra。
为什么要使用Hydra
一般在深度学习中,需要处理很多的配置参数,比如数据集路径、优化器、学习率、模型架构等,目前有的人使用原生的argparse
库来从命令行读入配置、有的人使用json
或者yaml
格式的配置文件、有的人在源代码中写一个类来保存配置、有的人直接使用.py
文件来写配置、还有的大型库(如openmmlab
)自己开发一套配置系统。下面来分析各种方式的优缺点:
方式 | 优点 | 缺点 |
---|---|---|
argparse | Python内置,使用方便 | 一旦需要很多的配置,那命令就会非常长,可能需要额外一个.sh 文件来运行 |
json、yaml配置文件 | 通用配置文件,也拥有对应的内置库,使用方便 | 若要对某个超参数进行消融实验,则要复制一堆整个的文件,然后对某一项进行修改 |
源代码中写一个class、py文件当配置 | 不需要额外操作,直接是python的数据结构,甚至还能使用一些高级语法,也可以通过继承来结构化 | 要进行消融实验还是很麻烦,并且会让代码变得更长,继承也不是很灵活 |
OpenMMLab的Config | 精心设计,功能强大,支持继承,拓展方便 | 不适合用来构建自己的库,需要阅读很多的源代码 |
Hydra | 支持继承,可通过yaml和命令行混合配置,还支持一些动态插值的语法…… | 因为是第三方库,需要进行一定的学习 |
安装
1 |
|
一个简单的使用例子
这个例子改自官方文档,新建一个conf/config.yaml
文件,内容如下:
1 |
|
然后代码里通过装饰器可以得到数据:
1 |
|
输出如下:
1 |
|
简单吧😄
使用继承的简单例子
如图所示构建了一个深度学习中可能出现的例子,在配置文件夹conf
下有一个config2.yaml
是组合的配置文件。一个深度学习代码可能包含backbone
、dataset
、head
等方面的配置,假设我们要使用mnist数据集,用resnet模型,并自定义一个10分类2层的一个分类器,然后指定学习率为1e-3,那在backbone文件夹下就新建一个resnet.yaml
文件,其余同理。
在主文件中要在一开始就写如图中的defaults配置项,表示继承下来的部分,其中key是文件夹的名字,value是具体配置文件的名字,_self_
表示本文件,当某个值存在冲突的时候会根据顺序处理冲突,假如同一个值被多个配置定义了,那更后的一个会覆盖,假如有多个相同的key,那最终key下的配置会被合并。
💚 defaults中的key还可以是一个目录的格式,比如- backbone/v1/v2: vgg
,解析后也是需要.backbone.v1.v2.<proprety>
来获取值。
💚defaults中也可以忽略key,则不添加层次关系。比如- run
,就表示加载进run.yaml
下的配置。
把上面的配置输出如下:
1 |
|
从命令行中获取配置参数
-
假设我在backbone添加了一个新的模型
vgg
,那就是在backbone文件夹下新建一个vgg.yaml
,之后可以通过更改默认配置文件来切换模型——但是,我们也可以直接在命令行中进行切换:1
python main2.py backbone=vgg
-
假如在backbone里提供多个模型,但是不提供默认的模型,需要强制用户手动选择,则不用填defaults,而是在命令行中用
+
来进行选择。(若已有默认,则会报错)1
python main2.py +backbone=vgg
-
假如要覆盖某个具体数值,可以直接在命令行中赋值:
1
2python main2.py learning_rate=1e-4
python main2.py backbone.layer=30 -
假如不确定某个配置项在配置文件中是否存在,则用
++
,若配置项存在则覆盖,若配置项不存在则追加1
python main2.py ++lr=1e-2
Yaml配置中可使用的动态语法
正如官方的这个例子:
1 |
|
可以用${}
来引用其他配置中的值,要注意这个引用的值是绝对路径。
还可以用???
来表示需要用户手动配置的必填值,缺失会报错omegaconf.errors.MissingMandatoryValue
。
需要注意的是,使用这些语法后,只有在使用值的时候才会实时算出对应值来,用print(OmegaConf.to_yaml(cfg)) # 可视化配置
这种语句可视化会发现值还是???
或者${}
。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!