hydra小记(一):深入理解 Hydra:instantiate 与 get_class 的区别
深入理解 Hydra:instantiate() 与 get_class() 的区别
在使用 Hydra 进行配置驱动的开发时,我们常常会用到两个实用函数:hydra.utils.instantiate() 和 hydra.utils.get_class()。虽然它们看起来都与对象的创建有关,但各自的用途和行为有明显区别。下面我们详细解释它们各自的工作模式,并提供示例帮助你在博客中讲解。
1. hydra.utils.get_class()
作用:
该函数仅仅用于从配置中获取目标类的对象,不会执行实例化。换句话说,它根据配置中指定的类的全限定名称(字符串)返回对应的类对象。
工作原理:
- 输入:一个包含
_target_
键的配置字典,其中_target_
的值是类的全限定名称,如"my_module.MyClass"
。 - 处理:解析这个字符串,导入模块并返回类对象。
- 输出:返回目标类本身,而不是实例。
示例:
# 配置文件中的内容
cfg = {
"_target_": "my_module.MyClass",
"param1": 10,
"param2": "hello"
}
# 使用 get_class() 获取类对象
cls = hydra.utils.get_class(cfg["_target_"])
# 此时 cls 指向 my_module.MyClass 类
# 后续可以自行调用构造器来创建实例/对象
instance = cls(param1=cfg["param1"], param2=cfg["param2"])
也可以添加: my_module_MyClass
作为说明,不影响任何程序操作。
instance: my_module_MyClass = cls(param1=cfg["param1"], param2=cfg["param2"])
总结:
- 主要用途:获取类对象,便于后续自行调用构造函数或进行进一步的操作。
- 注意事项:它不会自动传入配置中其他参数,需手动构造实例。
2. hydra.utils.instantiate()
作用:
该函数是一站式的实例化工具。它不仅会根据配置中 _target_
指定的字符串查找目标类,还会自动提取配置中其他键值,并将其作为关键字参数传递给该类的构造函数,直接返回一个实例对象。
工作原理:
- 输入:一个配置字典,必须包含
_target_
键和其他初始化参数。 - 处理:
- 读取
_target_
字段,获取目标类。 - 将配置中除
_target_
外的所有参数作为关键字参数传递给目标类的构造函数。 - 如果配置中包含嵌套的配置项,
instantiate()
会递归地实例化这些嵌套对象。
- 读取
- 输出:返回目标类的实例。
示例:
# 配置文件中的内容
cfg = {
"policy": {
"_target_": "my_module.MyPolicy",
"cond_predict_scale": True,
"crop_shape": [84, 84],
"diffusion_step_embed_dim": 128
}
}
# 使用 instantiate() 自动创建实例
model = hydra.utils.instantiate(cfg["policy"])
# 此时 model 已经是 my_module.MyPolicy(param1=True, crop_shape=[84,84], diffusion_step_embed_dim=128) 的实例
总结:
- 主要用途:直接实例化对象,无需手动传递参数,适用于配置驱动的对象创建。
- 优点:提高代码简洁性和灵活性,允许轻松更改实例化类或参数而无需改动代码。
3. 总结对比
特性 | hydra.utils.get_class() | hydra.utils.instantiate() |
---|---|---|
返回内容 | 返回目标类对象 | 返回目标类的实例对象 |
是否调用构造器 | 否,仅返回类 | 是,自动调用构造函数并传入配置中所有参数 |
配置要求 | 需要包含 _target_ 字段,但不使用其他参数 | 必须包含 _target_ ,其他键值作为初始化参数传入 |
使用场景 | 获取类对象供后续手动实例化或其他用途 | 一站式对象实例化,适合配置驱动编程,快速创建实例 |
通过理解这两个函数的区别,你可以更加灵活地设计你的配置结构,并根据需求选择合适的实例化方式。对于需要手动干预实例化过程的场景,可以使用 get_class();而在大多数标准配置驱动的场景下,instantiate() 提供了便捷且高效的方式来生成对象实例。