python用yaml装参数并支持命令行修改

效果:

  • 将实验用的参数写入 yaml 文件,而不是全部用 argparse 传,否则命令会很长;
  • 同时支持在命令行临时加、改一些参数,避免事必要在 yaml 中改参数,比较灵活(如 grid-search 时遍历不同的 loss weights)。

最初是在 MMDetection 中看到这种写法,参考 [1] 中 --cfg-options 这个参数,核心是 DictAction 类,定义在 [2]。yaml 一些支持的写法参考 [3]。本文同时作为 python yaml 读、写简例。

Code

  • DictAction 类抄自 [2];
  • parse_cfg 函数读 yaml 参数,并按命令行输入加、改参数(覆盖 yaml),用 EasyDict 装;
  • 用 yaml 备份参数时,用 easydict2dict 将 EasyDict 递归改回 dict,yaml 会干净点。不用也行。
from argparse import Action, ArgumentParser, Namespace
import copy
from easydict import EasyDict
from typing import Any, Optional, Sequence, Tuple, Union
import yamlclass DictAction(Action):"""抄自 MMEngineargparse action to split an argument into KEY=VALUE formon the first = and append to a dictionary. List options canbe passed as comma separated values, i.e 'KEY=V1,V2,V3', or with explicitbrackets, i.e. 'KEY=[V1,V2,V3]'. It also support nested brackets to buildlist/tuple values. e.g. 'KEY=[(V1,V2),(V3,V4)]'"""@staticmethoddef _parse_int_float_bool(val: str) -> Union[int, float, bool, Any]:"""parse int/float/bool value in the string."""try:return int(val)except ValueError:passtry:return float(val)except ValueError:passif val.lower() in ['true', 'false']:return True if val.lower() == 'true' else Falseif val == 'None':return Nonereturn val@staticmethoddef _parse_iterable(val: str) -> Union[list, tuple, Any]:"""Parse iterable values in the string.All elements inside '()' or '[]' are treated as iterable values.Args:val (str): Value string.Returns:list | tuple | Any: The expanded list or tuple from the string,or single value if no iterable values are found.Examples:>>> DictAction._parse_iterable('1,2,3')[1, 2, 3]>>> DictAction._parse_iterable('[a, b, c]')['a', 'b', 'c']>>> DictAction._parse_iterable('[(1, 2, 3), [a, b], c]')[(1, 2, 3), ['a', 'b'], 'c']"""def find_next_comma(string):"""Find the position of next comma in the string.If no ',' is found in the string, return the string length. Allchars inside '()' and '[]' are treated as one element and thus ','inside these brackets are ignored."""assert (string.count('(') == string.count(')')) and (string.count('[') == string.count(']')), \f'Imbalanced brackets exist in {string}'end = len(string)for idx, char in enumerate(string):pre = string[:idx]# The string before this ',' is balancedif ((char == ',') and (pre.count('(') == pre.count(')'))and (pre.count('[') == pre.count(']'))):end = idxbreakreturn end# Strip ' and " characters and replace whitespace.val = val.strip('\'\"').replace(' ', '')is_tuple = Falseif val.startswith('(') and val.endswith(')'):is_tuple = Trueval = val[1:-1]elif val.startswith('[') and val.endswith(']'):val = val[1:-1]elif ',' not in val:# val is a single valuereturn DictAction._parse_int_float_bool(val)values = []while len(val) > 0:comma_idx = find_next_comma(val)element = DictAction._parse_iterable(val[:comma_idx])values.append(element)val = val[comma_idx + 1:]if is_tuple:return tuple(values)return valuesdef __call__(self,parser: ArgumentParser,namespace: Namespace,values: Union[str, Sequence[Any], None],option_string: str = None):"""Parse Variables in string and add them into argparser.Args:parser (ArgumentParser): Argument parser.namespace (Namespace): Argument namespace.values (Union[str, Sequence[Any], None]): Argument string.option_string (list[str], optional): Option string.Defaults to None."""# Copied behavior from `argparse._ExtendAction`.options = copy.copy(getattr(namespace, self.dest, None) or {})if values is not None:for kv in values:key, val = kv.split('=', maxsplit=1)options[key] = self._parse_iterable(val)setattr(namespace, self.dest, options)def parse_cfg(yaml_file, update_dict={}):"""load configurations from a yaml file & update from command-line argmentsInput:yaml_file: str, path to a yaml configuration fileupdate_dict: dict, to modify/update options in those yaml configurationsOutput:cfg: EasyDict"""with open(args.cfg, "r") as f:cfg = EasyDict(yaml.safe_load(f))if update_dict:assert isinstance(update_dict, dict)for k, v in update_dict.items():k_list = k.split('.')assert len(k_list) > 0if len(k_list) == 1: # 单级,e.g. lr=0.1cfg[k_list[0]] = velse: # 多级,e.g. optimizer.group1.lr=0.2ptr = cfgfor i, _k in enumerate(k_list):if i == len(k_list) - 1: # last layerptr[_k] = velif _k not in ptr:ptr[_k] = {}ptr = ptr[_k]return cfgdef easydict2dict(ed):"""convert EasyDict to dict for clean yaml"""d = {}for k, v in ed.items():if isinstance(v, EasyDict):d[k] = easydict2dict(v)else:d[k] = vreturn dif "__main__" == __name__:# test command:#   python config.py --cfg-options int=5 dict2.lr=8 dict2.newdict.newitem=flyimport pprintparser = ArgumentParser()parser.add_argument("--cfg", type=str, default="config.yaml", help="指定 yaml")parser.add_argument('--cfg-options',nargs='+',action=DictAction,help='override some settings in the used config, the key-value pair ''in xxx=yyy format will be merged into config file. If the value to ''be overwritten is a list, it should be like key="[a,b]" or key=a,b ''It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ''Note that the quotation marks are necessary and that no white space ''is allowed.')args = parser.parse_args()# 命令行临时加、改参数pprint.pprint(args.cfg_options) # dict# 读 yaml,并按命令行输入加、改参数cfg = parse_cfg(args.cfg, args.cfg_options)pprint.pprint(cfg)# 备份 yaml(写 yaml)with open("backup-config.yaml", 'w') as f:yaml.dump(easydict2dict(cfg), f)

