1 Yaml

1.1 Yaml文件

首先新建一个test.yaml文件,文件内容如下

phase: train
dataset: mydataset

optimizer_args:
    optimizer: Adam
    base_lr: 0.0001
    step: [ 20, 35]
    learning_ratio: 1
    weight_decay: 0.0001
    start_epoch: 0

请注意,yaml对大小写敏感,使用缩进来表示层次关系,这一点与python相同,一个缩进可以是2个空格或者4个空格,注意不要使用tab键代替空格,上面这份配置文件等价于python中的字典。

1.1.1 yaml的基本数据类型

yaml中有以下基本数据类型

  • 字符串 str
  • 整型 int
  • 浮点型 float
  • 布尔型 boolean
  • null null
  • 时间
  • 日期

示例:

# 这个例子输出一个字典,其中value包括所有基本类型
str: "Hello World!"
int: 110
float: 3.141
boolean: true  # or false
None: null  # 也可以用 ~ 号来表示 null
time: 2016-09-22t11:43:30.20+08:00  # ISO8601,写法百度
date: 2016-09-22  # 同样ISO8601

python输出

{'str': 'Hello World!', 'int': 110, 'float': 3.141, 'boolean': True, 'None': None, 'time': datetime.datetime(2016, 9, 22, 11, 43, 30, 200000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800))), 'date': datetime.date(2016, 9, 22)}

1.1.2 数据类型强制转换

yaml支持数据类型强制转换,使用!!操作符,

例如

str: !!str 3.14
int: !!int "123"

python输出

{'str': '3.14', 'int': 123}

上述yaml内容中的3.14从float型被强制转换为str类型,"123"从字符串强制转换为int类型。

1.1.3 yaml与python数据对象的映射

(1) yaml映射为字典

如果yaml文件内容是键值对格式,那么会在python中映射为字典

phase: train
dataset: mydataset
model : ResNet18

python输出

{'phase': 'train', 'dataset': 'mydataset', 'model': 'ResNet18'}

(2) yaml映射为字典嵌套字典

如果yaml文件内容是键值对嵌套键值对格式,那么会在python中映射为字典嵌套字典

type1:
    phase: train
    dataset: mydataset
    model : ResNet18
type2:
    phase: train
    dataset: mydataset
    model : VGG

python输出

{'type1': {'phase': 'train', 'dataset': 'mydataset', 'model': 'ResNet18'}, 'type2': {'phase': 'train', 'dataset': 'mydataset', 'model': 'VGG'}}

(3) yaml映射为字典嵌套列表

如果yaml文件内容是键值对嵌套数组格式,那么会在python中映射为字典嵌套列表

type1:
    - train
    - mydataset
    - ResNet18
type2:
    - train
    - mydataset
    - VGG

python输出

{'type1': ['train', 'mydataset', 'ResNet18'], 'type2': ['train', 'mydataset', 'VGG']}

(4) yaml映射为列表

如果yaml文件内容是数组格式,那么会在python中映射为列表

- train
- mydataset
- ResNet18

python输出

['train', 'mydataset', 'ResNet18']

(5) yaml映射为列表嵌套字典

如果yaml文件内容是数组嵌套键值对格式,那么会在python中映射为列表嵌套字典

- phase: train
- dataset: mydataset
- model : ResNet18

python输出

[{'phase': 'train'}, {'dataset': 'mydataset'}, {'model': 'ResNet18'}]

(6) yaml映射为列表与字典的复合结构

如果yaml文件是以下格式,那么会在python中映射为列表与字典的复合结构

- phase: train
  dataset: mydataset
  model : ResNet18

- phase: train
  dataset: mydataset
  model : VGG

python输出

[{'phase': 'train', 'dataset': 'mydataset', 'model': 'ResNet18'}, {'phase': 'train', 'dataset': 'mydataset', 'model': 'VGG'}]

1.2 PyYaml安装

pip

pip install pyyaml

conda

conda install pyyaml

或者

conda install yaml

