cht
cht
发布于 2025-04-13 / 15 阅读
0
0

旧世纪

neural network acceleration.zip

Hydra 框架

  • # for Shadow Hand 

    python protomotions/train_agent.py +exp=maniptrans_Transformer task=ResDexHand dexhand=shadow side=RH headless=true num_envs=4096 learning_rate=2e-4 test=false randomStateInit=true 命令中有的参数 加+ 有的参数不加 + 这些有什么区别

2 在调用 maniptrans_Transformer.yaml 过程中,我们注意到

  • 此时 config/base.yaml 下的参数注定要被覆盖,通过观察,base.yaml 包含了

    defaults:
      - base/fabric
      - base/hydra
      - base/structure
  • 而 structure.yaml 包含了 如下,打问号的要被覆盖

    # @package _global_
    
    agent: ???
    
    env: ???
    
    robot: ???
    simulator: ???
    
    motion_lib: ???  # This is defined in the robot configs
    # This is provided by the user.
    # Can be null if reset using default pose and task doesn't use reference motions.
    motion_file: null
    
    terrain: ???  # This is defined in the terrain configs

  1. 问题二:为什么 - /agent/... 这样的路径就能覆盖参数?而不是 key-value 的形式

  1. YAML 的嵌套层级(缩进和冒号表示)直接映射为 Python 对象属性的链式调用(用. 表示)。

  • 假设 YAML 文件中的结构

agent:
  _target_: protomotions.agents.maniptrans.agent.ManiptransAgent
  config:
    gamma: 0.99
    model:
      _target_: protomotions.agents.maniptrans.model.VaeDeterministicOutputModel
      optimizer:
        lr: 2e-5
  • 要获取最外层的 agent 对象配置

agent_config = config.agent
  • 要获取 gamma 的值

gamma_value = config.agent.config.gamma  # 返回 0.99

  1. 前面都是提及了一些yaml的复用。所以 /home/linux/issac/maniptrans_transformer/protomotions/agents/maniptrans/agent.py有没有被用到呢

  • .../config/agent/maniptrans/agent.yaml 这个配置文件中,有这样一行至关重要的代码:

_target_: protomotions.agents.maniptrans.agent.Maniptrans
  • 这个 _target_ 就是一个明确的指令,它是一个字符串,指向一个具体的 Python 类。它的意思是:

    • 文件: protomotions/agents/maniptrans/agent.py

    • : 在上述文件中定义的 Maniptrans

  • 在主训练脚本 train_agent.py,有这样一行代码:

agent = instantiate(config.agent, env=env, fabric=fabric)
  • 当这行代码执行时,instantiate 函数会:

    • 查看 config.agent 这个配置对象。

    • 找到里面的 _target_ 键,并读取它的值:"protomotions.agents.maniptrans.agent.ManiptransAgent"

    • 动态地导入并创建这个类的实例

  1. 嵌套实例化

# @package _global_

num_envs: 4096
agent:
  _target_: protomotions.agents.maniptrans.agent.Maniptrans
  _recursive_: False
  config:
    # Setup basic actor-critic structure
    model:
      _target_: protomotions.agents.maniptrans.model.VaeDeterministicOutputModel
      _recursive_: False
      config:
        vae_latent_dim: ${agent.config.vae.latent_dim}
        vae_noise_type: ${agent.config.vae.noise_type}

        trunk:
          _target_: protomotions.agents.common.mlp.MultiHeadedMLP
          _recursive_: False
          num_out: ${robot.number_of_actions}
          config:
            input_models:
              self_obs:
                _target_: protomotions.agents.common.common.Flatten
  • 可以观察到这里有多个 _target_ 关键字 ,我们注意到它的实例化过程:

    • 首先在 agent.py 中创建 agent.py 对应的 Maniptrans 实例

 agent = instantiate(config.agent, env=env, fabric=fabric)
    • 如果调用了 agent 的 子方法 setup,那么 会运行下面这个代码

model: PPOModel = instantiate(self.config.model)
    • 这时候找到 protomotions.agents.maniptrans.model.VaeDeterministicOutputModel yaml的这句话,会去相应文件中找出相应类的init函数

为什么每一个嵌套都要隔着加一个config?

这不是强制性的 ,但这样写的话,当 Hydra 实例化对象时,它会将 config: 节点下的所有内容作为一个单一的对象,传递给 Python 类的构造函数 __init__

这样子的话,在model.py 的 VaeDeterministicOutputModel 实例化中,__init__ 方法的签名非常简洁,它只需要接收一个 config 对象,而不是接收一大堆独立的参数(__init__(self, vae_latent_dim, vae_noise_type, trunk, ...)),这会让代码变得极其冗长和难以维护

class VaeDeterministicOutputModel:
    # 构造函数只接收一个名为 config 的参数!
    def __init__(self, config): 
        super().__init__()

ManipTrans

运行训练脚本

python main/rl/train.py task=ResDexHand dexhand=inspire side=BiH headless=true num_envs=4096 learning_rate=2e-4 test=false randomStateInit=true dataIndices=[20aed@0] rh_base_model_checkpoint=assets/imitator_rh_inspire.pth lh_base_model_checkpoint=assets/imitator_lh_inspire.pth early_stop_epochs=1000 actionsMovingAverage=0.4 experiment=cross_20aed@0_inspire
  1. 运行 python main/rl/train.py task=ResDexHand 时发生了什么

  1. 这坨 OmegaConf 是什么,怎么组织语法实现lambda函数的?

下图为 lib 库 的 __init__ 函数

1. OmegaConf 是什么? OmegaConf 是一个用于处理层级化配置(如 YAML 文件)的 Python 库。Hydra 框架在底层深度使用了 OmegaConf。它的主要优点是能够将来自文件、命令行等多个来源的配置信息合并成一个统一的对象,并且支持动态计算和变量替换。

2. register_new_resolver 是做什么的? 这个函数的作用是向 OmegaConf 注册一个新的“解析器”(resolver)。解析器本质上就是一个自定义函数,你可以在 .yaml 配置文件中通过 ${} 语法来调用它,从而实现动态生成配置值。这极大地增强了静态配置文件的灵活性。

语法组织和 lambda 函数的实现register_new_resolver 的语法结构非常直观: OmegaConf.register_new_resolver("解析器的名字", 实现该功能的函数)

  • 第一个参数 是一个字符串,即你在 .yaml 文件中调用的名字。例如 "find_rl_train_config"

  • 第二个参数 是一个 Python 函数,它定义了当解析器被调用时应该执行的操作。

在这个项目中,为了代码简洁,开发者大量使用了 lambda 函数 作为第二个参数。lambda 函数是一种无需使用 def 关键字就能定义函数的简化写法,非常适合这种单行就能完成的简单功能。

  1. 这个 ... 语法是 Hydra/OmegaConf 框架中用来访问不同层级配置参数的相对路径表示法

  • ${...parameter}: 从当前位置向上返回 2 级,然后寻找 parameter

例如

它的意思是,这个文件中的 seed 参数的值,需要从上两级的配置文件中去获取。根据我们之前的分析,这个顶层文件就是 main/cfg/config.yaml

在之前我们查看过的 config.yaml 文件中,有这样一行定义了 seed 的默认值:

seed: 42


评论