进 Q 学术交流群:922230617 或加 CV_EDPJ 进 W 交流群
目录
0. 前言
1. 版本 1:最原始写法——Config 写死
1.1 完整代码
1.2 修改方式
1.3 优缺点
1.4 适用场景
2. 版本 2:常用标准——原生 argparse
2.1 完整代码
2.2 命令行修改
2.3 优缺点
2.4 重点补充:原生 bool 致命 BUG
2.5 适用场景
3. 版本 3:精简 argparse——simple-parsing
3.1 完整代码
3.2 命令行修改
3.3 优缺点
3.4 适用场景
4. 版本 4:严格类型校验——Pydantic
4.1 完整代码
4.2 命令行修改
4.3 优缺点
4.4 类型校验实战演示(核心对比)
4.5 适用场景
5. 版本 5:无 yaml 纯代码——OmegaConf 字典版
5.1 完整代码
5.2 命令行修改
5.3 优缺点
5.4 适用场景
6. 版本 6:有 yaml 文件——OmegaConf 多 yaml 合并版
6.1 文件结构
6.2 基础配置 base.yaml
6.3 覆盖配置 bottle.yaml
6.4 主代码 train.py
6.5 运行方式(三种覆盖优先级 + 合并最终结果)
6.6 优缺点
6.7 适用场景
7. 六种写法横向对比
8. 选择建议
9. 总结
0. 前言
在深度学习、AI科研、Python工程项目中,参数配置管理是每一个开发者必须掌握的基础能力。
很多初学者疑惑:
本文使用最简单、最直白、循序渐进的方式,整理目前业内 6 种主流配置写法。
全部使用统一参数模板(覆盖常用类型):
int:epoch
float:learning_rate
str:dataset
bool:data_aug(数据增强开关)
int list:image_size
str list:categories
每种写法包含:完整代码 + 命令行修改方式 + 优缺点 + 适用场景。
1. 版本 1:最原始写法——Config 写死
1.1 完整代码
def train(cfg): print(cfg)if __name__ == '__main__': # 纯字典配置 config = { "epoch": 10, # int "learning_rate": 5e-4, # float "dataset": "mvtec", # str "data_aug": True, # bool "image_size": [224, 512, 1024], # int list "categories": ["bottle", "cable", "capsule"] # str list } train(config)
1.2 修改方式
必须打开 py 文件,手动修改数值。
1.3 优缺点
✅ 最简单、无任何学习成本
❌ 不能命令行修改、不能批量实验、代码污染、不规范
1.4 适用场景
个人临时测试、小脚本、不需要反复调参。
2. 版本 2:通用标准——原生 argparse
2.1 完整代码
import argparsedef train(args): print(args)if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("--epoch", type=int, default=10) parser.add_argument("--learning_rate", type=float, default=5e-4) parser.add_argument("--dataset", type=str, default="mvtec") parser.add_argument("--data_aug", type=bool, default=True) parser.add_argument("--image_size", type=int, nargs='+', default=[224, 512, 1024]) parser.add_argument("--categories", type=str, nargs='+', default=["bottle", "cable", "capsule"]) args = parser.parse_args() train(args)
2.2 命令行修改
python train.py --epoch 20 --learning_rate 1e-4 \--image_size 256 512 --categories bottle capsule
2.3 优缺点
✅ 官方自带、无需安装包、支持命令行、开源通用
❌ 代码冗余、重复啰嗦、list 需要 nargs='+'、原生 bool 存在致命 BUG
2.4 重点补充:原生 bool 致命 BUG
argparse 中直接使用 type=bool 是错误写法!
命令行传入 --data_aug False 永远为 True,因为命令行传参默认字符串,非空字符串全部被 bool 判定为 True。
正确写法:必须手动定义 str2bool 转换函数
def str2bool(v): if isinstance(v, bool): return v if v.lower() in ('yes', 'true', 't', 'y', '1'): return True elif v.lower() in ('no', 'false', 'f', 'n', '0'): return False else: raise argparse.ArgumentTypeError('Boolean value expected.')# 使用方式parser.add_argument("--data_aug", type=str2bool, default=True)
2.5 适用场景
传统深度学习开源项目、论文代码、服务器集群运行。
3. 版本 3:精简 argparse——simple-parsing
3.1 完整代码
from dataclasses import dataclassfrom simple_parsing import ArgumentParser@dataclassclass Config: epoch: int = 10 learning_rate: float = 5e-4 dataset: str = "mvtec" data_aug: bool = True # Python 列表坑:直接赋值有风险,推荐 None + __post_init__ image_size: list[int] = None categories: list[str] = None def __post_init__(self): if self.image_size is None: self.image_size = [224, 512, 1024] if self.categories is None: self.categories = ["bottle", "cable", "capsule"]def train(cfg): print(cfg)if __name__ == '__main__': parser = ArgumentParser() parser.add_arguments(Config, dest="cfg") cfg = parser.parse_args().cfg train(cfg)
3.2 命令行修改
python train.py --epoch 20 --image_size 256 768
3.3 优缺点
✅ 极度简洁、保留 argparse 全部命令行能力
❌ list 存在 Python 原生坑,直接赋值有风险,推荐 None + __post_init__,或使用不可变的 tuple 替代 list
3.4 适用场景
个人科研、不想写冗长 argparse、追求简洁。
4. 版本 4:严格类型校验——Pydantic
4.1 完整代码
from pydantic import BaseModelclass Config(BaseModel): epoch: int = 10 learning_rate: float = 5e-4 dataset: str = "mvtec" data_aug: bool = True image_size: list[int] = [224, 512, 1024] # 无需 def,直接写 categories: list[str] = ["bottle", "cable", "capsule"]def train(cfg): print(cfg)if __name__ == '__main__': # 简易命令行覆盖(零依赖) import sys kwargs = dict(arg.split("=") for arg in sys.argv[1:]) cfg = Config(**kwargs) train(cfg)
4.2 命令行修改
python train.py epoch=20 image_size=[256,768]
4.3 优缺点
✅ 列表无坑、不用 def、强类型严格校验、工业级稳定
❌ 命令行语法不如原生 argparse 直观
4.4 类型校验实战演示(核心对比)
为直观体现 Pydantic 强类型校验和 OmegaConf 弱校验区别,执行错误传参(把 int 类型的 epoch 传入字符串):
错误命令行:
python train.py epoch="我是字符串"
1)Pydantic 运行结果(直接报错):
抛出 ValidationError 异常,提示 epoch 应为整数,传入字符串非法,代码直接终止,杜绝错误参数流入训练流程。
2)OmegaConf 运行结果(自动弱转换):
无任何报错,自动把字符串转为字符串类型,静默接收非法参数。
重点:不会在此处报错,但训练使用该参数运算时一定会崩溃。
总结:Pydantic 强制约束参数类型,规避 bug;OmegaConf 宽松兼容,不做强制拦截。
4.5 适用场景
工程项目、部署项目、需要严格类型检查。
5. 版本 5:无 yaml 纯代码——OmegaConf 字典版
5.1 完整代码
from omegaconf import OmegaConfdef train(cfg): print(cfg)if __name__ == '__main__': # 外置原生字典 config = { "epoch": 10, "learning_rate": 5e-4, "dataset": "mvtec", "data_aug": True, "image_size": [224, 512, 1024], "categories": ["bottle", "cable", "capsule"] } # 普通字典转为 OmegaConf 对象 cfg = OmegaConf.create(config) # 融合命令行参数(合并覆盖) cfg = OmegaConf.merge(cfg, OmegaConf.from_cli()) train(cfg)
或者直接使用 create 创建:
from omegaconf import OmegaConfdef train(cfg): print(cfg)if __name__ == '__main__': cfg = OmegaConf.create({ "epoch": 10, "learning_rate": 5e-4, "dataset": "mvtec", "data_aug": True, "image_size": [224, 512, 1024], "categories": ["bottle", "cable", "capsule"] }) # 命令行自动合并覆盖 cfg = OmegaConf.merge(cfg, OmegaConf.from_cli()) train(cfg)
5.2 命令行修改
python train.py epoch=20 categories=[bottle,capsule]
5.3 优缺点
✅ 写法自由、列表无坑、不用定义类、不用 def
❌ 无强制类型校验,自动弱转换类型
5.4 适用场景
科研快速迭代、喜欢字典写法、讨厌模板代码。
6. 版本 6:有 yaml 文件——OmegaConf 多 yaml 合并版
6.1 文件结构
├── train.py└── config/ ├── base.yaml └── bottle.yaml
6.2 基础配置 base.yaml
epoch: 10learning_rate: 5e-4dataset: "mvtec"data_aug: trueimage_size: [224, 512, 1024]categories: ["bottle", "cable", "capsule"]
6.3 覆盖配置 bottle.yaml
epoch: 20data_aug: falseimage_size: [256, 768]categories: ["bottle"]
6.4 主代码 train.py
from omegaconf import OmegaConfdef train(cfg): print(cfg)if __name__ == '__main__': # 多文件合并:基础配置 + 个性化配置 cfg = OmegaConf.load("config/base.yaml") cfg2 = OmegaConf.load("config/bottle.yaml") cfg = OmegaConf.merge(cfg, cfg2) # 命令行最高优先级覆盖 cfg = OmegaConf.merge(cfg, OmegaConf.from_cli()) train(cfg)
6.5 运行方式(三种覆盖优先级 + 合并最终结果)
优先级:命令行 > 个性化yaml > 基础yaml
合并规则:后加载的配置 覆盖 先加载的同名键,不同键保留全部,无冲突合并。
1)仅合并两个 YAML 文件(无命令行)
base.yaml + bottle.yaml 合并结果:
epoch: 20learning_rate: 5e-4dataset: "mvtec"data_aug: falseimage_size: [256, 768]categories: ["bottle"]
2)追加命令行覆盖(最高优先级)
# 命令行临时覆盖(最高优先级)python train.py learning_rate=1e-3 image_size=[512,1024]
最终完整合并结果:
epoch: 20learning_rate: 1e-3dataset: "mvtec"data_aug: falseimage_size: [512,1024]categories: ["bottle"]
6.6 优缺点
✅ 支持多配置合并、分层管理、批量实验、业内标准
✅ 列表 bool 无任何坑、命令行极其顺滑
❌ 需要管理 yaml 文件,新手稍微抽象
6.7 适用场景
大厂项目、SOTA 论文、大规模调参、多实验管理。
7. 六种写法横向对比总结
方案 | 列表是否要 def | 命令行 | 多配置合并 | 难度 | 推荐指数 |
|---|
Config | 不需要 | 不支持 | 不支持 | 极低 | ⭐ |
原生 argparse | 不需要 | 完美支持 | 不支持 | 中 | ⭐⭐⭐ |
simple-parsing | 必须写 | 完美支持 | 不支持 | 低 | ⭐⭐⭐⭐ |
Pydantic | 不需要 | 简易支持 | 不推荐 | 低 | ⭐⭐⭐⭐ |
OmegaConf 字典 | 不需要 | 完美支持 | 支持 | 极低 | ⭐⭐⭐⭐⭐ |
OmegaConf-YAML | 不需要 | 完美支持 | 最强支持 | 中 | ⭐⭐⭐⭐⭐ |
8. 选择建议
自己随便跑代码、不爱折腾 → Config / Pydantic
开源投稿、要通用、兼容服务器 → 原生 argparse
喜欢类写法、又不想写冗长 argparse → simple-parsing
追求极简、无坑、自由灵活 → OmegaConf 字典版
做科研批量实验、多组参数、分层配置 → OmegaConf + YAML(终极方案)
9. 全文总结
本文从最简单的字典硬编码开始,循序渐进演示了深度学习六种主流配置方案,覆盖开发中全部常用参数类型:int、float、str、bool、int list、str list。结合实战对比、类型校验、合并规则、命令行用法,清晰区分各类配置库的底层差异。
1)所有配置库本质完全一致:默认参数 + 外部优先级覆盖。
- 没有任何一种配置能做到 “不用改文件”,静态配置都需要手动编辑;
- 真正的差距在于:是否支持命令行临时覆盖、是否做类型校验、是否支持多文件合并。
2)原生 argparse 缺点明显:
- 代码冗长、list 必须 nargs、bool 存在原生 BUG,必须手写 str2bool 转换函数,
3)simple-parsing 简化 argparse,但存在 Python 列表默认值坑:
- list 最好赋值 None + __post_init__,使用有门槛。
4)Pydantic 与 OmegaConf 是目前主流优选,二者区别通俗易懂:
5)OmegaConf 容错机制提醒:
- 错误参数不会在初始化时报错,但一定会在训练运算、梯度计算时崩溃,且排查难度更大。