pyrallis库


https://github.com/eladrich/pyrallis
pyrallis是一个用于从数据类自动创建项目配置的简单库,它是从simple-parsing派生出来的,并收到Hydra的启发。

为啥要用pyrallis

使用pyrallis,您的配置直接链接到预定义的数据类,允许您使用面向对象的设计轻松创建不同的配置结构,包括嵌套结构。解析后的参数用于初始化数据类,为您提供键入提示和完整数据类对象的自动代码完成。

pyrallis使用例子

pyrallis有几个关键特性,但pyrallis的核心只是允许使用数据类定义参数解析器

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 train_model.py --config_path=some_config.yaml --exp_name=my_first_exp
Training my_first_exp with 42 workers...

假设你的yaml配置文件内容为:

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

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 train_model.py --exp_name=my_first_model
Training my_first_model with 8 workers...

pyrallis还会自动生成一个--help字符串数据类中的注释

$ 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 装饰器

pyramidis.parse 形式を使用したくない場合は、次のようにします。

def main():
    cfg = pyrallis.parse(config_class=TrainConfig)
    print(f'Training {
      
      cfg.exp_name} with {
      
      cfg.workers} workers...')

使用できるフォーマットは、pyramidis.wrap と同じです。

@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 などの既存のデータ クラス機能を使用して機能を追加できます。

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 -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 # 用于创建数据类
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 を呼び出すことなく、あたかもプロパティであるかのように、exp_dir に直接アクセスできることを意味します。

例えば:

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 をメソッドまたは関数として定義せずに、読み取り専用プロパティとして簡単にアクセスできます。これにより、より自然かつ直感的にプロパティ値を取得できるようになります。

Guess you like

Origin blog.csdn.net/weixin_43845922/article/details/132360869