from_modules¶
- class tensordict.from_modules(*modules, as_module: bool = False, lock: bool = True, use_state_dict: bool = False, lazy_stack: bool = False, expand_identical: bool = False)¶
检索多个模块的参数,用于集成学习/通过 vmap 实现的特性应用。
- 参数:
modules (nn.Module 序列) – 需要从中获取参数的模块。如果模块结构不同,则需要惰性堆叠(请参阅下面的
lazy_stack
参数)。- 关键字参数:
as_module (bool, 可选) – 如果为
True
,将返回一个TensorDictParams
实例,该实例可用于在torch.nn.Module
中存储参数。默认为False
。lock (bool, 可选) – 如果为
True
,则结果 tensordict 将被锁定。默认为True
。use_state_dict (bool, 可选) –
如果为
True
,将使用模块的 state-dict,并将其展开为具有模型树状结构的 TensorDict。默认为False
。注意
这在必须使用 state-dict 钩子时特别有用。
lazy_stack (bool, 可选) –
参数应该密集堆叠还是惰性堆叠。默认为
False
(密集堆叠)。注意
lazy_stack
和as_module
是互斥特性。警告
惰性输出和非惰性输出之间存在关键差异:非惰性输出将重新实例化具有所需批量大小的参数,而
lazy_stack
仅将参数表示为惰性堆叠。这意味着当lazy_stack=True
时,原始参数可以安全地传递给优化器,而当设置为True
时,需要传递新参数。警告
虽然使用惰性堆叠来保留原始参数引用可能很诱人,但请记住,每次调用
get()
时,惰性堆叠都会执行一次堆叠操作。这需要计算内存(参数大小的 N 倍,如果构建了计算图则更多)和时间。这也意味着优化器将包含更多参数,并且step()
或zero_grad()
等操作将需要更长时间执行。通常,lazy_stack
应该仅保留给极少数用例。expand_identical (bool, 可选) – 如果为
True
且同一参数(相同标识)被堆叠到自身,则将转而返回此参数的扩展版本。当lazy_stack=True
时,此参数将被忽略。
示例
>>> from torch import nn >>> from tensordict import from_modules >>> torch.manual_seed(0) >>> empty_module = nn.Linear(3, 4, device="meta") >>> n_models = 2 >>> modules = [nn.Linear(3, 4) for _ in range(n_models)] >>> params = from_modules(*modules) >>> print(params) TensorDict( fields={ bias: Parameter(shape=torch.Size([2, 4]), device=cpu, dtype=torch.float32, is_shared=False), weight: Parameter(shape=torch.Size([2, 4, 3]), device=cpu, dtype=torch.float32, is_shared=False)}, batch_size=torch.Size([2]), device=None, is_shared=False) >>> # example of batch execution >>> def exec_module(params, x): ... with params.to_module(empty_module): ... return empty_module(x) >>> x = torch.randn(3) >>> y = torch.vmap(exec_module, (0, None))(params, x) >>> assert y.shape == (n_models, 4) >>> # since lazy_stack = False, backprop leaves the original params untouched >>> y.sum().backward() >>> assert params["weight"].grad.norm() > 0 >>> assert modules[0].weight.grad is None
当
lazy_stack=True
时,情况略有不同>>> params = TensorDict.from_modules(*modules, lazy_stack=True) >>> print(params) LazyStackedTensorDict( fields={ bias: Tensor(shape=torch.Size([2, 4]), device=cpu, dtype=torch.float32, is_shared=False), weight: Tensor(shape=torch.Size([2, 4, 3]), device=cpu, dtype=torch.float32, is_shared=False)}, exclusive_fields={ }, batch_size=torch.Size([2]), device=None, is_shared=False, stack_dim=0) >>> # example of batch execution >>> y = torch.vmap(exec_module, (0, None))(params, x) >>> assert y.shape == (n_models, 4) >>> y.sum().backward() >>> assert modules[0].weight.grad is not None