基于hydra库实现yaml配置文件的读取(支持命令行参数)

前几天博主研究了argparse库的使用,发现较为方便。但是应对参数较多的场景时,在命令行里修改参数就变得较为麻烦。因此转向了对配置文件的使用,yaml是一个开放性的配置文件格式。使用yaml库加载不支持命令行参数,使用hydra库加载配置文件时可以支持命令行参数(实现对默认配置的新增、修改与删除)。

hydra对于yaml配置文件中支持的格式有:str、int、float、bool、list这5种格式,完全满足一般项目的基本配置了。

安装hydra

pip install hydra-core

yaml配置文件

yaml配置文件的简易写法如下所示,以下配置中分别测试了str、int、float、bool、list的各种写法。比如str测试了带‘’和不带‘’,float测试了直接表示和科学计算法表示。将以下配置文件保存到config目录(自己创建一个)下的config.yaml中

batch_size: 32
lr: 1e-4
epoch: 5e+3
decay: -0.1204
input_shape: [256,256]
test: false
bacbbone: resnet50
pretrain: 'mymodel/epoch20 iou92.23.h5'

yaml配置文件读取

使用以下代码就可以快速的从config目录下加载配置文件config.yaml,由配置@hydra.main(config_path=“config”, config_name=“config.yaml”)所指定

import hydra
from omegaconf import DictConfig, OmegaConf,open_dict
from pathlib import Path
import yaml
import os
@hydra.main(config_path="config", config_name="config.yaml")
def main(config):
	print('all config:',config)
if __name__ == "__main__":
    main()

将以上代码保存为main.py,在控制台执行python main.py,输出如下所示,可见hydra是支持多个参数的写法的。

all config: {
    
    'batch_size': 32, 'lr': 0.0001, 'epoch': 5000.0, 'decay': -0.1204, 'input_shape': [256, 256], 'test': False, 'bacbbone': 'resnet50', 'pretrain': 'mymodel/epoch20 iou92.23.h5'}

在命令行实现参数的修改新增

在下面的参数中实现了配置项的新增,修改与删除
新增:+ ,+user1=ua1表示添加参数user1,其值为ua1
修改:直接赋值或 ++,lr=0.1 表示赋值lr为0.1,++batch_size=64表示如果存在batch_size就修改其值为64;如果不存在batch_size配置则新增,且赋值为64
删除:~ ,~epoch表示删除参数epoch
以下代码实现了参数的新增、修改与删除,涉及到str、bool、int、float、list的赋值

python main.py +user1=ua1 +pwd1=1 +ss=true +lid=[1,2,3,4] lr=0.1 ++batch_size=64 ~epoch

通过调整,此时代码的输出如下所示,可以明显的看到新增了一些参数,lr与batch_size的值被修改,参数epoch的值被删除

all config: {
    
    'batch_size': 64, 'lr': 0.1, 'decay': -0.1204, 'input_shape': [256, 256], 
'test': False, 'bacbbone': 'resnet50', 'pretrain': 'mymodel/epoch20 iou92.23.h5',
 'user1': 'ua1', 'pwd1': 1, 'ss': True, 'lid': [1, 2, 3, 4]}

在代码中实现配置的修改

在下面代码的main函数中,博主实现了配置的访问,修改key(新增与删除),修改value的案例。同时,博主还测试了使用yaml库加载yaml文件,通过对比可以发现yaml库对参数写法的支持是有限,不够灵活。

import hydra
from omegaconf import DictConfig, OmegaConf,open_dict
from pathlib import Path
import yaml
import os
    
@hydra.main(config_path="config", config_name="config.yaml")
def main(config):
    running_dir = str(hydra.utils.get_original_cwd())
    working_dir = str(Path.cwd())
    print(f"The current running directory is {
      
      running_dir}")
    print(f"The config save directory is {
      
      working_dir}")
    
    #访问config
    print("\n 访问config中的key")
    print(f"The batch size is {
      
      config.batch_size}")
    print(f"The learning rate is {
      
      config['lr']}")
    print('all config:',config)
    
    #修改config的key
    print("\n 修改config中的key")
    OmegaConf.set_struct(config, True)
    with open_dict(config):
        #新增配置
        config['new_lr']=123
        #删除配置
        del config['lr']
    print('all config:',config)
        
    #修改config的值
    print("\n 修改config中特定key的value")
    config.batch_size=1111
    config['input_shape']=[640,640]
    print(f"The batch size is {
      
      config.batch_size}")
    print(f"The input_shape is {
      
      config['input_shape']}")
    
    
    #输出
    print('\n config中所有的key',dir(config))
    
#解释+新增(yaml文件中不存在),~删除(yaml文件中存在的某个键值对),++(yaml文件中)存在则覆盖,不存在则新增
#python main.py +user1=ua1 +pwd1=1 +ss=true +lid=[1,2,3,4] lr=0.1 ++batch_size=64
if __name__ == "__main__":
    main()
    records_info = yaml.load(open("config/config.yaml", encoding='utf8').read(), yaml.FullLoader)
    print("yaml.load:\n")
    print('config:',type(records_info))
    print('config:',records_info.keys())
    print('config:',records_info)
    
    #conf = OmegaConf.create({"compose": {"_target_": "albumentations.Compose", "_recursive_": True, "transforms": [{"_target_": "albumentations.Rotate", "limit": 10}, {"_target_": "albumentations.ToGray", "p": 1}]}})
    #print(OmegaConf.to_yaml(conf))
    #comp=hydra.utils.instantiate(conf.compose)

上述代码执行输出结果如下所示

访问config中的key
The batch size is 64
The learning rate is 0.1
all config: {‘batch_size’: 64, ‘lr’: 0.1, ‘decay’: -0.1204, ‘input_shape’: [256, 256], ‘test’: False, ‘bacbbone’: ‘resnet50’, ‘pretrain’: ‘mymodel/epoch20 iou92.23.h5’, ‘user1’: ‘ua1’, ‘pwd1’: 1, ‘ss’: True, ‘lid’: [1, 2, 3, 4]}


修改config中的key all config: {'batch_size': 64, 'decay': -0.1204, 'input_shape': [256, 256], 'test': False, 'bacbbone': 'resnet50', 'pretrain': 'mymodel/epoch20 iou92.23.h5', 'user1': 'ua1', 'pwd1': 1, 'ss': True, 'lid': [1, 2, 3, 4], 'new_lr': 123}
修改config中特定key的value
The batch size is 1111
The input_shape is [640, 640]

config中所有的key ['bacbbone', 'batch_size', 'decay', 'input_shape', 'lid', 'new_lr', 'pretrain', 'pwd1', 'ss', 'test', 'user1'] yaml.load:
config: class 'dict'
config: dict_keys(['batch_size', 'lr', 'epoch', 'decay', 'input_shape', 'test', 'bacbbone', 'pretrain'])
config: {'batch_size': 32, 'lr': '1e-4', 'epoch': '5e+3', 'decay': -0.1204, 'input_shape': [256, 256], 'test': False, 'bacbbone': 'resnet50', 'pretrain': 'mymodel/epoch20 iou92.23.h5'}

猜你喜欢

转载自blog.csdn.net/a486259/article/details/125897007