OmegaConf——配置文件管理助手
摘要
本文介绍了OmegaConf
库的安装、创建配置对象的方法、参数的使用技巧,包括参数调用、新增和删除键值对、配置文件合并及值引用等,展示了其在复杂项目配置管理中的强大功能。[本摘要由小猫AI生成]
什么是OmegaConf
在执行机器学习、深度学习任务的过程中,我们常常需要提供一些不同的配置参数来适应不同的运行环境、调试不同的超参数,从而来完成不同条件下的实验。在python
环境中,尽管argparse
库已经为实验者的参数配置提供了很大的便捷,但其参数配置过程对于命令行的依赖在面对相对复杂的大型项目时将显得十分吃力。
与argparse
库相比,OmegaConf
提供了一种更为灵活的参数配置方式,支持YAML
配置文件、对象、CLI
参数等多种形式。在使用上,它具有巨大的潜力:
YAML
格式:OmegaConf
默认支持YAML
文件,这使得配置文件更加易读且易于编辑,而不仅仅是简单的键值对。
- 层次结构:
OmegaConf
支持创建复杂的配置对象,可以方便地管理嵌套的字典结构,这在处理具有多个层级的复杂配置文件时非常有用。
- 类型安全:
OmegaConf
支持类型注解,可以指定配置项的数据类型,并在加载时进行类型检查,减少了运行时错误的可能性。
- 合并配置:
OmegaConf
提供了配置文件的合并功能,允许用户从一个或多个YAML
文件中加载配置,并将它们合并成一个单一的配置对象。
CLI
覆盖:允许通过命令行参数覆盖配置文件中的某些值,而无需重新定义整个配置。
- 动态性:可以在运行时修改配置对象中的值,这在调试和实验不同的配置设置时非常有用。
在下文中,将详细介绍OmegaConf
的使用方式,并实现简单的文件配置实例。
OmegaConf的安装
使用pip
对OmegaConf
库进行安装,在这里使用清华源镜像进行安装。
pip install omegaconf -i https://pypi.tuna.tsinghua.edu.cn/simple
在使用前,先导入OmegaConf
对应的库。
from omegaconf import OmegaConf
OmegaConf类的创建
在本章中,将简要介绍OmegaConf
类的几种常用创建方式:直接创建OmegaConf
类对象、由python
字典创建OmegaConf
对象、从YAML
文件创建OmegaConf
对象、从dataclass
类创建OmegaConf
对象以及从命令行参数创建OmegaConf
对象。
- 创建方式一:直接创建
OmegaConf
类对象
使用create
函数可以创建一个空的OmegaConf
类。
omegaconf = OmegaConf.create()
print(omegaconf)
运行结果:
{}
- 创建方式二:由
python
字典创建OmegaConf
对象
由于配置参数本质是若干对键值对,因此在初始化OmegaConf
对象时可以从字典对象进行创建。
omegaconf_fromdic = OmegaConf.create({"version":1.0, "name":"test_dic", "args":[{"epoch":20, "lr":0.1}]})
print(omegaconf_fromdic)
运行结果:
{'version': 1.0, 'name': 'test_dic', 'args': [{'epoch': 20, 'lr': 0.1}]}
- 创建方式三:从
YAML
文件创建OmegaConf
对象
OmegaConf
最大的优势在于从YAML
配置文件中直接读取参数,从而能够更加便捷地记录和修改复杂项目中多次实验的参数。现创建parameters.yaml
文件,并由该文件直接创建OmegaConf
对象,文件内容如下:
version: 2.0
name: "test_yaml"
args:
epoch: 10
lr: 0.1
batchsize: ???
file_path = "./parameters.yaml"
omegaconf_fromyaml = OmegaConf.load(file_path)
print(omegaconf_fromyaml)
运行结果:
{'version': 2.0, 'name': 'test_yaml', 'args': {'epoch': 10, 'lr': 0.1, 'batchsize': '???'}}
- 创建方式四:从
dataclass
类创建OmegaConf
对象
OmegaConf
类还支持从dataclass
类中创建对象。
from dataclasses import dataclass
@dataclass
class Config:
version: float=3.0
name: str="test_dataclass"
arg: int=1
omegaconf_fromdataclass = OmegaConf.structured(Config(arg=2))
print(omegaconf_fromdataclass)
运行结果:
{'version': 3.0, 'name': 'test_dataclass', 'arg': 2}
- 创建方式五:从命令行参数创建
OmegaConf
对象
在运行时,可以通过命令行参数来创建OmegaConf
类。采用from_cli
函数来接收命令行指定的参数和值,并创建OmegaConf
对象。新建test1.py
,内容如下:
from omegaconf import OmegaConf
omegaconf = OmegaConf.from_cli()
print(omegaconf)
使用命令行来运行该文本:
python test1.py version=3.0 name="test_cli"
运行结果:
{'version': 3.0, 'name': 'test_cli'}
OmegaConf参数的使用
在本章中,将基于上文 创建方式三:从YAML
文件创建OmegaConf
对象 展开对OmegaConf
参数使用的介绍,包含参数调用、指定必填参数、新增键值对、删除键值对、合并配置文件、将参数存入YAML
文件以及值引用这几个模块的介绍。
- 参数调用
与python
字典不同的是,OmegaConf
对象使用.
运算符来调用参数。
file_path = "./parameters.yaml"
omegaconf = OmegaConf.load(file_path)
print(omegaconf.name)
运行结果:
test_yaml
对于二级键值对下的参数,可以使用链式调用的方式进行调用。
print(omegaconf.args.epoch)
运行结果:
10
对OmegaConf
对象而言,.
运算符并非是以只读的方式进行访问,它同样可以实现对参数的修改。
omegaconf.name="modified"
print(omegaconf)
运行结果:
{'version': 2.0, 'name': 'modified', 'args': {'epoch': 10, 'lr': 0.1, 'batchsize': '???'}}
- 指定必填参数
在YAML
配置文件中,并非所有值都具有默认值,我们可以使用???
来表示一个必填参数,当改参数在指定数值之前被调用,则会抛出异常信息。
print(omegaconf.batchsize)
运行结果:
ConfigAttributeError: Missing key batchsize
我们需要对必填参数进行赋值后,再调用改参数。
omegaconf.batchsize = 32
print(omegaconf.batchsize)
运行结果:
32
- 新增键值对
通过.
运算符,我们可以直接实现键值对的新增。
omegaconf.args.alpha = 0.5
print(omegaconf.args)
运行结果:
{'epoch': 10, 'lr': 0.1, 'batchsize': '???', 'alpha': 0.5}
但是,跨两级进行键值对的新增是非法的,我们应先新增父目录的键值对,再新增子目录的键值对。
omegaconf.test_arg.alpha = 0.5 # 该行为非法
omegaconf.test_arg = {}
omegaconf.test_arg.alpha = 0.5
print(omegaconf.test_arg)
运行结果:
{'alpha': 0.5}
此外,也可以使用update
函数对多级键值对进行更新,其中应将force_add
参数置为True
。
OmegaConf.update(omegaconf, "a.b", 10, force_add=True)
print(OmegaConf.to_yaml(omegaconf)) # 转换成yaml对象后输出
运行结果:
version: 2.0
name: modified
args:
epoch: 10
lr: 0.1
batchsize: ???
alpha: 0.5
batchsize: 32
test_arg:
alpha: 0.5
a:
b: 10
- 删除键值对
我们可以通过del
函数来实现键值对的删除。
del omegaconf.a
print(OmegaConf.to_yaml(omegaconf))
运行结果:
version: 2.0
name: modified
args:
epoch: 10
lr: 0.1
batchsize: ???
alpha: 0.5
batchsize: 32
test_arg:
alpha: 0.5
- 合并多个配置文件
OmegaConf
可以使用merge
函数来实现多个配置文件参数的合并。新建server_config.yaml
文件,内容如下:
server:
port:80
username: ye
对parameters.yaml
和server_config.yaml
文件参数进行合并。
file_path2 = "server_config.yaml"
omegaconf2 = OmegaConf.load(file_path2)
merged_conf = OmegaConf.merge(omegaconf, omegaconf2)
print(OmegaConf.to_yaml(merged_conf))
运行结果:
version: 2.0
name: modified
args:
epoch: 10
lr: 0.1
batchsize: ???
alpha: 0.5
batchsize: 32
test_arg:
alpha: 0.5
server: port:80
username: ye
- 将参数存入
YAML
文件
完成参数更新后,同样可以将参数存入YAML
文件中。
with open("merged_config.yaml", 'w') as fp:
OmegaConf.save(config=merged_conf, f=fp)
- 值的引用
在YAML
配置文件内部,可以使用$
运算符来实现文件内部值的相互引用。将server_config.yaml
的内容进行以下修改,再次加载OmegaConf
类,即可实现值的引用:
server:
port: 80
host: localhost
username: ye
url: http://${server.host}:${server.port}/
omegaconf2 = OmegaConf.load(file_path2)
print(omegaconf2.url)
运行结果:
http://localhost:80/
然而,值引用的解析是一种懒解析,当且仅当调用需要解析的内容时,才会对引用内容进行拆包,否则将不会执行解析。当我们直接打印OmegaConf
对象时,引用内容并不会被解析。
print(OmegaConf.to_yaml(omegaconf2))
运行结果:
server:
port: 80
host: localhost
username: ye
url: http://${server.host}:${server.port}/
为了强制对值引用进行解析,我们可以使用resolve
函数手动解析后再次打印对象。这样,所有值引用都会被拆包替换,直接得到我们想要的结果。
OmegaConf.resolve(omegaconf2)
print(OmegaConf.to_yaml(omegaconf2))
运行结果:
server:
port: 80
host: localhost
username: ye
url: http://localhost:80/