输入的 config.yaml

  • 语法参考 [3]
# An example yaml configuration file, used in utils/config.py as an example input.
# Ref: https://pyyaml.org/wiki/PyYAMLDocumentationlog_path: ./log
none: [~, null, None]
bool: [true, false, on, off, True, False]
int: 42				# <- 改它
float: 3.14159
list: [LITE, RES_ACID, SUS_DEXT]
list2:- -1- 0- 1
str:a20.2# d: tom
dict: {hp: 13, sp: 5}
dict2:				# <- 加它lr: 0.01			# <- 改它decay_rate: 0.1name: jerry

测试:

# --cfg-options 支持多级指定(用「.」分隔)
python config.py --cfg config.yaml --cfg-options int=5 dict2.lr=8 dict2.newdict.newitem=fly

输出:

{'dict2.lr': 8, 'dict2.newdict.newitem': 'fly', 'int': 5}
{'bool': [True, False, True, False, True, False],'dict': {'hp': 13, 'sp': 5},'dict2': {'decay_rate': 0.1,'lr': 8,							# <- 改了'name': 'jerry','newdict': {'newitem': 'fly'}},	# <- 加了'float': 3.14159,'int': 5,									# <- 改了'list': ['LITE', 'RES_ACID', 'SUS_DEXT'],'list2': [-1, 0, 1],'log_path': './log','none': [None, None, 'None'],'str': 'a 2 0.2'}

References

  1. open-mmlab/mmdetection/tools/train.py
  2. open-mmlab/mmengine/mmengine/config/config.py
  3. PyYAML Documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript综合练习4

JavaScript 综合练习 4 1. 案例演示 2. 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title&…

深入探索MySQL 8:隐藏索引与降序索引的新特性

随着技术的不断进步&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;也在不断地更新和升级&#xff0c;以满足日益增长的数据处理需求。作为最受欢迎的开源关系型数据库之一&#xff0c;MySQL的每个新版本都会引入一系列新特性和改进&#xff0c;旨在提高性能、增强安全…

单片机的认识

单片机的定义 先简单理解为&#xff1a; 在一片集成电路芯片上集成了微处理器&#xff08;CPU &#xff09;存储器&#xff08;ROM和RAM&#xff09;、I/O 接口电路&#xff0c;构成单芯片微型计算机&#xff0c;即为单片机。 把组成微型计算机的控制器、运算器、存储器、输…

MATLAB实现随机森林回归算法

随机森林回归是一种基于集成学习的机器学习算法&#xff0c;它通过组合多个决策树来进行回归任务。随机森林的基本思想是通过构建多个决策树&#xff0c;并将它们的预测结果进行平均或投票来提高模型的准确性和鲁棒性。 以下是随机森林回归的主要特点和步骤&#xff1a; 决策树…

“SharpDocx” C#项目中用于创建 Word 文档的轻量级模板引擎

简介&#xff1a; SharpDocx是一个轻量级的模板引擎&#xff0c;用于创建Word文档。它允许开发者基于视图生成Word文档&#xff0c;这个视图本身就是一个Word文档&#xff0c;可以根据需要设置简单或复杂的布局。 以下是一些主要特点&#xff1a; 模板引擎类似Razor&#xf…

jmeter-问题二:JMeter进行文件上传时,常用的几种MIME类型

以下是一些常用的MIME类型及其对应的文件扩展名&#xff1a; 文本类型: text/plain: 通常用于纯文本文件&#xff0c;如 .txt 文件。 text/html: 用于HTML文档&#xff0c;即 .html 文件。 application/msword: Microsoft Word文档&#xff0c;即 .doc 和 .docx 文件。 图像…

【大厂AI课学习笔记】【1.5 AI技术领域】(8)文本分类

8,9,10&#xff0c;将分别讨论自然语言处理领域的3个重要场景。 自然语言处理&#xff0c;Natual Language Processing&#xff0c;NLP&#xff0c;包括自然语言识别和自然语言生成。 用途是从非结构化的文本数据中&#xff0c;发掘洞见&#xff0c;并访问这些信息&#xff0…

哈工大团队顶刊发布!由单偏心电机驱动的爬行机器人实现多方向运动传递

单电机也能驱动平面内前进和转弯运动&#xff1f;没错&#xff0c;图中的机器人名叫GASR&#xff0c;仅由四个零件组成&#xff0c;分别是偏心电机、电池、电路板、聚酰亚胺薄片&#xff0c;它可以灵活自如地实现前进、转弯等移动。其中的核心驱动器——纽扣式偏心转子电机产自…

[SAP] ABAP设置非系统关键字代码提示功能

在事务码SE38(ABAP编辑器)屏幕右下角&#xff0c;点击【Options选项】图标 勾选【代码完成】|【建议文本中的非关键字】&#xff0c;并点击【保存】按钮 在下面的程序代码中&#xff0c;当我需要输入在11行的位置输入非关键字lv_str的时候&#xff0c;会有非关键字代码提示的功…

django中实现数据迁移

在Django中&#xff0c;数据迁移&#xff08;data migrations&#xff09;通常指的是将模型&#xff08;models&#xff09;中的数据从一个状态迁移到另一个状态。这可以涉及很多操作&#xff0c;比如添加新字段、删除字段、更新字段的数据类型&#xff0c;或者更改表之间的关系…

【java】Hibernate访问数据库

一、Hibernate访问数据库案例 Hibernate 是一个在 Java 社区广泛使用的对象关系映射&#xff08;ORM&#xff09;工具。它简化了 Java 应用程序中数据库操作的复杂性&#xff0c;并提供了一个框架&#xff0c;用于将对象模型数据映射到传统的关系型数据库。下面是一个简单的使…

JAVA设计模式之模版方法模式详解

模板方法模式 1 模板方法模式介绍 模板方法模式(template method pattern)原始定义是&#xff1a;在操作中定义算法的框架&#xff0c;将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法中的算法可以理解为广义上的业务逻辑…

【canvas】实现画布橡皮擦功能、并解决擦除不连贯问题;

简单介绍橡皮擦功能思路&#xff0c;代码demo自己看看就好了&#xff0c;一点都不复杂&#xff1a; 确认橡皮擦大小&#xff0c;可动态设置&#xff1b;鼠标按下记录点击的坐标&#xff0c;然后根据设置的橡皮擦大小画一个圆&#xff0c;最后清除该圆形区域坐标范围的颜色信息…

机器学习---概率图模型(概率计算问题)

1. 直接计算法 给定模型和观测序列&#xff0c;计算观测序列O出现的概率。最直接 的方法是按概率公式直接计算.通过列举所有可能的长度为T的状态序列&#xff0c;求各个状 态序列 I 与观测序列的联合概率&#xff0c;然后对所有可能的状态序列求和&#xff0c;得 到。 状态…

洛谷 P2678 [NOIP2015 提高组] 跳石头 (Java)

洛谷 P2678 [NOIP2015 提高组] 跳石头 (Java) 传送门&#xff1a;P2678 [NOIP2015 提高组] 跳石头 题目&#xff1a; [NOIP2015 提高组] 跳石头 题目背景 NOIP2015 Day2T1 题目描述 一年一度的“跳石头”比赛又要开始了&#xff01; 这项比赛将在一条笔直的河道中进行&…

3 scala集合-Set

与 Java 的 Set 一样&#xff0c;scala 的 set 中&#xff0c;元素都是唯一的&#xff0c;而且遍历 set 中集合的顺序&#xff0c;跟元素插入的顺序是不一样的。 同样&#xff0c;Set 也包含可变和不可变两种。要实现可变 Set 集合&#xff0c;需要使用类 scala.collection.mu…

Centos 性能调优

调优 : 文件使用限制和进程数 查询单个用户对文件描述符的使用限制&#xff0c; 即打开文件的个数 ulimit -n默认是 1024 查询单个用户最多拥有的进程数 ulimit -u默认是 4096 调整两个参数为 65535 (2^16 - 1) 修改 sudo vi /etc/security/limits.conf * soft nof…

在屏蔽任何FRP环境下从零开始搭建安全的FRP内网穿透服务

背景 本人目前在境外某大学读博&#xff0c;校园网屏蔽了所有内网穿透的工具的数据包和IP访问&#xff0c;为了实现在家也能远程访问服务器&#xff0c;就不得不先开个学校VPN&#xff0c;再登陆。我们实验室还需要访问另一个大学的服务器&#xff0c;每次我都要去找另一个大学…

Mysql-Explain-使用说明

Explain 说明 explain SELECT * FROM tb_category_report;id&#xff1a;SELECT识别符&#xff0c;这是SELECT查询序列号。select_type&#xff1a;表示单位查询的查询类型&#xff0c;比如&#xff1a;普通查询、联合查询(union、union all)、子查询等复杂查询。table&#x…

酷开科技荣获消费者服务平台黑猫投诉“消费者服务之星”称号

什么是优质服务&#xff1f;既是以客户为中心的庄严承诺&#xff0c;又是对服务能力提升的深耕细作&#xff1b;既是对服务标准的敬畏&#xff0c;也是对服务创新的不断探索……服务是多维的&#xff0c;每个企业都有自己独到的诠释&#xff0c;或事无巨细环环严控&#xff0c;…