1.3 PyYaml的使用

假设test.yaml文件内容如下:

phase: train
dataset: mydataset

optimizer_args:
    optimizer: Adam
    base_lr: 0.0001
    step: [ 20, 35]
    learning_ratio: 1
    weight_decay: 0.0001
    start_epoch: 0

1.3.1 加载yaml

1.3.1.1 非安全加载方式yaml.load()

使用yaml.load以非安全的方式加载yaml文件,

# -*- coding: utf-8 -*-

import yaml

if __name__ == '__main__':
    with open(r'test.yaml'.encode('utf-8'),'r') as f:
        try:
            default_args = yaml.load(f,Loader=yaml.FullLoader)
        except AttributeError:
            default_args = yaml.load(f)
    print(default_args)

程序输出如下

{'phase': 'train', 'dataset': 'mydataset', 'optimizer_args': {'optimizer': 'Adam', 'base_lr': 0.0001, 'step': [20, 35], 'learning_ratio': 1, 'weight_decay': 0.0001, 'start_epoch': 0}}

其中Loader参数可以指定以下加载器:

加载器类 功能 描述
BaseLoader 不解析或不支持任何标签,只构造基本的 Python 对象 ( str, list, dict)
Loader 保持向后兼容性,但在其他方面与UnsafeLoader相同
UnsafeLoader unsafe_load() 支持所有标准、库和自定义标签,并且可以构造任意 Python 对象
SafeLoader safe_load() 仅支持标准 YAML 标签,例如!!str,不构造类实例
FullLoader full_load() 应该能够安全地加载几乎所有的 YAML
1.3.1.2 安全加载方式yaml.safe_load()

yaml.safe_load()其内部的加载器指定为SafeLoader

# -*- coding: utf-8 -*-

import yaml

if __name__ == '__main__':
    with open(r'test.yaml'.encode('utf-8'),'r') as f:
        try:
            default_args = yaml.safe_load(f)
        except AttributeError:
            default_args = yaml.safe_load(f)
    print(default_args)

程序输出

{'phase': 'train', 'dataset': 'mydataset', 'optimizer_args': {'optimizer': 'Adam', 'base_lr': 0.0001, 'step': [20, 35], 'learning_ratio': 1, 'weight_decay': 0.0001, 'start_epoch': 0}}

1.3.2 将python对象存储到yaml文件

将python对象存储到yaml文件需要使用到yaml.dump()或者yaml.safe_dump()方法。

(1) 将python 字典写入到yaml

# -*- coding: utf-8 -*-

import yaml

if __name__ == '__main__':
    write_dict = {'phase':'train',
                  'dataset':'mydataset',
                  'model':'ResNet18',
                  'epoch':200}

    with open(f'write.yaml'.encode('utf-8'),'w') as f:
        yaml.dump(write_dict,f)

输出文件内容

dataset: mydataset
epoch: 200
model: ResNet18
phase: train

(2) 将python 列表写入到yaml

# -*- coding: utf-8 -*-

import yaml

if __name__ == '__main__':
    write_list = ['train','mydataset','ResNet18',200]

    with open(f'write.yaml'.encode('utf-8'),'w') as f:
        yaml.dump(write_list,f)

输出文件内容

- train
- mydataset
- ResNet18
- 200

(3) 将python 列表和字典复合结构写入到yaml

# -*- coding: utf-8 -*-

import yaml

if __name__ == '__main__':
    write_list = [
        {'phase': 'train',
         'dataset': 'mydataset',
         'model': 'ResNet18',
         'epoch': 200},
        {'phase': 'train',
         'dataset': 'mydataset',
         'model': 'VGG',
         'epoch': 150}
    ]

    with open(f'write.yaml'.encode('utf-8'),'w') as f:
        yaml.dump(write_list,f)

文件输出内容

- dataset: mydataset
  epoch: 200
  model: ResNet18
  phase: train
- dataset: mydataset
  epoch: 150
  model: VGG
  phase: train

参考链接