pyrallis库

pyrallis库

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 轻松地作为一个只读属性访问,而无需将其定义为方法或函数。这为你提供了一种更自然、更直观的方式来获取该属性值。

相关推荐
谢眠1 分钟前
深度学习day3-自动微分
python·深度学习·机器学习
搏博10 分钟前
神经网络问题之一:梯度消失(Vanishing Gradient)
人工智能·机器学习
z千鑫11 分钟前
【人工智能】深入理解PyTorch:从0开始完整教程!全文注解
人工智能·pytorch·python·gpt·深度学习·ai编程
YRr YRr19 分钟前
深度学习:神经网络的搭建
人工智能·深度学习·神经网络
威桑21 分钟前
CMake + mingw + opencv
人工智能·opencv·计算机视觉
爱喝热水的呀哈喽25 分钟前
torch张量与函数表达式写法
人工智能·pytorch·深度学习
rellvera32 分钟前
【强化学习的数学原理】第02课-贝尔曼公式-笔记
笔记·机器学习
肥猪猪爸1 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn1 小时前
二分基本实现
数据结构·算法
萝卜兽编程1 小时前
优先级队列
c++·算法