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
问题二:为什么
- /agent/...
这样的路径就能覆盖参数?而不是 key-value 的形式
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
前面都是提及了一些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"
。动态地导入并创建这个类的实例
嵌套实例化
# @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
运行
python main/rl/train.py task=ResDexHand
时发生了什么
这坨 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
关键字就能定义函数的简化写法,非常适合这种单行就能完成的简单功能。
这个
...
语法是 Hydra/OmegaConf 框架中用来访问不同层级配置参数的相对路径表示法。
${...parameter}
: 从当前位置向上返回 2 级,然后寻找parameter
。
例如
它的意思是,这个文件中的 seed
参数的值,需要从上两级的配置文件中去获取。根据我们之前的分析,这个顶层文件就是 main/cfg/config.yaml
。
在之前我们查看过的 config.yaml
文件中,有这样一行定义了 seed
的默认值:
seed: 42