pyrallis库
- 为啥要用pyrallis
- pyrallis使用例子
- [Key Features](#Key Features)
- 了解pyrallis五步法
-
- [pyrallis.parse for dataclass Parsing](#pyrallis.parse for dataclass Parsing)
- [pyrallis.wrap 装饰器](#pyrallis.wrap 装饰器)
- 使用固有数据类特性的更好配置
- [from dataclasses import dataclass, field创建数据类](#from dataclasses import dataclass, field创建数据类)
https://github.com/eladrich/pyrallis
pyrallis是一个用于从数据类自动创建项目配置的简单库,它是从simple-parsing派生出来的,并收到Hydra的启发。
为啥要用pyrallis
使用pyrallis,您的配置直接链接到预定义的数据类,允许您使用面向对象的设计轻松创建不同的配置结构,包括嵌套结构。解析后的参数用于初始化数据类,为您提供键入提示和完整数据类对象的自动代码完成。
pyrallis使用例子
pyrallis有几个关键特性,但pyrallis的核心只是允许使用数据类定义参数解析器。
python
from dataclasses import dataclass
import pyrallis
@dataclass
class TrainConfig:
"""Training config for Machine Learning"""
workers: int = 8 # The number of workers for training
exp_name: str = 'default_exp' # The experiment name
def main():
cfg = pyrallis.parse(config_class=TrainConfig)
print(f'Training {cfg.exp_name} with {cfg.workers} workers...')
然后可以使用命令行参数、yaml配置文件或两者同时指定参数。
python
$ python train_model.py --config_path=some_config.yaml --exp_name=my_first_exp
Training my_first_exp with 42 workers...
假设你的yaml配置文件内容为:
python
exp_name: my_yaml_exp
workers: 42
Key Features
关键特性基于这种设计,pyrallis提供了一些非常有趣的功能,包括
- 由于结构化配置,内置IDE支持自动完成和检查。
- 从命令行和配置文件中联合读取,支持指定默认配置文件。
- 支持内置的数据类特性,如_post_init和@property
- 支持数据类的嵌套和继承,嵌套参数自动创建!
- @pyrallis.wrap()装饰器,用于包装主类
- 使用pyrallis.encode.register和pyrallis.decode.register轻松扩展到新类型
- 轻松加载和保存现有的配置使用pyrallis.dump和pyrallis.load
- --help从数据类创建,同时考虑到注释!
- 支持多种配置格式(yaml,json, toml)使用pyrallis.set_config_type
了解pyrallis五步法
pyrallis.parse for dataclass Parsing
python
from dataclasses import dataclass, field
import pyrallis
@dataclass
class TrainConfig:
"""Training config for Machine Learning"""
# The number of workers for training
workers: int = field(default=8)
# The experiment name
exp_name: str = field(default='default_exp')
def main():
cfg = pyrallis.parse(config_class=TrainConfig)
print(f'Training {cfg.exp_name} with {cfg.workers} workers...')
if __name__ == '__main__':
main()
然后可以通过命令行来传递config:
python
$ python train_model.py --exp_name=my_first_model
Training my_first_model with 8 workers...
pyrallis还会自动生成一个--help字符串数据类中的注释
python
$ python train_model.py --help
usage: train_model.py [-h] [--config_path str] [--workers int] [--exp_name str]
optional arguments:
-h, --help show this help message and exit
--config_path str Path for a config file to parse with pyrallis (default:
None)
TrainConfig:
Training config for Machine Learning
--workers int The number of workers for training (default: 8)
--exp_name str The experiment name (default: default_exp)
pyrallis.wrap 装饰器
如果不喜欢用pyrallis.parse格式:
python
def main():
cfg = pyrallis.parse(config_class=TrainConfig)
print(f'Training {cfg.exp_name} with {cfg.workers} workers...')
可以使用pyrallis.wrap格式是一样的:
python
@pyrallis.wrap()
def main(cfg: TrainConfig):
# The decorator automagically uses the type hint to parsers arguments into TrainConfig
print(f'Training {cfg.exp_name} with {cfg.workers} workers...')
使用固有数据类特性的更好配置
当使用数据类时,我们可以使用现有的添加额外的功能数据类特性,如post_init机制或@properties
python
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
import pyrallis
@dataclass
class TrainConfig:
""" Training config for Machine Learning """
# The number of workers for training
workers: int = field(default=8)
# The number of workers for evaluation
eval_workers: Optional[int] = field(default=None)
# The experiment name
exp_name: str = field(default='default_exp')
# The experiment root folder path
exp_root: Path = field(default=Path('/share/experiments'))
def __post_init__(self):
# A builtin method of dataclasses, used for post-processing our configuration.
self.eval_workers = self.eval_workers or self.workers
@property
def exp_dir(self) -> Path:
# Properties are great for arguments that can be derived from existing ones
return self.exp_root / self.exp_name
@pyrallis.wrap()
def main(cfg: TrainConfig):
print(f'Training {cfg.exp_name}...')
print(f'\tUsing {cfg.workers} workers and {cfg.eval_workers} evaluation workers')
print(f'\tSaving to {cfg.exp_dir}')
python
$ python -m train_model.py --exp_name=my_second_exp --workers=42
Training my_second_exp...
Using 42 workers and 42 evaluation workers
Saving to /share/experiments/my_second_exp
from dataclasses import dataclass, field创建数据类
python
from dataclasses import dataclass, field # 用于创建数据类
from pathlib import Path # 用于处理文件和文件路径
from typing import Optional, Tuple, List # 提供类型注解支持
from loguru import logger # 一个日志库
@dataclass # 装饰器,用于将下面的类定义为数据类
class RenderConfig:
# RenderConfig类为渲染的相关参数提供了一个集中的配置。
# 这样,你可以创建这个类的实例,并为其提供特定的配置,而不是分散在多个地方设置这些参数
""" Parameters for the Mesh Renderer """
# 使用dataclasses, 定义了一个名为RenderConfig的数据类.
# 数据类简化了类的创建过程,主要用于创建像结构体那样的简单类,其中的字段主要是数据
# 在类的内部,每个变量定义都是一个成员变量
# Grid size for rendering during painting
train_grid_size: int = 1200 # 定义了一个名为train_grid_size的成员变量,它的类型为int,默认值为1200
# Grid size of evaluation
eval_grid_size: int = 1024
# training camera radius range
radius: float = 1.5
# Set [0,overhead_range] as the overhead region
overhead_range: float = 40
# Define the front angle region
front_range: float = 70
# The front offset, use to rotate shape from code
front_offset:float = 0.0
# Number of views to use
n_views: int = 8
# Theta value for rendering during training
base_theta:float = 60
# fiels(default_factory=list):对于默认为列表或其他可变对象的成员变量,直接设置默认值可能会导致不期望的行为
# (因为类的所有实例将共享同一个列表)。为了避免这个问题,使用field函数的default_factory参数来提供一个函数,
# 此函数将返回新的列表实例
# Additional views to use before rotating around shape
views_before: List[Tuple[float,float]] = field(default_factory=list)
# Additional views to use after rotating around shape
views_after: List[Tuple[float, float]] = field(default_factory=[[180,30],[180,150]].copy)
# Whether to alternate between the rotating views from the different sides
alternate_views: bool = True
@dataclass
class GuideConfig:
""" Parameters defining the guidance """
# Guiding text prompt
text: str
# The mesh to paint
shape_path: str = 'shapes/spot_triangulated.obj'
# Append direction to text prompts
append_direction: bool = True
# A Textual-Inversion concept to use
# 表示concept_name这个属性的类型可以是字符串(str)或者None,并且它的默认值为None
concept_name: Optional[str] = None
# Path to the TI embedding
# 表示concept_path这个属性的类型可以是Path(这是pathlib模块中的一个类,用于表示文件或目录的路径)或者None
concept_path: Optional[Path] = None
# A huggingface diffusion model to use
diffusion_name: str = 'stabilityai/stable-diffusion-2-depth'
# Scale of mesh in 1x1x1 cube
shape_scale: float = 0.6
# height of mesh
dy: float = 0.25
# texture image resolution
texture_resolution: int = 1024
# texture mapping interpolation mode from texture image, options: 'nearest', 'bilinear', 'bicubic'
texture_interpolation_mode: str= 'bilinear'
# Guidance scale for score distillation
guidance_scale: float = 7.5
# Use inpainting in relevant iterations
use_inpainting: bool = True
# The texture before editing
reference_texture: Optional[Path] = None
# The edited texture
initial_texture: Optional[Path] = None
# Whether to use background color or image
use_background_color: bool = False
# Background image to use
background_img: str = 'textures/brick_wall.png'
# Threshold for defining refine regions
z_update_thr: float = 0.2
# Some more strict masking for projecting back
strict_projection: bool = True
@dataclass
class LogConfig:
""" Parameters for logging and saving """
# Experiment name
exp_name: str
# Experiment output dir
exp_root: Path = Path('experiments/')
# How many steps between save step
save_interval: int = 100
# Run only test
eval_only: bool = False
# Number of angles to sample for eval during training
eval_size: int = 10
# Number of angles to sample for eval after training
full_eval_size: int = 100
# Export a mesh
save_mesh: bool = True
# Whether to show intermediate diffusion visualizations
vis_diffusion_steps: bool = False
# Whether to log intermediate images
log_images: bool = True
@property
def exp_dir(self) -> Path:
return self.exp_root / self.exp_name
@property 是一个内置的 Python 装饰器,它用于将一个方法转换为属性。使用此装饰器后,你可以直接访问该方法作为属性,而无需像调用方法那样加上 ()。
在上面提供的 LogConfig 类中,有一个使用了 @property 装饰器的方法 exp_dir。这意味着你可以直接访问 exp_dir,就好像它是一个属性一样,而不需要调用它。
例如:
python
log_config = LogConfig(exp_name="my_experiment")
print(log_config.exp_dir) # 输出: experiments/my_experiment
在上面的例子中,exp_dir 返回了将 exp_root(默认值为 "experiments/")与 exp_name(这里的值为 "my_experiment")连接起来的路径。通过使用 @property 装饰器,你可以将 exp_dir 轻松地作为一个只读属性访问,而无需将其定义为方法或函数。这为你提供了一种更自然、更直观的方式来获取该属性值。