• 文档 >
  • 模块代码 >
  • torch >
  • torch.nn.modules 下的 module 模块
快捷键

torch.nn.modules.module 的源代码

# mypy: 允许未类型化定义

导入 functools
导入 检查
导入 itertools
导入 警告
导入 弱引用
来自 集合 导入 命名元组, OrderedDict
来自 collections.abc 导入 迭代器, 映射
来自 打字 导入 任意, 可调用, 可选, 过载, 类型变量, 联合
来自 typing_extensions 导入 自身

导入 火炬
来自 火炬 导入 设备, 数据类型, 张量
来自 torch._prims_common 导入 DeviceLikeType
来自 torch.nn 参数 导入 缓冲区, 参数
来自 torch.utils._python_dispatch 导入 可追踪包装子类
来自 torch.utils.hooks 导入 向后钩, 可移除句柄


__all__ = [
    注册模块前向预处理钩子,
    注册模块前向钩子,
    "注册模块完整反向钩子",
    "注册模块反向钩子",
    "注册模块完整反向钩子",
    "注册模块缓冲区注册钩子",
    "注册模块模块注册钩子",
    "注册模块参数注册钩子",
    "模块",
]

_grad_t = 联盟[元组[张量, ...] 张量]
# 请参阅 https://mypy.readthedocs.io/en/latest/generics.html#generic-methods-and-generic-self 了解用法
要注解`self`的`T`的数量。许多`Module`的方法返回`self`,我们希望那些返回值是
子类的类型,而不是`Module`的更宽松类型。
T = 类型变量(T, 绑定="模块")


 _不兼容键(
    命名元组("不兼容的键", ["缺少的键", "意外的键")]
):
    __slots__ = ()

    def __repr__(self):
        如果 not self.缺少键  not self.预期之外的键:
            返回 "<所有键匹配成功>"
        返回 超级().__repr__()

    __str__ = __repr__


def _addindent(s_, numSpaces):
    s = s_.分割("输入文本翻译为简体中文为:\n")
    #不要对单行内容进行操作
    如果 长度(s) == 1:
        返回 s_
    第一 = s.弹出(0)
    s = [空格数量 * 输入文本为空,请提供需要翻译的文本) +     s]
    s = "输入文本翻译为简体中文为:\n".加入(s)
    s = 第一 + "输入文本翻译为简体中文为:\n" + s
    返回 s


r"""这跟踪所有模块在执行前立即执行的常见钩子
注册缓冲区/模块/参数"""
全局缓冲区注册钩子: 字典[int, 可调用] = 有序字典()
全局模块注册钩子: 字典[int, 可调用] = 有序字典()
全局参数注册钩子: 字典[int, 可调用] = 有序字典()


 包装钩子:
    def 初始化(self, hook: 可调用, 模块: 可选["模块"] = ):
        self.hook: 可调用 = 钩子
        functools.更新包装器(self, hook)

        self.使用模块: 布尔类型 = 

        如果 模块  not :
            self.模块: 弱引用.参考类型[模块] = 弱引用.ref(模块)
            self.with_module = 真实

    def __调用__(self, *参数: 任意, **kwargs: 任意) -> 任意:
        如果 self.使用模块:
            模块 = self.模块()
            如果 模块  :
                提升 运行时错误("你正在尝试调用已死亡模块的钩子!")
            返回 self.hook(模块, *参数, **kwargs)
        返回 self.hook(*参数, **kwargs)

    def __getstate__(self) -> 字典:
        结果 = {钩子: self.hook, with_module: self.使用模块}
        如果 self.使用模块:
            结果[模块] = self.模块()

        返回 结果

    def __setstate__(self, 状态: 字典):
        self.钩子 = 状态[钩子]
        self.with_module = 状态[with_module]

        如果 self.使用模块:
            如果 状态[模块]  :
                提升 运行时错误(
                    "您正在尝试复活已死亡的模块的钩子!"
                )
            self.模块 = 弱引用.ref(状态[模块])


r"这跟踪了所有模块共有的钩子,这些钩子在模块执行前后被调用。"
这些是用于调试/性能分析的全局状态。
目的
_全局反向前钩子: 字典[int, 可调用] = 有序字典()
_全局反向钩子: 字典[int, 可调用] = 有序字典()
_全局是否完全反向钩子: 可选[布尔] = 
_全局前置钩子: 字典[int, 可调用] = 有序字典()
_全局正向钩子: 字典[int, 可调用] = 有序字典()
_全局前进钩子始终被调用: 字典[int, 布尔] = 有序字典()
_global_forward_hooks_with_kwargs: 字典[int, 布尔] = 有序字典()

_EXTRA_STATE_KEY_SUFFIX = "_extra_state"


[文档]def 注册模块缓冲区注册钩子( 钩子: 可调用[...None], ) -> RemovableHandle: 注册所有模块通用的缓冲区注册钩子。 .. 警告 :: 这将为 `nn.Module` 模块添加全局状态 每次调用 :func:`register_buffer` 时都会调用此钩子。 它应该具有以下签名:: 钩子可以修改输入或返回单个修改后的值。 钩子可以修改输入或返回单个修改后的值。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ handle = RemovableHandle(_global_buffer_registration_hooks) _global_buffer_registration_hooks[handle.id] = hook return handle
[文档]def register_module_module_registration_hook( 钩子: Callable[..., None], ) -> RemovableHandle: r"""注册一个对所有模块都通用的模块注册钩子。 ..警告:: 这将为`nn.Module`模块添加全局状态 每次调用`:func:`register_module`时都会调用此钩子。 它应该具有以下签名:: hook(module, name, submodule) -> None 或新子模块 钩子可以修改输入或返回单个修改后的值 返回: class:`torch.utils.hooks.RemovableHandle`: 可以用来通过调用 handle.remove()移除已添加的钩子的句柄 ``handle.remove()`` """ handle = RemovableHandle(_global_module_registration_hooks) _global_module_registration_hooks[handle.id] = hook return handle
[文档]def register_module_parameter_registration_hook( hook: Callable[..., None], ) -> RemovableHandle: 注册所有模块通用的参数注册钩子。 .. 警告 :: 这将为 `nn.Module` 模块添加全局状态 每次调用 :func:`register_parameter` 时都会调用此钩子。 它应该具有以下签名:: 钩子(module, name, param) -> None 或新的参数 钩子可以修改输入或返回单个修改后的值。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ handle = RemovableHandle(_global_parameter_registration_hooks) _global_parameter_registration_hooks[handle.id] = hook return handle
[文档]def register_module_forward_pre_hook(hook: Callable[..., None]) -> RemovableHandle: r"""注册所有模块通用的前向钩子。 .. 警告 :: 这将为 `nn.module` 模块添加全局状态 仅用于调试/性能分析目的。 钩子将在每次调用 :func:`forward` 之前被调用。 它应该具有以下签名: hook(模块, 输入) -> 无或修改后的输入 输入仅包含传递给模块的位置参数。 关键字参数不会传递给钩子,只传递给 `forward`。 钩子可以修改输入。用户可以返回一个元组或一个 钩子中单个修改的值。我们将值包装成一个元组 如果返回单个值(除非该值已经是元组)。 此钩子优先于已注册到特定模块的钩子。 ``register_forward_pre_hook``。 返回: `torch.utils.hooks.RemovableHandle`: 可以用来通过调用 `handle.remove()` 移除已添加的钩子的句柄 ``handle.remove()`` """ handle = RemovableHandle(_global_forward_pre_hooks) _global_forward_pre_hooks[handle.id] = hook return handle
[文档]def register_module_forward_hook( hook: 可调用函数[...None], *, with_kwargs: 布尔型 = False, always_call: 布尔型 = False, ) -> RemovableHandle: 注册全局前向钩子,适用于所有模块。 .. 警告 :: 这将为 `nn.module` 模块添加全局状态 仅用于调试/性能分析目的。 钩子将在每个 :func:`forward` 计算输出之后被调用。 它应该具有以下签名: hook(模块, 输入, 输出) -> 无或修改后的输出 输入仅包含传递给模块的位置参数。 关键字参数不会传递给钩子,只会传递给 `forward`。 您可以选择性地通过返回新值来修改模块的输出。 该值将替换来自 :func:`forward` 函数的输出。 参数: 钩子(Callable):用户定义的注册钩子。 总是调用(布尔值):如果为 ``True``,则无论何种情况都会运行 ``hook`` 是否在调用模块时引发异常。 默认:``False`` 返回: class:`torch.utils.hooks.RemovableHandle`: 可以通过调用来移除已添加的钩子的句柄 ``handle.remove()`` 此钩子将在注册特定模块钩子之前执行 ``register_forward_hook``. """ handle = RemovableHandle( _global_forward_hooks, extra_dict=_global_forward_hooks_always_called ) _global_forward_hooks[handle.id] = hook 如果使用 with_kwargs: _global_forward_hooks_with_kwargs[handle.id] = True 如果总是调用: _global_forward_hooks_always_called[handle.id] = True 返回处理
[文档]def 注册模块反向钩子( 钩子: Callable[["模块", _grad_t, _grad_t], Union[None, _grad_t]], ) -> 可移除句柄: 注册对所有模块通用的反向钩子。 此函数已被弃用,推荐使用 func:`torch.nn.modules.module.register_module_full_backward_hook` ,并且此函数的行为将在未来的版本中发生变化。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ global _global_is_full_backward_hook 如果 _global_is_full_backward_hook 为 True: 抛出 RuntimeError( "不能同时使用常规反向钩子和完整反向钩子作为全局模块钩子。请只使用其中一个。" "全局模块钩子。请只使用其中一个。" ) _global_is_full_backward_hook = False handle = RemovableHandle(_global_backward_hooks) _global_backward_hooks[handle.id] = hook return handle
[文档]def register_module_full_backward_pre_hook( hook: Callable[["模块", _grad_t], Union[None, _grad_t]], ) -> RemovableHandle: r"""注册所有模块通用的反向前钩子。 ..警告:: 这将为`nn.module`模块添加全局状态 并且仅适用于调试/性能分析目的。 使用此函数注册的钩子行为与那些 通过 :meth:`torch.nn.Module.register_full_backward_pre_hook` 注册。 更多详情请参阅其文档。 使用此函数注册的钩子将在使用 :meth:`torch.nn.Module.register_full_backward_pre_hook` 注册的钩子之前被调用。 使用 :meth:`torch.nn.Module.register_full_backward_pre_hook` 注册的钩子之前被调用。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ handle = RemovableHandle(_global_backward_pre_hooks) _global_backward_pre_hooks[handle.id] = hook return handle
[文档]def register_module_full_backward_hook( hook: Callable[["模块", _grad_t, _grad_t], Union[None, _grad_t]], ) -> RemovableHandle: r"""注册适用于所有模块的通用反向钩子。 ..警告:: 这将为`nn.module`模块添加全局状态 并且仅适用于调试/性能分析目的。 使用此函数注册的钩子行为与那些 通过 :meth:`torch.nn.Module.register_full_backward_hook` 注册。 更多详情请参阅其文档。 使用此函数注册的钩子将在使用 :meth:`torch.nn.Module.register_full_backward_hook` 注册的钩子之前调用。 使用 :meth:`torch.nn.Module.register_full_backward_hook` 注册的钩子。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ global _global_is_full_backward_hook 如果 _global_is_full_backward_hook 为 False: 抛出 RuntimeError( "不能同时使用常规反向钩子和完整反向钩子作为全局模块钩子。请只使用其中一个。" "全局模块钩子。请只使用其中一个。" ) _global_is_full_backward_hook = True handle = RemovableHandle(_global_backward_hooks) _global_backward_hooks[handle.id] = hook return handle
# 欺骗 mypy 不应用逆变规则到输入,通过定义 # 将值作为函数,而不是函数。另请参阅 # https://github.com/python/mypy/issues/8795 def _未实现的前向
(self, *输入: 任意) -> : r"""定义每次调用时执行的计算。 应被所有子类覆盖。 .. 注意:: 尽管前向传播的算法需要在内部定义 此函数之后应调用 :class:`Module` 实例 而不是这个,因为前者负责运行 注册的钩子,而后者则静默忽略它们。 "源代码" 提升 不支持的操作异常( f模块[{类型(self).__name__}缺少所需的 "forward" 函数 )
[文档] 模块: r神经网络模块的基类。 您的模型也应该继承这个类。 模块还可以包含其他模块,允许它们以嵌套形式存在。 您可以将子模块作为常规属性分配,形成树状结构。 导入 torch.nn 作为 nn 导入 torch.nn.functional 作为 F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) 返回 F.relu(self.conv2(x)) 这种方式分配的子模块将被注册,并且也将被注册 参数在调用 :meth:`to` 等时被转换。 .. 注意:: 根据上述示例,对父类进行 `__init__()` 调用 必须在分配给子对象之前进行。 ivar training: 布尔值表示此模块是否处于训练或 评估模式。 vartype training: bool "源代码" 导出补丁: 布尔类型 = _版本: 整型 = 1 r这允许对 :meth:`load_state_dict` 的更好向后兼容性支持。 :meth:`state_dict`, 版本号将保存为属性中 返回状态字典的 `_metadata`,因此被序列化。`_metadata` 是 字典的键遵循 state dict 的命名约定。 从状态字典加载的用法说明。 如果从模块中添加/删除新参数/缓冲区,此数值应 被更新,并且模块的 `_load_from_state_dict` 方法可以比较 版本号,如果状态字典来自之前,则进行适当的更改 "变化。” 训练: 布尔类型 参数: 字典[字符串, 可选[参数]] _缓冲区: 字典[字符串, 可选[张量]] _非持久缓冲区集合: 集合[字符串] _backward_pre_hooks: 字典[int, 可调用] _backward_hooks: 字典[int, 可调用] _is_full_backward_hook: 可选[布尔] _前向钩子: 字典[int, 可调用] 标记相应的前向钩子是否接受 kwargs 由于 JIT 不支持 set[int],因此此字典用作集合,其中所有 此字典中的钩子接受 kwargs 参数。 _forward_hooks_with_kwargs: 字典[int, 布尔] 即使抛出异常也应始终调用的前向钩子 _forward_hooks_always_called: 字典[int, 布尔] _前向预处理钩子: 字典[int, 可调用] 标记相应的前向钩子是否接受 kwargs 由于 JIT 不支持 set[int],因此此字典用作集合,其中所有 此字典中的钩子接受 kwargs 参数。 _forward_pre_hooks_with_kwargs: 字典[int, 布尔] 状态字典钩子: 字典[int, 可调用] _load_state_dict_pre_hooks: 字典[int, 可调用] _state_dict_pre_hooks: 字典[int, 可调用] 加载状态字典后钩子: 字典[int, 可调用] 模块: 字典[字符串, 可选["模块"]] 调用父类初始化方法: 布尔类型 = _编译调用实现: 可选[可调用] = def 初始化(self, *参数, **kwargs) -> : 初始化内部模块状态,由 nn.Module 和 ScriptModule 共享。 火炬._C._log_api_usage_once(python.nn_module) 向后兼容:当 call_super_init=False 时,不允许使用参数。 如果 self.调用父类的 init 方法 布尔(kwargs): 提升 类型错误( f"{类型(self).__name__}'__init__' 方法收到一个意外的关键字参数 '{下一(迭代(kwargs))} 请提供需要翻译的文本 ) 如果 self.调用父类的 init 方法 布尔(参数): 提升 类型错误( f"{类型(self).__name__}`.__init__()` 函数接收 1 个位置参数但{长度(参数) + 1} "赋予" ) "" 调用 super().__setattr__('a', a) 而不是典型的 self.a = a 为了避免 Module.__setattr__ 的开销。Module 的 __setattr__ 有特殊 处理参数、子模块和缓冲区,但仅调用 super().__setattr__用于所有其他属性。 "源代码" 超级().__setattr__("训练", True) 超级().__setattr__(_参数, {}) 超级().__setattr__(_缓冲区, {}) 超级().__setattr__(非持久缓冲区设置, 集合()) 超级().__setattr__(向后预处理钩子, 有序字典()) 超级().__setattr__("_backward_hooks", 有序字典()) 超级().__setattr__("_is_full_backward_hook", ) 超级().__setattr__("_forward_hooks", 有序字典()) 超级().__setattr__("_forward_hooks_with_kwargs", 有序字典()) 超级().__setattr__("_forward_hooks_always_called", 有序字典()) 超级().__setattr__("_forward_pre_hooks", 有序字典()) 超级().__setattr__("_forward_pre_hooks_with_kwargs", 有序字典()) 超级().__setattr__("_状态字典挂钩", 有序字典()) 超级().__setattr__("_state_dict_pre_hooks", 有序字典()) 超级().__setattr__("_加载状态字典前挂钩", 有序字典()) 超级().__setattr__("_load_state_dict_post_hooks", 有序字典()) 超级().__setattr__(_模块, {}) 如果 self.调用父类初始化方法: 超级().初始化(*参数, **kwargs) 前向: 可调用[..., 任意] = _未实现的功能
[文档] def 注册缓冲区( self, 名称: 字符串, 张量: 可选[张量] 持久性: 布尔类型 = 真实 ) -> : r在模块中添加一个缓冲区。 这通常用于注册不应被视为模型参数的缓冲区。例如,BatchNorm 的`running_mean` 通常是用于注册不应被视为模型参数的缓冲区。例如,BatchNorm 的`running_mean` 不是参数,而是模块状态的一部分。缓冲区默认情况下是持久的,将与参数一起保存。此行为可以通过将:attr:`persistent` 设置为 ``False`` 来更改。持久缓冲区与非持久缓冲区之间的唯一区别 默认情况下,是持久的,将与参数一起保存。此行为可以通过将:attr:`persistent` 设置为 ``False`` 来更改。持久缓冲区与非持久缓冲区之间的唯一区别 的行为可以通过将:attr:`persistent` 设置为 ``False`` 来更改。持久缓冲区与非持久缓冲区之间的唯一区别 的唯一区别在于持久缓冲区和非持久缓冲区 这后者将不会是本模块的一部分 attr:`状态字典`。 缓冲区可以通过给定的名称作为属性进行访问。 Args: 名称(str):缓冲区的名称。缓冲区可以通过名称访问 使用给定的名称从该模块中 张量(Tensor 或 None):要注册的缓冲区。如果为 ``None``,则忽略在缓冲区上运行的运算,例如 :attr:`cuda`。 如果为 ``None``,则该缓冲区 **不会** 包含在模块的 :attr:`state_dict` 中。 该缓冲区 **不会** 包含在模块的 :attr:`state_dict` 中。 持久化(布尔值):缓冲区是否属于此模块的一部分 attr:`状态字典`。 示例:: >>> # xdoctest: +SKIP("undefined vars") >>> self.register_buffer('running_mean', torch.zeros(num_features)) "源代码" 如果 持久 isinstance(self, 火炬.算子.脚本模块): 提升 运行时错误(ScriptModule 不支持非持久化缓冲区) 如果 "_缓冲区" not self.字典: 提升 属性错误("在调用 Module.__init__() 之前不能分配缓冲区") elif not isinstance(名称, 字符串): 提升 类型错误( f"缓冲区名称应该是字符串。得到"{火炬.类型名(名称)}" ) elif "." 名称: 提升 键错误(缓冲区名称可以t contain “.”) elif 名称 == "": 提升 键错误(缓冲区名称可以t 可以为空字符串 "") elif 有属性(self, 名称) 名称 not self._缓冲区: 提升 键错误(f"属性 '{名称}已存在) elif 张量 not not isinstance(张量, 火炬.张量): 提升 类型错误( f"无法分配"{火炬.类型名(张量)}对象到缓冲区{名称}' " "需要(torch Tensor 或 None)" ) 否则: 钩子 全局缓冲区注册钩子.(): 输出 = hook(self, 名称, 张量) 如果 输出 not : 张量 = 输出 self._缓冲区[名称] = 张量 如果 持久性: self._非持久缓冲区集合.丢弃(名称) 否则: self._非持久缓冲区集合.添加(名称)
[文档] def register_parameter(self, name: str, param: Optional[Parameter]) -> None: r"""添加模块参数。 可以使用给定的名称将该参数作为属性访问。 参数: 参数名称(str):参数的名称。可以访问 从本模块使用给定名称 参数(参数或 None):要添加到模块的参数。如果 ``None``,然后运行在参数上的操作,例如::attr:`cuda` 忽略。如果为 ``None``,则 **不** 包含该参数。 模块的 :attr:`state_dict`。 """ 如果 "_parameters" 不在 self.__dict__ 中: raise AttributeError( "无法在调用 Module.__init__() 之前分配参数" ) elif not isinstance(name, str): raise TypeError( f"参数名称应该是一个字符串。获取 {torch.typename(name)}" ) elif "." in name: 抛出 KeyError('参数名称不能包含 "."') elif name == "" 抛出 KeyError('参数名称不能为空字符串 ""') elif hasattr(self, name) and name not in self._parameters: "引发 KeyError(f"属性 '{name}' 已存在") 如果 param 为 None: self._parameters[name] = None elif not isinstance(param, Parameter): raise TypeError( 无法将 '{torch.typename(param)}' 对象分配给参数 '{name}' "(需要 torch.nn.Parameter 或 None)" ) elif param.grad_fn: raise ValueError( f"无法将非叶 Tensor 分配给参数'{name}'。模型 " f"参数必须显式创建。要表示'{name}' " 作为另一个张量的函数,计算其值 forward() 方法。 ) else: for hook in _global_parameter_registration_hooks.values(): output = hook(self, name, param) if output is not None: param = output self._参数[name] = param
[文档] def add_module(self, name: str, module: Optional["Module"]) -> None: r"""添加当前模块的子模块。 可以使用给定的名称将该模块作为属性访问。 参数: name (str): 子模块名称。子模块可以通过给定的名称从本模块访问。 使用该名称从本模块访问子模块 module (Module): 要添加到模块中的子模块。 """ 如果不是 module 是 Module 的子类且 module 不为 None: raise TypeError(f"{torch.typename(module)} 不是一个 Module 子类") elif not isinstance(name, str): raise TypeError( 模块名称应该是一个字符串。获取 {torch.typename(name)} ) 如果 hasattr(self, name) 且 name 不在 self._modules 中: 引发 KeyError(f'属性 '{name}' 已存在') elif "." in name: raise KeyError(f'module name can\'t contain ".", got: {name}') elif name == "": raise KeyError('module name can\'t be empty string ""') for hook in _global_module_registration_hooks.values(): output = hook(self, name, module) if output is not None: module = output self._modules[name] = 模块
[文档] def register_module(self, name: str, module: Optional["Module"]) -> None: r"""别名::func:`add_module`""" self.add_module(name, module)
[文档] def 获取子模块(self, 目标: 字符串) -> "模块": "如果存在,则返回由 `target` 指定的子模块,否则抛出错误。" 例如,假设你有一个 `nn.Module` 类型的 `A` 模块, 看起来像这样: .. 代码块:: text A( (net_b): 模块( (net_c): 模块( (conv): 卷积层 2d(16, 33, 核大小=(3, 3), 步长=(2, 2)) ) (线性): 线性(in_features=100, out_features=200, bias=True) ) ) (图示一个名为 ``nn.Module`` 的 ``A`` 模块。``A`` 模块包含一个嵌套的 子模块 ``net_b``,该子模块本身又包含两个子模块 ``net_c`` 和 ``linear``。然后 ``net_c`` 模块包含一个子模块 ``conv``。) 检查我们是否有“linear”子模块 将 `get_submodule("net_b.linear")` 调用。为了检查 我们有 `conv` 子模块,我们会调用 获取子模块("net_b.net_c.conv")。 ``get_submodule`` 的运行时间受 ``target`` 中模块嵌套程度的限制 对 ``target`` 的查询 `named_modules` 实现了相同的结果,但它是 O(N) 的 传递模数的数量。因此,为了进行简单的检查, 如果某些子模块存在,`get_submodule` 应始终 已使用。 Args: 目标:子模块的完全限定字符串名称 寻找。 (参见上方示例了解如何指定完全限定的字符串。) 模块:设置子模块的模块。 返回: torch.nn.Module:由 `target` 引用的子模块 抛出异常: AttributeError:如果在由路径导致的任何点,路径解析到一个不存在的属性名或不是`nn.Module`的实例。 目标字符串的(子)路径解析到一个不存在的 如果属性名不存在或不是`nn.Module`的实例。 "源代码" 如果 目标 == "": 返回 self 原子: 列表[字符串] = 目标.分割(“点”) 模块: 火炬.nn.模块 = self 项目 原子: 如果 not 有属性(模块, 项目): 提升 属性错误( 模块._获取名称() + "没有属性“” + 项目 + ` ) 修饰 = getattr(模块, 项目) 如果 not isinstance(模块, 火炬.nn.模块): 提升 属性错误(` + 项目 + "“”不是一个 nn.Module") 返回 模块
[文档] def 设置子模块( self, 目标: 字符串, 模块: "模块", 严格的: 布尔类型 = ) -> : "" 如果存在,设置由`target`指定的子模块,否则抛出错误。 .. 注意:: 如果`strict`设置为`False`(默认),则该方法将替换现有的子模块 或者如果父模块存在,则创建一个新的子模块。如果将 `strict` 设置为 `True`, 该方法将仅尝试替换现有的子模块,如果子模块不存在,则抛出错误。 例如,假设你有一个 `nn.Module` 类型的 `A` 模块, 例如,假设你有一个 `nn.Module` 类型的 `A` 模块, 看起来像这样: .. 代码块:: text A( (net_b): 模块( (net_c): 模块( (conv): Conv2d(3, 3, 3) ) (linear): Linear(3, 3) ) ) (图示为 ``nn.Module`` 的 ``A``。``A`` 包含一个嵌套的 子模块 ``net_b``,该子模块本身又包含两个子模块 ``net_c`` 和 ``linear``。然后 ``net_c`` 模块包含一个子模块 ``conv``。) 要用新的子模块 `Linear` 覆盖 `Conv2d`, 可以调用 `set_submodule("net_b.net_c.conv", nn.Linear(1, 1))` 其中 `strict` 可以是 `True` 或 `False` 要将新的子模块 `Conv2d` 添加到现有的 `net_b` 模块中, 你将调用 `set_submodule("net_b.conv", nn.Conv2d(1, 1, 1))`。 在上面的代码中,如果你将 `strict=True` 设置为 True 并调用 `set_submodule("net_b.conv", nn.Conv2d(1, 1, 1), strict=True)`,将会引发一个 AttributeError 异常, 因为 `net_b` 没有名为 `conv` 的子模块。 Args: 目标:子模块的完全限定字符串名称 寻找。 (参见上方示例了解如何指定完全限定的字符串。) 模块:设置子模块的模块。 模块:设置子模块的模块。 严格:如果 `False`,该方法将替换现有的子模块 或如果父模块存在,则创建一个新的子模块。如果 ``True``, 该方法将仅尝试替换现有子模块并抛出错误 如果子模块已经存在。 抛出异常: ValueError:如果`target`字符串为空或者`module`不是`nn.Module`的实例。 AttributeError:如果在由路径导致的任何点,路径解析到一个不存在的属性名或不是`nn.Module`的实例。 在`target`字符串中,如果(子)路径解析到一个不存在的属性名或不是`nn.Module`的实例。 如果属性名不存在或不是`nn.Module`的实例。 "源代码" 如果 目标 == "": 提升 ValueError(无法设置没有目标名称的子模块!) 原子: 列表[字符串] = 目标.分割(“点”) 如果 not isinstance(模块, 火炬.nn.模块): 提升 ValueError( ` + "模块" + f`不是 nn.Module,找到{类型(模块)}" ) 如果 长度(原子) == 1: 父节点: 火炬.nn.模块 = self 否则: 父键 = “点”.加入(原子[-1]) 父级 = self.获取子模块(父键) 如果 严格的 not 有属性(父节点, 原子[-1)] 提升 属性错误( 父节点._获取名称() + "没有属性“” + 原子[-1] + ` ) 如果 有属性(父节点, 原子[-1)] 修饰 = getattr(父节点, 原子[-1]) 如果 not isinstance(模块, 火炬.nn.模块): 提升 属性错误(` + 原子[-1] + "“”不是一个 nn.Module") setattr(父节点, 原子[-1] 模块)
[文档] def get_parameter(self, target: str) -> "参数": 返回由 `target` 给定的参数(如果存在),否则抛出错误。 查看`get_submodule`的文档字符串以获取更详细的信息 本方法功能说明以及如何使用 正确指定 ``target``。 Args: target: 要查找的参数的完全限定字符串名称 (有关如何指定,请参阅 ``get_submodule``)。 完全限定的字符串。) 返回: torch.nn.Parameter:由 ``target`` 引用的参数 引发: 属性错误:如果目标字符串引用了无效的路径或解析为不是 的 ``nn.Parameter`` 的内容 """ module_path, _, param_name = target.rpartition(".") mod: torch.nn.Module = self.get_submodule(module_path) if not hasattr(mod, param_name): raise AttributeError( mod._get_name() 没有属性 `" + param_name + "`" ) param: torch.nn.Parameter = getattr(mod, param_name) 如果 param 不是 torch.nn.Parameter 类型: 抛出 AttributeError("`" + param_name + "` 不是一个 nn.Parameter") 返回 param
[文档] def get_buffer(self, target: str) -> "Tensor": 返回由 ``target`` 给定的缓冲区,如果存在,否则抛出错误。 查看文档字符串以获取 ``get_submodule`` 的更详细说明,以及此方法的功能以及如何正确指定 ``target``。 以及如何正确指定 ``target`` 的说明。 Args: 参数: 目标:缓冲区的完全限定字符串名称 查找。(有关如何指定,请参阅 ``get_submodule``) 完全限定的字符串。 返回: torch.Tensor:由“target”引用的缓冲区 引发异常: 属性错误:如果目标字符串引用无效 路径或解析为不是 缓冲区 """ 模块路径, _, 缓冲区名称 = target.rpartition(".") mod: torch.nn.Module = self.get_submodule(模块路径) 如果 mod 对象没有名为 buffer_name 的属性: 则抛出 AttributeError 异常( mod._get_name()方法返回的字符串 + " 没有属性 `" + buffer_name + "`" ) buffer: torch.Tensor = getattr(mod, buffer_name) if buffer_name not in mod._buffers: raise AttributeError("`" + buffer_name + "` is not a buffer") return buffer
[文档] def get_extra_state(self) -> 任意: 返回任何需要包含在模块的状态字典中的额外状态。 实现此功能以及为您的模块对应的 :func:`set_extra_state` 方法 如果您需要存储额外的状态。此函数在构建时被调用。 模块的 `state_dict()`。 注意额外的状态应该是可序列化的,以确保状态字典的序列化工作正常。 我们只为序列化张量提供向后兼容性保证。 其他对象可能会破坏向后兼容性,如果 他们的序列化 pickle 形式会改变。 返回: object:存储在模块的状态字典中的任何额外状态 """ raise RuntimeError( "在 Module.get_extra_state()中到达了一个不应该被调用的代码路径。" "请在此处提交一个问题:https://github.com/pytorch/pytorch/issues/new?template=bug-report.yml" "以报告此错误。" )
[文档] def set_extra_state(self, state: Any) -> None: """设置加载的 `state_dict` 中包含的额外状态。 此函数从 :func:`load_state_dict` 调用,用于处理任何额外状态 在`state_dict`中找到。实现此函数以及相应的 func:`get_extra_state`函数,如果你的模块需要在其`state_dict`中存储额外的状态 `state_dict`。 参数: state(字典):来自 `state_dict` 的额外状态 """ raise RuntimeError( "在 Module.set_extra_state() 中达到了一个不应该被调用的代码路径。" "请在此处提交问题:https://github.com/pytorch/pytorch/issues/new?template=bug-report.yml" "以报告此错误。" )
def 应用
(self, 函数, 递归=True): 如果 递归: 模块 self.儿童(): 模块.应用(函数) def compute 应该使用 set_data(张量, 张量应用): 如果 火炬.具有兼容的浅拷贝类型(张量, 张量应用): # 如果新张量与现有张量具有兼容的张量类型, 当前行为是使用 `.data=` 在原地更改张量。 # 和未来的行为是覆盖现有的张量。 修改当前行为是一个向后不兼容的变更,我们希望它 将在未来版本中实现。所以目前我们引入了 `torch.__future__.get_overwrite_module_params_on_conversion()` 全局标志,允许用户控制他们是否想要未来的 # 是否覆盖现有张量的行为。 返回 not 火炬.未来.获取转换时的覆盖模块参数() 否则: 返回 应使用交换张量 = ( 火炬.未来.在转换时获取交换模块参数() ) , 参数 self.参数.项目(): 如果 参数 : 继续 模块中存储的张量是图叶子节点,我们不希望 跟踪 `param_applied` 的 autograd 历史,因此我们必须使用 `with torch.no_grad():` 火炬.不梯度(): 应用参数 = 函数(参数) 应该使用 set_data = compute 应该使用 set_data(参数, 应用参数) 子类可能有多个子张量,因此我们需要使用 swap_tensors 应该使用交换张量 = ( 应使用交换张量 可追踪包装子类(应用参数) ) 参数梯度 = 参数.梯度 如果 应该使用 swap_tensors: try: 如果 参数梯度 not : 访问 param.grad 会使它的 at::Tensor 的使用计数变为 2,这将防止交换。 将梯度使用计数减至 None 参数.梯度 = 应用参数 = 火炬.nn.参数( 应用参数, 需要梯度=参数.requires_grad ) 火炬.工具.交换张量(参数, 应用参数) 除了 异常 作为 e: 如果 参数梯度 not : 参数.梯度 = 参数梯度 提升 运行时错误( f"_apply():无法交换"{self._获取名称()}.{}" ) 来自 e 输出参数 = 参数 elif 应使用设置数据: 参数.数据 = 应用参数 输出参数 = 参数 否则: 断言 isinstance(参数, 参数) 断言 参数.叶子节点 输出参数 = 参数(应用参数, 参数.需要梯度) self.参数[] = 输出参数 如果 参数梯度 not : 火炬.不梯度(): 应用梯度 = 函数(参数梯度) 应该使用设置数据 = compute 应该使用 set_data( 参数梯度, 应用梯度 ) 如果 应该使用 swap_tensors: 应用梯度.需要梯度_(参数梯度.需要梯度) try: 火炬.工具.交换张量(参数梯度, 应用梯度) 除了 异常 作为 e: 提升 运行时错误( f"_apply():无法交换"{self._获取名称()}.{}.grad" ) 来自 e 输出参数.梯度 = 参数梯度 elif g 是否使用 setData: 断言 输出参数.梯度 not 输出参数.研究生.数据 = 应用梯度 否则: 断言 参数梯度.叶子节点 输出参数.梯度 = 应用梯度.需要梯度_( 参数梯度.requires_grad ) , 缓冲区 self._缓冲区.项目(): 如果 缓冲区 not : self._缓冲区[] = 函数(缓冲区) 返回 self
[文档] def apply(self: T, fn: Callable[["模块"], None]) -> T: r"""递归地对每个子模块(由 ``.children()`` 返回)以及自身应用 ``fn``。 常规用法包括初始化模型的参数 (另见 :ref:`nn-init-doc`)。 Args: fn (:class:`模块` -> None): 对每个子模块应用的功能 Returns: 模块: self 示例:: >>> @torch.no_grad() >>> def 初始化权重(m): >>> 打印(m) >>> 如果类型为 nn.Linear: >>> m.weight.fill_(1.0) >>> 打印(m.weight) >>> net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2)) >>> net.apply(init_weights) Linear(in_features=2, out_features=2, bias=True) 包含参数: tensor([[1., 1.], [1., 1.], requires_grad=True) Linear(in_features=2, out_features=2, bias=True) 包含参数的 tensor([[1., 1.], [[1., 1.]], requires_grad=True) Sequential( (0): 线性层(in_features=2, out_features=2, bias=True) (1): 线性层(in_features=2, out_features=2, bias=True) ) """ for module in self.children(): module.apply(fn) fn(self) return self
[文档] def cuda(self: T, device: Optional[Union[int, device]] = None) -> T: r"""将所有模型参数和缓冲区移动到 GPU 上。 这也使得相关的参数和缓冲区成为不同的对象。因此 应在模块在 GPU 上优化时调用之前进行。 当模块在优化时存在于 GPU 上,应该先调用它。 .. 注意:: 此方法会就地修改模块。 参数: 设备(int,可选):如果指定,所有参数都将 复制到该设备 返回值: 模块:self """ 返回 self._apply(lambda t: t.cuda(device))
[文档] def ipu(self: T, device: Optional[Union[int, device]] = None) -> T: r"""将所有模型参数和缓冲区移动到 IPU。 这也将使相关的参数和缓冲区成为不同的对象。因此 它应该在构建优化器之前调用,如果模块将 在优化过程中实时运行。 .. 注意:: 此方法会就地修改模块。 参数: 设备(int,可选):如果指定,所有参数将复制到该设备 复制到该设备 返回: 模块:self """ """ return self._apply(lambda t: t.ipu(device))
[文档] def xpu(self: T, device: Optional[Union[int, device]] = None) -> T: r"""将所有模型参数和缓冲区移动到 XPU。 这也将使相关的参数和缓冲区成为不同的对象。因此 它应该在构建优化器之前调用,如果模块将 在优化过程中实时运行于 XPU。 .. 注意:: 此方法会就地修改模块。 参数: 设备(int,可选):如果指定,所有参数将复制到该设备 复制到该设备 返回: 模块:self """ 返回将 self._apply 应用到 t.xpu(device) 的结果
[文档] def mtia(self: T, device: Optional[Union[int, device]] = None) -> T: r"""将所有模型参数和缓冲区移动到 MTIA。 这也使得相关的参数和缓冲区成为不同的对象。 应在构建优化器之前调用 在优化过程中持续运行 MTIA。 .. 注意: 此方法会就地修改模块。 参数: device(int,可选):如果指定,所有参数都将 复制到该设备 返回值: 模块:self """ return self._apply(lambda t: t.mtia(device))
[文档] def cpu(self: T) -> T: r"""将所有模型参数和缓冲区移动到 CPU。 .. note:: 此方法会就地修改模块。 返回值: 模块:self """ return self._apply(lambda t: t.cpu())
[文档] def type(self: T, dst_type: 联合[dtype, str]) -> T: r"""将所有参数和缓冲区转换为 :attr:`dst_type`。 .. note:: 此方法会就地修改模块。 Args: dst_type (类型或字符串): 所需类型 Returns: 模块: self """ 返回 self._apply(lambda t: t.type(dst_type))
[文档] def float(self: T) -> T: r"""将所有浮点参数和缓冲区转换为 ``float`` 数据类型。 .. 注意:: 此方法会就地修改模块。 返回: 模块:self """ 返回 self._apply(lambda t: t.float() if t.is_floating_point() else t)
[文档] def double(self: T) -> T: r"""将所有浮点参数和缓冲区转换为 ``double`` 数据类型。 .. 注意:: 此方法会就地修改模块。 返回: 模块:self """ 返回 self._apply(lambda t: t.double() if t.is_floating_point() else t)
[文档] def half(self: T) -> T: r"""将所有浮点参数和缓冲区转换为 ``half`` 数据类型。 .. 注意:: 此方法会就地修改模块。 返回: 模块:self """ 返回 self._apply(lambda t: t.half() if t.is_floating_point() else t)
[文档] def bfloat16(self: T) -> T: r"""将所有浮点参数和缓冲区转换为 ``bfloat16`` 数据类型。 .. 注意:: 此方法会就地修改模块。 返回: 模块:self """ 返回 self._apply(lambda t: t.bfloat16() if t.is_floating_point() else t)
[文档] def to_empty( self: T, *, device: Optional[DeviceLikeType], recurse: bool = True -> T: 将参数和缓冲区移动到指定的设备,而不复制存储。 参数: 设备 (:class:`torch.device`): 参数期望的设备 和此模块中的缓冲区。 递归(布尔值):是否应递归地将子模块的参数和缓冲区移动到指定设备。 将递归地移动到指定的设备。 返回值: 模块:self """ return self._apply( lambda t: torch.empty_like(t, device=device), recurse=recurse )
@overload def ( self, 设备
: 可选[设备类型] = ..., 数据类型: 可选[数据类型] = ..., 非阻塞: 布尔类型 = ..., ) -> 自身: ... @overload def (self, 数据类型: 数据类型, 非阻塞: 布尔类型 = ...) -> 自身: ... @overload def (self, 张量: 张量, 非阻塞: 布尔类型 = ...) -> 自身: ...
[文档] def (self, *参数, **kwargs): r移动和/或设置参数和缓冲区。 这可以调用为 .. 函数:: to(device=None, dtype=None, non_blocking=False) noindex: .. 函数:: to(数据类型, non_blocking=False) noindex: .. 函数:: to(张量, non_blocking=False) noindex: .. 函数:: to(memory_format=torch.channels_last) noindex: 其签名与 :meth:`torch.Tensor.to` 类似,但仅接受 浮点或复数 :attr:`dtype`。此外,此方法将 仅将浮点数或复数参数和缓冲区转换为 :attr:`dtype` (如果给定)。积分参数和缓冲区将被移动 :attr:`device`,如果提供了,但数据类型不变。当 :attr:`non_blocking` 被设置,它尝试异步转换/移动 关于主机,如果可能的话,例如,移动 CPU 张量 固定内存到 CUDA 设备。 见下文示例。 .. 注意:: 此方法就地修改模块。 Args: 设备(:class:`torch.device`): 参数和在此模块中的缓冲区所期望的设备。可选。 此模块中的缓冲区 dtype (:class:`torch.dtype`): 所需的浮点数或复数数据类型 此模块中的参数和缓冲区 tensor (torch.Tensor): 具有所需数据类型和设备的张量 该模块中所有参数和缓冲区的数据类型和设备 内存格式(:class:`torch.memory_format`):期望的内存格式 该模块中 4D 参数和缓冲区的格式(关键字参数) (仅关键字参数) 返回: 模块:self 示例: >>> # xdoctest: +IGNORE_WANT("非确定性") >>> 线性 = nn.Linear(2, 2) >>> 线性权重 包含参数: 矩阵([[ 0.1913, -0.3420], [-0.5113, -0.2325]]) >>> 线性.to(torch.double) Linear(in_features=2, out_features=2, bias=True) >>> 线性权重 包含参数: 矩阵([[ 0.1913, -0.3420], [-0.5113, -0.2325]], 索引类型=torch.float64) >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA1) >>> gpu1 = torch.device("cuda:1") >>> linear.to(gpu1, dtype=torch.half, non_blocking=True) Linear(in_features=2, out_features=2, bias=True) >>> 线性权重 包含参数: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16, device='cuda:1') >>> cpu = torch.device("cpu") >>> linear.to(cpu) Linear(in_features=2, out_features=2, bias=True) >>> 线性权重 包含参数: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16) >>> 线性层 = nn.Linear(2, 2, bias=None).to(torch.cdouble) >>> 线性权重 包含参数: 矩阵([[ 0.3741+0.j, 0.2382+0.j], [ 0.5593+0.j, -0.4443+0.j]], dtype=torch.complex128) >>> linear(torch.ones(3, 2, dtype=torch.cdouble)) tensor([[0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j]], dtype=torch.complex128) "源代码" 设备, 数据类型, 非阻塞, 转换为格式 = 火炬._C._nn.解析到( *参数, **kwargs ) 如果 dtype not : 如果 not (数据类型.是否为浮点数 数据类型.是复杂的): 提升 类型错误( "nn.Module.to 只接受浮点数或复数类型,但得到了期望的数据类型=" f"复数模块是正在积极开发中的新功能,其设计可能会改变,"{数据类型}" ) 如果 数据类型.是复杂的: warnings.警告( "复杂模块是正在积极开发中的新特性,其设计可能会发生变化," "当使用复杂的张量作为参数或缓冲区时,某些模块可能无法按预期工作。" "请在此处提交问题:https://github.com/pytorch/pytorch/issues/new?template=bug-report.yml" "如果复杂模块无法按预期工作。" ) def 转换(t): try: 如果 转换为格式 not t.暗淡() (4, 5): 返回 t.( 设备, dtype 如果 t.is_floating_point() t.是复杂的() 否则 , 非阻塞, 内存格式=转换为格式, ) 返回 t.( 设备, dtype 如果 t.is_floating_point() t.是复杂的() 否则 , 非阻塞, ) 除了 未实现异常 作为 e: 如果 字符串(e) == "无法从元张量中复制;没有数据!": 提升 不支持的操作异常( f"{e}请使用 torch.nn.Module.to_empty()代替 torch.nn.Module.to() f"当将模块从元移动到不同的设备时。" ) 来自 否则: 提升 返回 self.应用(转换)
[文档] def register_full_backward_pre_hook( self, hook: Callable[["模块", _grad_t], Union[None, _grad_t]], prepend: bool = False, ) -> RemovableHandle: 注册模块的向后预钩子。 每当计算模块的梯度时,都会调用此钩子。 钩子应具有以下签名:: hook(module, grad_output) -> 元组[Tensor] 或 None `:attr:`grad_output` 是一个元组。钩子应该 不修改其参数,但可以可选地返回一个新的梯度 关于将用于替代:attr:`grad_output` 的输出 随后的计算。:attr:`grad_output` 中的条目对于所有非-Tensor 参数将为 ``None``。 由于技术原因,当此钩子应用于一个模块时,其前向函数将接收传递给模块的每个张量的视图。同样,调用者将接收一个视图 对于技术原因,当此钩子应用于一个模块时,其前向函数将 接收传递给模块的每个张量的视图。同样,调用者将接收一个视图 每个由模块的 forward 函数返回的 Tensor 的每个元素。 ..警告:: 使用反向钩子时,不允许就地修改输入,否则将引发错误。 将引发错误。 Args: hook (Callable): 用户定义的钩子,用于注册。 prepend (bool): 如果为 true,提供的 ``hook`` 将在 所有现有的 ``backward_pre`` 钩子之前触发 `:class:`torch.nn.Module`. 否则,提供的 `hook`将在所有现有的`backward_pre` `hook`触发后执行 在这:class:`torch.nn.Module`。注意全局 backward_pre 钩子已注册 `register_module_full_backward_pre_hook` 函数将在 此方法注册的所有钩子之前触发。 返回值: class:`torch.utils.hooks.RemovableHandle`: 可以用来通过调用 handle.remove()移除已添加的钩子的句柄 ``handle.remove()`` """ handle = RemovableHandle(self._backward_pre_hooks) self._backward_pre_hooks[handle.id] = hook if prepend: self._backward_pre_hooks.move_to_end(handle.id, last=False) # type: ignore[attr-defined] return handle
[文档] def register_backward_hook( self, hook: Callable[["模块", _grad_t, _grad_t], Union[None, _grad_t]] ) -> RemovableHandle: r"""在模块上注册反向钩子。 此函数已被弃用,推荐使用 :meth:`~torch.nn.Module.register_full_backward_hook` 和 此函数的行为将在未来版本中更改。 返回: `:class:`torch.utils.hooks.可移除句柄`: 可以用来通过调用移除已添加的钩子的句柄 ``handle.remove()`` """ 如果 self._is_full_backward_hook 为 True: 引发 RuntimeError( 无法同时使用常规反向钩子和完整反向钩子 单个模块。请只使用其中一个。 ) self._is_full_backward_hook = False handle = RemovableHandle(self._backward_hooks) self._backward_hooks[handle.id] = hook return handle
[文档] def 注册完整反向钩子( self, hook: 可调用[["模块", _grad_t, _grad_t] 联盟[, _grad_t]], 预先添加: 布尔类型 = 错误, ) -> 可移除句柄: r注册模块的回退钩子。 钩子将在每次调用与模块相关的梯度时被调用 计算,即只有当梯度与 关于模块输出的计算。钩子应具有以下 签名:: hook(module, grad_input, grad_output) -> tuple(Tensor) or None attr:`grad_input` 和 :attr:`grad_output` 是包含梯度的元组 关于输入和输出分别。钩子应该 不修改其参数,但可以可选地返回一个新的梯度 关于将用于替代:attr:`grad_input` 的输入 后续计算。:attr:`grad_input` 仅对应于提供的输入 作为位置参数和所有关键字参数将被忽略。条目 在 :attr:`grad_input` 和 :attr:`grad_output` 中,对于所有非-Tensor,将都是 ``None``。 参数。 由于技术原因,当此钩子应用于一个模块时,其前向函数将 接收传递给模块的每个张量的视图。同样,调用者将接收到一个视图 每个由模块的 forward 函数返回的 Tensor。 ..警告:: 当使用反向钩子时,不允许就地修改输入或输出。 将引发错误。 Args: 钩子(Callable):要注册的用户定义钩子。 prepend(布尔值):如果为 true,提供的 ``hook`` 将在 所有现有的 ``backward`` 钩子之前触发 class:`torch.nn.Module`。否则,提供的 ``hook`` 将在 所有现有的 ``backward`` 钩子之后触发 这个 :class:`torch.nn.Module`。注意全局 使用 ``backward`` 注册的钩子 func:`register_module_full_backward_hook` 将在 此方法注册的所有钩子之前触发。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() "源代码" 如果 self._is_full_backward_hook 错误: 提升 运行时错误( "不能同时使用常规反向钩子和完整反向钩子在一个 " "单个模块上。请只使用其中之一。" ) self._is_full_backward_hook = 真实 handle = 可移除句柄(self._backward_hooks) self._backward_hooks[处理.id] = 钩子 如果 预先添加: self._backward_hooks.移动到末尾(处理.id, 最后=错误) # 类型: 忽略[attr-defined] 返回 处理
def _获取反向钩子(self): r返回用于调用函数的回退钩子。 它返回两个列表,一个包含完整的回退钩子,另一个包含非完整的回退钩子。 非完整回退钩子。 "源代码" 全向后钩: 列表[可调用] = [] 如果 _全局是否为完整反向钩子 True: 全局反向钩子 += _全局反向钩子.() 如果 self._is_full_backward_hook True: 全局反向钩子 += self._backward_hooks.() non_full_backward_hooks: 列表[可调用] = [] 如果 _全局是否为完整反向钩子 错误: 非全局反向钩子 += _全局反向钩子.() 如果 self._is_full_backward_hook 错误: 非全局反向钩子 += self._backward_hooks.() 返回 全向后钩, 非全局反向钩子 def _get_backward_pre_hooks(self): 向后预处理钩: 列表[可调用] = [] backward_pre_hooks += _全局反向前钩子.() backward_pre_hooks += self._backward_pre_hooks.() 返回 backward_pre_hooks def _maybe_warn_non_full_backward_hook(self, 输入, 结果, grad_fn): 如果 not isinstance(结果, 火炬.张量): 如果 not ( isinstance(结果, 元组) 所有(isinstance(r, 火炬.张量) r 结果) ): warnings.警告( 使用非完整回退钩子在未返回的模块上 单个张量或张量元组已被弃用,并将被移除 在未来的版本中。这个钩子将缺少一些 grad_output。 请使用 register_full_backward_hook 以获取文档化的行为。, 未来警告, 栈级别=2, ) 返回 否则: 结果 = (结果,) 如果 not isinstance(输入, 火炬.张量): 如果 not ( isinstance(输入, 元组) 所有(isinstance(i, 火炬.张量) i 输入) ): warnings.警告( 使用非全向后钩子在未以“ 单个张量或张量元组已被弃用,并将被移除 在未来的版本中。这个钩子将缺少一些 grad_input。 请使用 register_full_backward_hook 以获取文档化的行为。, 未来警告, 栈级别=2, ) 返回 否则: 输入 = (输入,) 我们确定输入和结果都是张量元组 out_grad_fn = {r.grad_fn r 结果 如果 r.grad_fn not } 如果 长度(out_grad_fn) == 0 ( 长度(out_grad_fn) == 1 grad_fn not out_grad_fn ): warnings.警告( "在使用输出嵌套在 Python 数据结构时使用非完整反向钩子" 已弃用,将在未来版本中删除。此钩子将缺失 "一些 grad_output。", 未来警告, 栈级别=2, ) elif 长度(out_grad_fn) > 1: warnings.警告( "当输出由不同的 autograd 节点生成时使用非完整反向钩子" 已弃用,将在未来版本中删除。此钩子将缺失 "一些 grad_output。请使用 register_full_backward_hook 以获取文档化的行为。", 未来警告, 栈级别=2, ) 否则: 在这一点上,hook 的 grad_output 部分很可能正确 输入梯度函数 = {i.grad_fn i 输入 如果 i.grad_fn not } 下一个函数 = {n[0] n grad_fn.下一个函数} 如果 输入梯度函数 != 下一个函数: warnings.警告( 使用前向包含多个 autograd 节点时,非全向后钩子 已弃用,将在未来版本中删除。此钩子将缺失 一些 grad_input。请使用 register_full_backward_hook 来获取文档化的 行为。, 未来警告, 栈级别=2, )
[文档] def 注册前向钩子( self, hook: 联盟[ 可调用[[T, 元组[任意, ...]], 可选[任意]], 可调用[ [T, 元组[任意, ...] 字典[字符串, 任意]], 可选[元组[任意, 字典[字符串, 任意]], ] ] *, 预先添加: 布尔类型 = 错误, with_kwargs: 布尔类型 = 错误, ) -> 可移除句柄: r在模块上注册一个前置钩子。 每次调用 :func:`forward` 之前都会调用此钩子。 如果 `with_kwargs` 为 false 或未指定,则输入只包含 模块接收到的位置参数。关键字参数不会 传递给钩子,仅传递给 `forward`。钩子可以修改 输入. 用户可以返回一个元组或单个修改后的值 hook. 如果返回单个值,我们将将其包装成一个元组 除非该值已经是元组。钩子应该有 以下签名: hook(module, args) -> None 或修改后的输入 如果 `with_kwargs` 为 true,则前向预钩子将传递给前向函数的 kwargs。如果钩子修改了输入, 则将传递给前向函数的 kwargs。如果钩子修改了输入, 输入,应返回参数和关键字参数。钩子应具有以下签名: 签名如下: hook(module, args, kwargs) -> None 或修改后的输入和关键字参数的元组 Args: hook (Callable):用户定义的钩子,用于注册。 prepend(布尔值):如果为 true,提供的 ``hook`` 将在 所有现有的 ``forward_pre`` 钩子之前触发 class:`torch.nn.Module`。否则,提供的 ``hook`` 将在 所有现有的 ``forward_pre`` 钩子之后触发 在这个 :class:`torch.nn.Module` 上。注意全局 ``forward_pre`` 注册的钩子 func:`register_module_forward_pre_hook` 将在所有 该方法注册的钩子之前触发。 默认:``False`` with_kwargs (bool): 如果为真,则将传递给 forward 函数的 kwargs 参数传递给 hook 给定。 默认:``False`` 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() "源代码" handle = 可移除句柄( self._前向预处理钩子, extra_dict=self._forward_pre_hooks_with_kwargs ) self._前向预处理钩子[处理.id] = 钩子 如果 with_kwargs: self._forward_pre_hooks_with_kwargs[处理.id] = 真实 如果 预先添加: self._前向预处理钩子.移动到末尾(处理.id, 最后=错误) # 类型: 忽略[attr-defined] 返回 处理
[文档] def 注册前向钩子( self, hook: 联盟[ 可调用[[T, 元组[任意, ...] 任意] 可选[任意]], 可调用[[T, 元组[任意, ...] 字典[字符串, 任意] 任意] 可选[任意]], ] *, 预先添加: 布尔类型 = 错误, with_kwargs: 布尔类型 = 错误, 总是呼叫: 布尔类型 = 错误, ) -> 可移除句柄: r在模块上注册一个前向钩子。 该钩子将在每次调用 :func:`forward` 计算输出后执行。 如果 `with_kwargs` 为 `False` 或未指定,则输入只包含 模块接收到的位置参数。关键字参数不会 传递给钩子,仅传递给 `forward`。钩子可以修改 不会对 forward 产生影响,因为这是在调用 :func:`forward` 之后调用的。钩子 不会对 forward 产生影响,因为这是在调用 :func:`forward` 之后调用的。 应具有以下签名: hook(module, args, output) -> None 或修改后的输出 如果 `with_kwargs` 为 `True`,则前向钩子将传递给前向函数的 `kwargs`,并期望返回 ``kwargs`` 给前向函数,并期望返回 输出可能被修改。钩子应具有以下签名: hook(module, args, kwargs, output) -> None 或修改后的输出 Args: hook (Callable):用户定义的钩子,用于注册。 prepend (bool):如果为 ``True``,则提供的 ``hook`` 将被触发 在此之前的所有现有 ``forward`` 钩子 class:`torch.nn.Module`。否则,提供的 ``hook`` 将在 ``hook`` 将在所有现有 ``forward`` 钩子之后触发 这个 :class:`torch.nn.Module`。注意全局 已注册的 `forward` 钩子 `:func:`register_module_forward_hook`将在所有钩子之前触发 由该方法注册的钩子。 默认:``False`` with_kwargs (bool): 如果为 ``True``,则 ``hook`` 将传递给前向函数的 kwargs 参数。 默认:``False`` always_call (布尔值): 如果为 ``True``,则无论在调用模块时是否引发异常,都会运行 ``hook``。 是否在调用模块时引发异常。 默认:``False`` 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() "源代码" handle = 可移除句柄( self._前向钩子, extra_dict=[ self._forward_hooks_with_kwargs, self._forward_hooks_always_called, ] ) self._前向钩子[处理.id] = 钩子 如果 with_kwargs: self._forward_hooks_with_kwargs[处理.id] = 真实 如果 总是呼叫: self._forward_hooks_always_called[处理.id] = 真实 如果 预先添加: self._前向钩子.移动到末尾(处理.id, 最后=错误) # 类型: 忽略[attr-defined] 返回 处理
def _慢速快进(self, *输入, **kwargs): 跟踪状态 = 火炬._C._获取追踪状态() 如果 not 跟踪状态 isinstance(self.前向, 火炬._C.脚本方法): 返回 self.前向(*输入, **kwargs) 录制范围 = 火炬.算子.跟踪.跟踪模块映射 not 如果 录制范围: # 类型忽略被添加,因为此时已知 # torch.jit._trace._trace_module_map 不是 Optional,并且具有类型 Dict[Any, Any] 名称 = 火炬.算子.跟踪._trace_module_map[self] 如果 self 火炬.算子.跟踪.跟踪模块映射 否则 # type: 忽略[index, operator] # 无编号:B950 如果 名称: 跟踪状态.推送作用域(名称) 否则: 录制范围 = try: 结果 = self.前向(*输入, **kwargs) 最后: 如果 录制范围: 跟踪状态.pop_scope() 返回 结果 def _wrapped_call_impl(self, *参数, **kwargs): 如果 self._compiled_call_impl not : 返回 self._编译调用实现(*参数, **kwargs) # 类型:忽略[杂项] 否则: 返回 self._call_impl(*参数, **kwargs) # torchrec 测试代码的一致性,与以下代码 # fmt: off def _call_impl(self, *参数, **kwargs): forward_call = (self._slow_forward 如果 火炬._C._获取追踪状态() 否则 self.前向) # 如果没有钩子,我们希望跳过其余的逻辑 这个函数,然后直接调用前进。 如果 not (self._backward_hooks self._backward_pre_hooks self.前向钩子 self._forward_pre_hooks 全局反向前钩子 全局反向钩子 _全局转发钩子 _全局前置钩子): 返回 前向调用(*参数, **kwargs) 结果 = 总是调用/总是调用的钩子 = 集合() def 内部(): 非局部 结果, 参数, kwargs 全向后钩, 非全局反向钩子 = [] [] backward_pre_hooks = [] 如果 self._backward_pre_hooks _全局反向前钩子: backward_pre_hooks = self._get_backward_pre_hooks() 如果 self._backward_hooks _全局反向钩子: 全向后钩, 非全局反向钩子 = self._获取反向钩子() 如果 _全局正向预处理钩子 self._前向预处理钩子: 钩子 ID, 钩子 ( *_全局前置钩子.项目(), *self._前向预处理钩子.项目(), ): 如果 hook_id self._forward_pre_hooks_with_kwargs: 参数、关键字参数和结果 = hook(self, 参数, kwargs) # 类型:忽略[杂项] 如果 参数、关键字参数和结果 not : 如果 isinstance(args_kwargs_result, 元组) 长度(args_kwargs_result) == 2: 参数, kwargs = 参数、关键字参数和结果 否则: 提升 运行时错误( "前向钩子必须返回 None 或一个元组" f"但得到了(new_args, new_kwargs),"{args_kwargs_result} ) 否则: 参数结果 = hook(self, 参数) 如果 参数结果 not : 如果 not isinstance(参数结果, 元组): 参数结果 = (参数结果,) args = 参数结果 bw_hook = 如果 全局反向钩子 向后预处理钩: bw_hook = 向后钩(self, 全向后钩, 向后预处理钩) args = bw 钩.设置输入钩子(参数) 结果 = 前向调用(*参数, **kwargs) 如果 _全局转发钩子 self._前向钩子: 钩子 ID, 钩子 ( *_全局正向钩子.项目(), *self._前向钩子.项目(), ): 标记始终调用的钩子将被执行 如果 hook_id self.始终调用的前向钩子 hook_id _全局前进钩子始终被调用: 总是调用的钩子.添加(钩子 ID) 如果 hook_id self._forward_hooks_with_kwargs hook_id _global_forward_hooks_with_kwargs: 钩子结果 = hook(self, 参数, kwargs, 结果) 否则: 钩子结果 = hook(self, 参数, 结果) 如果 钩子结果 not : 结果 = 钩子结果 如果 bw 钩: 如果 not isinstance(结果, (火炬.张量, 元组)): warnings.警告("为了调用向后钩子," "模块输出应为 Tensor 或 Tensor 的元组" f"但接收到了"{类型(结果)}") 结果 = bw 钩.setup_output_hook(结果) # 处理非完整向后钩子 如果 non_full_backward_hooks: 变量 = 结果 while not isinstance(变量, 火炬.张量): 如果 isinstance(变量, 字典): 变量 = 下一(v v 变量.() 如果 isinstance(v, 火炬.张量)) 否则: 变量 = 变量[0] grad_fn = 变量.grad_fn 如果 grad_fn not : 钩子 non_full_backward_hooks: grad_fn.注册钩子(包装钩子(hook, self)) self._maybe_warn_non_full_backward_hook(参数, 结果, grad_fn) 返回 结果 # 在编译时这实际上并不等同于行为,但它是 几乎不可能支持在神经网络中抛出异常 然后在模块中捕获它,然后在这里再次捕获,然后 再次捕获,并期望生成的帧被编译。 这里的重新抛出只是使我们的异常处理变得一团糟,没有任何好处 # 原因。不要在发生异常的情况下尝试运行始终调用的钩子 # 异常。 如果 火炬.编译器.is_compiling(): 返回 内部() try: 返回 内部() 除了 异常: # 如果尚未运行,则运行始终调用的钩子 # 目前只有前向钩子有始终调用选项,但也许 应该也添加到完整的反向钩子中。 钩子 ID, 钩子 _全局正向钩子.项目(): 如果 hook_id _全局前进钩子始终被调用 hook_id not 总是调用的钩子: # type: ignore[possibly-undefined] try: 钩子结果 = hook(self, 参数, 结果) # type: ignore[possibly-undefined] 如果 钩子结果 not : 结果 = 钩子结果 除了 异常 作为 e: warnings.警告(“全局模块的 forward hook,其中 `always_call=True` 导致抛出异常” f“在 forward 中抛出另一个错误时被抑制了:”{字符串(e)}") 继续 钩子 ID, 钩子 self._前向钩子.项目(): 如果 hook_id self.始终调用的前向钩子 hook_id not 总是调用的钩子: # type: ignore[possibly-undefined] try: 如果 hook_id self._forward_hooks_with_kwargs: 钩子结果 = hook(self, 参数, kwargs, 结果) # type: ignore[possibly-undefined] 否则: 钩子结果 = hook(self, 参数, 结果) # type: ignore[possibly-undefined] 如果 钩子结果 not : 结果 = 钩子结果 除了 异常 作为 e: warnings.警告("模块前向钩子 `always_call=True` 抛出异常" f“在 forward 中抛出另一个错误时被抑制了:”{字符串(e)}") 继续 # 在 try 块中引发的异常 提升 # fmt: on __调用__: 可调用[..., 任意] = _包装调用实现 def __getstate__(self): 状态 = self.字典.复制() 状态.弹出("_编译调用实现", ) 返回 状态 def __setstate__(self, 状态): self.字典.更新(状态) # 支持加载没有以下属性的旧检查点: 如果 "_forward_pre_hooks" not self.字典: self._forward_pre_hooks = 有序字典() 如果 "_forward_pre_hooks_with_kwargs" not self.字典: self._forward_pre_hooks_with_kwargs = 有序字典() 如果 "_forward_hooks_with_kwargs" not self.字典: self._forward_hooks_with_kwargs = 有序字典() 如果 "_forward_hooks_always_called" not self.字典: self.始终调用的前向钩子 = 有序字典() 如果 "_state_dict_hooks" not self.字典: self._state_dict_hooks = 有序字典() 如果 _state_dict_pre_hooks not self.字典: self._state_dict_pre_hooks = 有序字典() 如果 _load_state_dict_pre_hooks not self.字典: self._load_state_dict_pre_hooks = 有序字典() 如果 "_加载状态字典后钩子" not self.字典: self._加载状态字典后钩子 = 有序字典() 如果 "_非持久缓冲区设置" not self.字典: self.非持久缓冲区集合 = 集合() 如果 "_is_full_backward_hook" not self.字典: self._is_full_backward_hook = 如果 "_backward_pre_hooks" not self.字典: self._backward_pre_hooks = 有序字典() 返回类型不应标注为`Any`,否则类型检查 在`torch.nn.Module`及其所有子类上大部分功能因此被禁用。参见: # https://github.com/pytorch/pytorch/pull/115074 def __getattr__(self, 名称: 字符串) -> 联盟[张量, "模块"]: 如果 _parameters self.字典: 参数 = self.字典[_参数] 如果 名称 参数: 返回 参数[名称] 如果 "_缓冲区" self.字典: _缓冲区 = self.字典[_缓冲区] 如果 名称 _缓冲区: 返回 _缓冲区[名称] 如果 "_模块" self.字典: 模块 = self.字典[_模块] 如果 名称 模块: 返回 模块[名称] 提升 属性错误( f''{类型(self).__name__}'对象没有此属性'{名称} ) def __setattr__(self, 名称: 字符串, : 联盟[张量, "模块"]) -> : def 移除(*字典或集合): d 字典或集合: 如果 名称 d: 如果 isinstance(d, 字典): 删除 d[名称] 否则: d.丢弃(名称) params = self.字典.获取(_参数) 如果 isinstance(, 参数): 如果 params : 提升 属性错误( "在调用 Module.__init__() 之前不能分配参数" ) 移除( self.字典, self._缓冲区, self.模块, self._非持久缓冲区集合, ) self.注册参数(名称, ) elif params not 名称 参数: 如果 value not : 提升 类型错误( f"无法分配"{火炬.类型名()}'作为参数 '{名称}' " "(期望 torch.nn.Parameter 或 None)" ) self.注册参数(名称, ) 否则: 模块 = self.字典.获取(_模块) 如果 isinstance(, 模块): 如果 模块 : 提升 属性错误( "在调用 Module.__init__() 之前不能分配模块" ) 移除( self.字典, self.参数, self._缓冲区, self._非持久缓冲区集合, ) 钩子 全局模块注册钩子.(): 输出 = hook(self, 名称, ) 如果 输出 not : value = 输出 模块[名称] = value elif 模块 not 名称 模块: 如果 value not : 提升 类型错误( f"无法分配"{火炬.类型名()}'作为子模块'{名称}' " '(期望 torch.nn.Module 或 None)' ) 钩子 全局模块注册钩子.(): 输出 = hook(self, 名称, ) 如果 输出 not : value = 输出 模块[名称] = value 否则: 缓冲区 = self.字典.获取(_缓冲区) 如果 isinstance(, 缓冲区) 缓冲区 not 名称 缓冲区: 如果 value not not isinstance(, 火炬.张量): 提升 类型错误( f"无法分配"{火炬.类型名()}'作为缓冲区'{名称}' " '期望为 torch.nn.Buffer、torch.Tensor 或 None' ) 如果 isinstance(, 缓冲区): 持久 = .持久 否则: 持久 = 名称 not self.非持久缓冲区集合 # === 漏洞 === # 这整个块应该是这样的: # self.register_buffer(name, value, persistent) # 但为了支持那些(错误地)实现了 register_buffer()方法且 # register_buffer()方法没有"persistent"参数的 nn.Module 的子类 # 参数。只有接受它时才传递,否则假设 # 总是正确的 如果 self.注册缓冲区 火炬.nn.模块.注册缓冲区: self.注册缓冲区(名称, , 持久性) 否则: 符号 = 检查.签名(self.注册缓冲区) 如果 "持久性" 符号.参数: self.注册缓冲区(名称, , 持久性) 否则: 如果 not 持久性: 提升 运行时错误( "注册一个非持久性缓冲区 " "在实现模块子类的模块上 " "register_buffer() 不允许使用持久性参数" "参数不被允许。" ) # 假设不使用参数的实现具有在参数添加之前的 # 行为:持久性=True self.注册缓冲区(名称, ) # === HACK END === 否则: 超级().__setattr__(名称, ) def __delattr__(self, 名称): 如果 名称 self.参数: 删除 self.参数[名称] elif 名称 self._缓冲区: 删除 self._缓冲区[名称] self._非持久缓冲区集合.丢弃(名称) elif 名称 self.模块: 删除 self.模块[名称] 否则: 超级().__delattr__(名称) def _register_state_dict_hook(self, hook): r"""注册 :meth:`~torch.nn.Module.state_dict` 方法的后钩子。 它应该具有以下签名:: hook(module, state_dict, prefix, local_metadata) -> None 或 state_dict 已注册的钩子可以就地修改 ``state_dict`` 或返回一个新的。 如果返回一个新的 ``state_dict``,则只有当它是从调用 :meth:`~nn.Module.state_dict` 的根模块返回时,才会被尊重。 该模块的 :meth:`~nn.Module.state_dict` 被调用。 "源代码" 如果 getattr(hook, "_from_public_api", 错误): 提升 运行时错误( "无法注册与之前通过 register_state_dict_post_hook 注册的相同的函数作为状态字典后钩子" "已注册的状态字典后钩子" ) handle = 可移除句柄(self.状态字典钩子) self.状态字典钩子[处理.id] = 钩子 返回 handle
[文档] def register_state_dict_post_hook(self, hook): r"""注册 :meth:`~torch.nn.Module.state_dict` 方法的后钩子。 应具有以下签名:: hook(module, state_dict, prefix, local_metadata) -> None 注册的钩子可以就地修改 `state_dict`。 """ 在 `_register_state_dict_hook` 中存在一个错误,该错误已在 https://github.com/pytorch/pytorch/issues/117437 中描述,其中返回值 仅在根模块中尊重,但在子模块中不尊重。 在这个公开版本中,我们通过只允许通过钩子修改 state_dict 来解决这个问题。然而,由于通过这两个 API 注册的钩子都将被添加到`_state_dict_hooks`中,因此`_state_dict_hooks`的类型也会发生变化。 然而,由于通过这两个 API 注册的钩子都将被添加到`_state_dict_hooks`中,因此`_state_dict_hooks`的类型也会发生变化。 `_state_dict_hooks`的类型也会发生变化。 由于对其有众多依赖,无法更改,我们标记一个钩子 通过将其上的 `_from_public_api` 设置为注册,通过公共 API 进行注册。 在`state_dict`实现中,如果可调用对象没有这个 # 标志,将保留尊重返回值的老行为 # 对于根模块,否则我们确保钩子返回 None。 hook._from_public_api = True handle = RemovableHandle(self._state_dict_hooks) self._state_dict_hooks[handle.id] = hook 返回处理
[文档] def register_state_dict_pre_hook(self, hook): r"""为 :meth:`~torch.nn.Module.state_dict` 方法注册预钩子。 它应该具有以下签名:: hook(module, prefix, keep_vars) -> None 已注册的钩子可以在调用 ``state_dict`` 之前进行预处理。 调用。 """ handle = RemovableHandle(self._state_dict_pre_hooks) self._state_dict_pre_hooks[handle.id] = hook return handle
def 保存到状态字典
(self, 目的地, 前缀, 保留变量): r将模块状态保存到`destination`字典中。 目标字典将包含状态 模块本身,而不是其子模块。这将在每个 子模块在 :meth:`~torch.nn.Module.state_dict` 中。 在罕见情况下,子类可以通过实现类特定行为 覆盖此方法以使用自定义逻辑。 Args: 目标(字典):状态将存储在此字典中。 prefix(字符串):在此处使用的参数和缓冲区的前缀。 模块 "源代码" 名称, 参数 self.参数.项目(): 如果 参数 not : 目的地[前缀 + 名称] = 参数 如果 保持变量 否则 参数.detach() 名称, 缓冲区 self._缓冲区.项目(): 如果 缓冲区 not 名称 not self._非持久缓冲区集合: 目的地[前缀 + 名称] = 缓冲区 如果 保持变量 否则 缓冲区.detach() 额外状态键 = 前缀 + _EXTRA_STATE_KEY_SUFFIX 如果 ( getattr(self., 获取额外状态, 模块.获取额外状态) not 模块.获取额外状态 ): 目的地[额外状态键] = self.获取额外状态() 用户可以向 `state_dict` 传递一个可选的任意可映射对象,在这种情况下,`state_dict` 返回该对象。但如果他们不传递任何内容,则创建并返回一个 `OrderedDict`。 但如果他们不传递任何内容,则创建并返回一个 `OrderedDict`。 目标 = 类型变量("目标", 绑定=字典[字符串, 任意]) @overload def state_dict( self, *, 目的地: 目的地, 前缀: 字符串 = ..., 保留变量: 布尔类型 = ... ) -> 目的地: ... @overload def state_dict(self, *, 前缀: 字符串 = ..., 保留变量: 布尔类型 = ...) -> 字典[字符串, 任意]: ... # TODO: 当向后兼容性允许时,将 `*args` 改为 `*` 并在文档中移除相应的警告。 # 同时移除参数解析的逻辑。
[文档] def state_dict(self, *参数, 目的地=, 前缀="", 保留变量=错误): r返回包含模块整个状态的引用字典。 参数和持久缓冲区(例如运行平均值)均包括在内。 键对应参数和缓冲区名称。 设置为 `None` 的参数和缓冲区不包括在内。 .. 注意:: 返回的对象是一个浅拷贝。它包含引用 到模块的参数和缓冲区。 .. 警告:: 当前 `state_dict()` 也接受位置参数 按照 ``destination``、``prefix`` 和 ``keep_vars`` 的顺序。然而, 这将被弃用,并且未来版本将强制执行关键字参数。 请避免使用“destination”参数,因为它不是为最终用户设计的。 .. 警告:: 请避免使用参数“destination”,因为它不是为最终用户设计的。 请避免使用参数“destination”,因为它不是为最终用户设计的。 Args: 目的地(dict,可选):如果提供,模块的状态将为 更新到字典中,并返回相同的对象。 否则,将创建并返回一个 `OrderedDict`。 默认:``无``。 前缀(str,可选):添加到参数和缓冲区的前缀 组成状态字典键的名称。默认值:``''``。 keep_vars(bool,可选):默认情况下,返回的状态字典中的 :class:`~torch.Tensor` 被从自动微分中分离出来。如果它的是 返回的状态字典中的 :class:`~torch.Tensor` 被从自动微分中分离出来。如果它是 设置为 ``True``,则不会执行分离。 默认:``False``。 返回: dict: 包含整个模块状态的字典 示例:: >>> # xdoctest: +SKIP("undefined vars") >>> module.state_dict().keys() ['偏见', '权重'] "源代码" # TODO: 当向后兼容性允许时,移除 `args` 和解析逻辑。 如果 长度(参数) > 0: # 默认情况下忽略 DeprecationWarning warnings.警告( "位置参数正在弃用,请使用关键字参数(kwargs)。请参阅 " "https://maskerprc.github.io/docs/main/generated/torch.nn.Module.html#torch.nn.Module.state_dict" "详情请见。", 未来警告, 栈级别=2, ) 如果 destination : destination = 参数[0] 如果 长度(参数) > 1 前缀 == "": 前缀 = 参数[1] 如果 长度(参数) > 2 保持变量 错误: 保持变量 = 参数[2] 如果 destination : destination = 有序字典() 目的地.元数据 = 有序字典() 本地元数据 = 字典(版本=self._版本) 如果 有属性(目的地, _metadata): 目的地.元数据[前缀[-1]] = 本地元数据 钩子 self._state_dict_pre_hooks.(): hook(self, 前缀, 保留变量) self.保存到状态字典(目的地, 前缀, 保留变量) 名称, 模块 self.模块.项目(): 如果 模块 not : 模块.state_dict( 目的地=目的地, 前缀=前缀 + 名称 + “点”, 保留变量=保留变量, ) 钩子 self.状态字典钩子.(): 钩子结果 = hook(self, 目的地, 前缀, 本地元数据) 如果 not getattr(hook, "_from_public_api", 错误): 如果 钩子结果 not : destination = 钩子结果 否则: 如果 钩子结果 not : 提升 运行时错误(state_dict 后钩必须返回 None) 返回 目的地
def _register_load_state_dict_pre_hook(self, hook, 使用模块=错误): r详细信息请参阅 :meth:`~torch.nn.Module.register_load_state_dict_pre_hook` 一个细微的区别是,如果将 ``with_module`` 设置为 ``False``,那么 钩子函数不会将 ``module`` 作为第一个参数,而 meth:`~torch.nn.Module.register_load_state_dict_pre_hook` 总是接受 ``module`` 作为第一个参数。 参数: 钩子(Callable):在调用之前将被调用的可调用钩子 加载状态字典。 with_module (bool, 可选): 是否传递模块 实例作为第一个参数传递给钩子。 "源代码" handle = 可移除句柄(self._load_state_dict_pre_hooks) self._load_state_dict_pre_hooks[处理.id] = 包装钩子( hook, self 如果 with_module 否则 ) 返回 handle
[文档] def register_load_state_dict_pre_hook(self, hook): r"""在模块的 :meth:`~nn.Module.load_state_dict` 被调用之前注册一个预钩子。 它应该具有以下签名:: hook(module, state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs) -> None # noqa: B950 参数: 钩子(Callable):在加载状态字典之前将被调用的可调用钩子。 在加载状态字典之前。 """ return self._register_load_state_dict_pre_hook(hook, with_module=True)
[文档] def register_load_state_dict_post_hook(self, hook): r"""注册一个在模块的 :meth:`~nn.Module.load_state_dict` 被调用后运行的钩子。 它应该具有以下签名:: hook(module, incompatible_keys) -> None ``module`` 参数是当前注册此钩子的模块,而 ``incompatible_keys`` 参数是一个包含 ``missing_keys`` 和 ``unexpected_keys`` 属性的 ``NamedTuple``。 ``missing_keys`` 和 ``unexpected_keys``。 ``missing_keys`` 表示缺少的键。 是一个包含缺失键的 ``str`` 列表 ``unexpected_keys`` 是一个包含意外键的 ``str`` 列表 给定的 incompatible_keys 可以根据需要就地修改 注意,当调用 :func:`load_state_dict` 时执行的检查 `strict=True` 受钩子所做的修改影响 `missing_keys` 或 `unexpected_keys`,如预期。向任一集合中添加键将导致在 `strict=True` 时抛出错误,并且 清除所有缺失和意外的键将避免错误。 清除所有缺失和意外的键将避免错误。 返回: `:class:`torch.utils.hooks.可移除句柄`: 一个可以通过调用来移除已添加钩子的句柄 处理.remove() """ handle = RemovableHandle(self._load_state_dict_post_hooks) self._load_state_dict_post_hooks[handle.id] = hook return handle
def 从状态字典加载( self, state_dict, 前缀, 本地元数据, 严格的, 缺少键, 预期之外的键, 错误信息, ): r将参数和缓冲区从 :attr:`state_dict` 复制到仅此模块,而不是其子模块。 这在每次调用子模块时都会被调用。 在 :meth:`~torch.nn.Module.load_state_dict` 中被调用。为此模块在输入 :attr:`state_dict` 中保存的元数据为 :attr:`local_metadata`。 模块在输入 :attr:`state_dict` 中的元数据提供为 :attr:`local_metadata`。 对于没有元数据的 state 字典,:attr:`local_metadata`为空。 子类可以通过使用实现类特定的向后兼容加载 本地元数据中的版本号 `local_metadata.get("version", None)`。 此外,:attr:`local_metadata` 还可以包含键 `assign_to_params_buffers` 表示是否应该将键分配给状态字典中对应的张量。 分配给状态字典中对应的张量。 .. 注意:: `:attr:`state_dict` 并非与输入的 `:attr:`state_dict` 相同的对象。 所以 `:attr:`state_dict` 并不等于 `:meth:`~torch.nn.Module.load_state_dict`。 它可以被修改。 Args: state_dict(字典):包含参数和持久缓冲区的字典。 持久缓冲区。 prefix(字符串):在此处使用的参数和缓冲区的前缀。 模块 local_metadata (dict): 包含此模块元数据的字典。 查看 strict (bool): 是否严格强制要求 :attr:`state_dict` 与 :attr:`prefix` 匹配键名。 attr:`state_dict` 与 :attr:`prefix` 匹配的键名。 本模块的参数和缓冲区 missing_keys(字符串列表):如果 strict=True,将缺少的键添加到该列表中 此列表 unexpected_keys(字符串列表):如果 strict=True,将意外的键添加到 列表的关键 error_msgs(字符串列表):应将错误消息添加到此列表中,并将一起报告 ,并在 meth:`~torch.nn.Module.load_state_dict` "源代码"
钩子 self._load_state_dict_pre_hooks.(): hook( state_dict, 前缀, 本地元数据, 严格的, 缺少键, 预期之外的键, 错误信息, ) 持久缓冲区 = { k: v k, v self._缓冲区.项目() 如果 k not self.非持久缓冲区集合 } 本地名称参数 = itertools.chain( self.参数.项目(), 持久缓冲区.项目() ) 本地状态 = {k: v k, v 本地名称参数 如果 v not } 分配给参数缓冲区 = 本地元数据.获取(分配到参数缓冲区, 错误) 使用交换张量 = 火炬.未来.在转换时获取交换模块参数() 名称, 参数 local_state.项目(): key = 前缀 + 名称 如果 key state_dict: 输入参数 = state_dict[] 如果 not 火炬.覆盖.是否与张量类似(输入参数): 错误信息.追加( f'在复制名为 " 的参数时 '{}", ' " "期望从检查点接收 torch.Tensor 或类似 Tensor 的对象,但实际接收到了 " f"接收到的 "{类型(输入参数)}" ) 继续 # 这用于避免将未初始化的参数复制到 非懒加载模块,因为它们没有进行检查的钩子 在这种情况下,当访问 .shape 属性时会出错。 是懒加载参数 = 火炬.nn.参数.is_lazy(参数) 向后兼容:从 0.3.* 版本加载 1 维张量到 0.4+ 版本 如果 ( not 是懒加载参数 长度(参数.shape) == 0 长度(输入参数.shape) == 1 ): 输入参数 = 输入参数[0] 如果 not 是懒加载参数 输入参数.形状 != 参数.shape: # 本地形状应与检查点中的形状匹配 错误信息.追加( f"大小不匹配,对于"{}复制形状为{输入参数.shape}从检查点开始, f当前模型中的形状是{参数.shape} ) 继续 如果 ( 参数.是否是元数据 not 输入参数.是否是元数据 not 分配给参数缓冲区 ): warnings.警告( f"对于"{}从检查点中的非元参数复制到元参数 当前模型中的参数,这是一个空操作。(您是指“) 将 `assign=True` 传递给 `assign` 以将状态字典中的项目分配给它们的 相应模块中的键而不是直接复制它们? ) try: 火炬.不梯度(): 如果 使用交换张量: 新输入参数 = 参数.模块加载( 输入参数, 分配=分配给参数缓冲区 ) 如果 id(新输入参数) == id(输入参数) id( 新输入参数 ) == id(参数): 提升 运行时错误( "模块加载返回了 self 或 other,请.detach() " "如果返回模块加载中的输入之一的结果" ) 如果 isinstance(参数, 火炬.nn.参数): 如果 not isinstance(新输入参数, 火炬.nn.参数): 新输入参数 = 火炬.nn.参数( 新输入参数, 需要梯度=参数.需要梯度, ) 否则: 新输入参数.需要梯度_(参数.需要梯度) 火炬.工具.交换张量(参数, 新输入参数) 删除 新输入参数 elif 分配到参数缓冲区: # 上面的形状检查已经完成 如果 isinstance(参数, 火炬.nn.参数): 如果 not isinstance(输入参数, 火炬.nn.参数): 输入参数 = 火炬.nn.参数( 输入参数, 需要梯度=参数.requires_grad ) 否则: 输入参数.需要梯度_(参数.需要梯度) setattr(self, 名称, 输入参数) 否则: 参数.复制_(输入参数) 除了 异常 作为 ext: ex: 行动 = "交换" 如果 使用交换张量 否则 "复制" 错误信息.追加( f'当{行动}参数名为{}", ' " f"在模型中的维度是"{参数.尺寸()} f"在检查点中的维度是"{输入参数.尺寸()}," f"发生异常:"{ext: ex.参数} ) elif 严格的: 缺少键.追加() 额外状态键 = 前缀 + _EXTRA_STATE_KEY_SUFFIX 如果 ( getattr(self., 设置额外状态, 模块.设置额外状态) not 模块.设置额外状态 ): 如果 额外状态键 state_dict: self.设置额外状态(state_dict[额外状态键]) elif 严格的: 缺少键.追加(额外状态键) elif 严格的 (额外状态键 state_dict): 预期之外的键.追加(额外状态键) 如果 严格的: key state_dict.(): 如果 .以...开头(前缀) key != 额外状态键: 输入名称 = [长度(前缀) ].分割(“点”, 1) # 必须是模块如果它有属性 如果 长度(输入名称) > 1: 如果 输入名称[0] not self.模块: 预期之外的键.追加() elif 输入名称[0] not local_state: 预期之外的键.追加()
[文档] def 加载状态字典( self, state_dict: 映射[字符串, 任意] 严格的: 布尔类型 = True, 分配: 布尔类型 = ): r将参数和缓冲区从 :attr:`state_dict` 复制到本模块及其后代。 如果 :attr:`strict` 为 ``True``,则 attr:`state_dict` 的键必须与该模块的 :meth:`~torch.nn.Module.state_dict` 函数返回的键完全匹配。 如果 :attr:`assign` 为 ``True``,则优化器必须在创建之后。 .. 警告:: 如果 :attr:`assign` 为 ``True``,则优化器必须在创建之后。 调用 :attr:`load_state_dict` 方法,除非 func:`~torch.__future__.get_swap_module_params_on_conversion` 设置为 ``True``。 Args: state_dict(字典):包含参数和持久缓冲区的字典。 持久缓冲区。 strict (bool, 可选): 是否严格检查 `state_dict` 中的键是否与该模块的 `state_dict` 函数返回的键匹配。默认:`True` in :attr:`state_dict` 中的键必须与该模块的 :meth:`~torch.nn.Module.state_dict` 函数返回的键匹配。默认:`True` meth:`~torch.nn.Module.state_dict` 函数。默认:`True` assign (bool, 可选): 当设置为 `False` 时,不分配张量的属性 当前模块中保留,而将其设置为“True”则保留 状态字典中张量的属性。唯一 异常是 `:class:`~torch.nn.Parameter` 的 `requires_grad` 字段 对于模块中的值被保留的情况。 默认:``False`` 返回: ``NamedTuple``包含`missing_keys`和`unexpected_keys`字段: * **missing_keys** 是一个包含任何预期键的字符串列表。 由该模块预期但未在提供的 ``state_dict`` 中出现的键。 * **unexpected_keys** 是一个包含未由该模块预期但出现在提供的 ``state_dict`` 中的键的字符串列表。 由该模块预期但未在提供的 ``state_dict`` 中出现的键。 注意: 如果参数或缓冲区注册为“None”,则其对应键 存在于:attr:`state_dict`,:meth:`load_state_dict` 将引发 运行时错误。 "源代码" 如果 not isinstance(state_dict, 映射): 提升 类型错误( f期望 state_dict 是类似字典的,得到{类型(state_dict)} ) 缺少键: 列表[字符串] = [] 预期之外的键: 列表[字符串] = [] 错误信息: 列表[字符串] = [] # 拷贝状态字典以便 _load_from_state_dict 可以修改它 元数据 = getattr(state_dict, _metadata, ) 状态字典 = 有序字典(state_dict) 如果 元数据 not : # mypy 并不知道 "_metadata" 存在于状态字典中 state_dict.元数据 = 元数据 # 类型: 忽略[attr-defined] def 加载(模块, 本地状态字典, 前缀=""): 本地元数据 = {} 如果 元数据 否则 元数据.获取(前缀[-1] {}) 如果 分配: 本地元数据[分配到参数缓冲区] = 分配 模块.从状态字典加载( 本地状态字典, 前缀, 本地元数据, True, 缺少键, 预期之外的键, 错误信息, ) 名称, 儿童 模块.模块.项目(): 如果 儿童 not : 子前缀 = 前缀 + 名称 + "." 子状态字典 = { k: v k, v 本地状态字典.项目() 如果 k.以...开头(前缀子项) } 加载(儿童, 子状态字典, 前缀子项) # noqa: F821 # 注意,钩子可以修改 missing_keys 和 unexpected_keys。 不兼容的键 = _不兼容键(缺少键, 预期之外的键) 钩子 模块.加载状态字典后钩子.(): out = hook(模块, 不兼容的键) 断言 out , ( 钩子注册到 `register_load_state_dict_post_hook` 后不再使用 预期返回新值,如果需要修改 incompatible_keys "应该在原地完成。" ) 加载(self, state_dict) 删除 加载 如果 严格的: 如果 长度(预期之外的键) > 0: 错误信息.插入( 0, "state_dict 中存在意外的键:"{}..格式( “,”.加入(f“”{k}'' k 预期之外的键) ), ) 如果 长度(缺少键) > 0: 错误信息.插入( 0, "state_dict 中缺少键:"{}..格式( “,”.加入(f“”{k}'' k 缺少键) ), ) 如果 长度(错误信息) > 0: 提升 运行时错误( 加载状态字典时出错{}:\n\t{}".格式( self..__name__, "\n\t".加入(错误信息) ) ) 返回 _不兼容键(缺少键, 预期之外的键)
def 命名成员( self, get_members_fn, 前缀="", 递归=True, 删除重复项: 布尔类型 = 真实 ): r"""帮助产生各种模块的名称 + 成员。""" 备忘录 = 集合() 模块 = ( self.命名模块(前缀=前缀, 删除重复项=删除重复项) 如果 递归 否则 [前缀, self] ) 模块前缀, 模块 模块: 成员 = get_members_fn(模块) k, v 会员: 如果 v v 描述: 继续 如果 删除重复项: 描述.添加(v) 名称 = 模块前缀 + ("." 如果 模块前缀 否则 "") + k 产生 名称, v
[文档] def parameters(self, recurse: bool = True) -> Iterator[Parameter]: 返回模块参数的迭代器。 这通常传递给优化器。 参数: 递归(布尔值):如果为 True,则产生此模块的参数 否则,仅返回参数。 是该模块的直接成员。 产生: 参数:模块参数 示例:: >>> # xdoctest: +SKIP("未定义的变量") >>> for param in model.parameters(): >>> 打印(param 的类型(), param.size()) (20L,) (20L, 1L, 5L, 5L) """ for _name, param in self.named_parameters(recurse=recurse): yield param
[文档] def named_parameters( self, prefix: str = "", recurse: bool = True, remove_duplicate: bool = True ) -> Iterator[tuple[str, Parameter]]: r"""返回模块参数的迭代器,同时返回参数的名称以及参数本身。 参数: 前缀(str):所有参数名称的前缀。 递归(布尔值):如果为 True,则产生此模块的参数 否则,仅返回参数。 是该模块的直接成员。 移除重复项(布尔值,可选):是否移除重复项 结果中的参数。默认为 True。 产出: (str, 参数): 包含名称和参数的元组 示例:: >>> # xdoctest: +SKIP("未定义的变量") >>> for name, param in self.named_parameters(): >>> 如果 name 在 ['bias'] 中: >>> 打印(param.size()) """ gen = self._named_members( lambda 模块: 模块._parameters.items(), prefix=prefix, recurse=recurse, remove_duplicate=remove_duplicate, ) yield from gen
[文档] def buffers(self, recurse: bool = True) -> 迭代器[Tensor]: r"""返回模块缓冲区的迭代器。 Args: recurse (bool): 如果为 True,则生成当前模块及其所有子模块的缓冲区。否则,仅生成当前模块的直接成员缓冲区。 和所有子模块的。否则,仅生成当前模块的直接成员缓冲区。 是当前模块的直接成员缓冲区。 产生: torch.Tensor:模块缓冲区 示例:: >>> # xdoctest:+SKIP("未定义变量") >>> for buf in model.buffers(): >>> 打印(buf 的类型, buf 的大小()) (20L,) (20L, 1L, 5L, 5L) """ 对于 _, buf in self.named_buffers(recurse=recurse): yield buf
[文档] def named_buffers( self, 前缀: str = "", 递归: bool = True, 删除重复: bool = True ) -> 迭代器[tuple[str, Tensor]]: r"""返回模块缓冲区的迭代器,同时返回缓冲区的名称以及缓冲区本身。 参数: 前缀(str):所有缓冲区名称的前缀。 递归(bool,可选):如果为 True,则产生此模块的缓冲区 否则,仅返回缓冲区。 是该模块的直接成员。默认为 True。 remove_duplicate (bool, 可选): 是否在结果中移除重复的缓冲区。默认为 True。 Yields: (str, torch.Tensor): 包含名称和缓冲区的元组 示例:: >>> # xdoctest: +SKIP("undefined vars") >>> for name, buf in self.named_buffers(): >>> if name in ['running_var']: >>> print(buf.size()) """ gen = self._named_members( lambda 模块: 模块._buffers.items(), prefix=prefix, recurse=recurse, remove_duplicate=remove_duplicate, ) yield from gen
[文档] def children(self) -> 迭代器["模块"]: r"""返回一个立即子模块的迭代器。 Yields: 模块:一个子模块 """ for _name, module in self.named_children(): yield module
[文档] def named_children(self) -> Iterator[tuple[str, "Module"]]: r"""返回一个遍历直接子模块的迭代器,同时提供模块名称及其本身。 Yields: (str, Module): 包含名称和子模块的元组 示例:: >>> # xdoctest: +SKIP("未定义的变量") >>> for name, module in model.named_children(): >>> if name in ['conv4', 'conv5']: >>> 打印(module) """ memo = set() for name, module in self._modules.items(): 如果模块不为空且模块不在 memo 中 将模块添加到 memo 中 生成 name 和 module
[文档] def modules(self) -> 迭代器["Module"]: r"""遍历网络中所有模块。 Yields: Module: 网络中的一个模块 注意: 重复模块只返回一次。在下文中 示例,`l` 将只返回一次。 示例: >>> l = nn.Linear(2, 2) >>> net = nn.Sequential(l, l) >>> for idx, m in enumerate(net.modules()): ... 打印(idx, '->', m) 0 -> 顺序( (0): 线性层(in_features=2, out_features=2, bias=True) (1): 线性层(in_features=2, out_features=2, bias=True) ) 1 -> 线性层(in_features=2, out_features=2, bias=True) """ for _, module in self.named_modules(): yield module
[文档] def named_modules( self, memo: Optional[set["Module"]] = None, prefix: str = "", remove_duplicate: 布尔 = True, ): 返回网络中所有模块的迭代器,同时返回模块的名称以及模块本身。 Args: memo: 存储已添加到结果中的模块集合的备忘录 prefix: 将添加到模块名称的前缀 remove_duplicate: 是否在结果中删除重复的模块实例 或否 产生: (str,模块):名称和模块的元组 注意: 重复的模块只返回一次。在以下 示例,``l`` 只会返回一次。 示例:: >>> l = nn.Linear(2, 2) >>> net = nn.Sequential(l, l) >>> for idx, m in enumerate(net.named_modules()): ... 打印(idx, '->', m) 0 -> ('', Sequential( (0): Linear(in_features=2, out_features=2, bias=True) (1): 线性(in_features=2, out_features=2, bias=True) )) 1 -> ('0', 线性(in_features=2, out_features=2, bias=True)) """ 如果 memo 为 None: memo = set() 如果 self 不在 memo 中: 如果 remove_duplicate: self.memo.add() yield 前缀, self for name, module in self._modules.items(): if module is None: 继续执行 模块前缀 = prefix + ("." if prefix else "") + name yield from module.named_modules( memo, 模块前缀, 删除重复项 )
[文档] def train(self: T, mode: bool = True) -> T: r"""将模块设置为训练模式。 这只对某些模块有效。有关特定模块在训练/评估模式下的行为详情,请参阅相关文档。 particular modules for details of their behaviors in training/evaluation 模式,即它们是否受影响,例如::class:`Dropout`,:class:`BatchNorm`, 等。 Args: mode (bool): 是否设置训练模式(``True``)或评估模式 mode(``False``)。默认:``True``。 返回: 模块:self """ 如果不是 bool 类型: 则抛出 ValueError 异常:“期望训练模式为布尔值”。 self.training = mode for module in self.children(): module.train(mode) 返回 self
[文档] def eval(self: T) -> T: r"""将模块设置为评估模式。 这仅对某些模块有影响。请参阅文档。 特定模块在训练/评估中的行为细节 模式,即它们是否受到影响,例如::class:`Dropout`,:class:`BatchNorm` 等等。 这与:meth:`self.train(False) `等效。 请参阅:ref:`locally-disable-grad-doc`,以比较它与.eval()以及可能与之混淆的几个类似机制。 `.eval()`和可能与其混淆的几个类似机制。 返回: 模块:self """ 返回 self.train(False)
[文档] def requires_grad_(self: T, requires_grad: bool = True) -> T: r"如果自动微分应该记录此模块中参数的操作,则更改此设置。" 此方法设置参数的 :attr:`requires_grad` 属性 改变位置。 此方法对于冻结模块的一部分以进行微调很有帮助 或单独训练模型的部分(例如,GAN 训练)。 请参阅:ref:`locally-disable-grad-doc` 了解其与 `.requires_grad_()` 以及可能与之混淆的几个类似机制的对比。 `.requires_grad_()` 和几个可能与其混淆的类似机制。 参数: requires_grad (bool): 是否应该记录此模块中参数的操作。默认:``True``。 参数在此模块中。默认:``True``。 返回值: 模块:self """ for p in self.parameters(): p.requires_grad_(requires_grad) return self
[文档] def zero_grad(self, set_to_none: bool = True) -> None: 重置所有模型参数的梯度。 更多上下文请参阅 :class:`torch.optim.Optimizer` 下的类似函数。 参数: 将梯度设置为 None(而不是设置为 0)。 详细信息请参阅::meth:`torch.optim.Optimizer.zero_grad`。 """ 如果 getattr(self, "_is_replica", False): warnings.warn( 从使用 nn.DataParallel()创建的模块中调用.zero_grad()没有任何效果。 参数是从原始模块中复制的(以可微分的方式)。 这意味着它们不是 autograd 的叶子节点,因此不会累积梯度。 如果你在前向方法中需要梯度,请考虑使用 autograd.grad。 ) for p in self.parameters(): 如果 p.grad 不是 None: 如果设置 None p.grad = None else: 如果 p.grad.grad_fn 不是 None p.grad.detach_() else: p.grad.requires_grad_(False) p.grad.zero_()
[文档] def share_memory(self: T) -> T: r"""参见 :meth:`torch.Tensor.share_memory_`。” return self._apply(lambda t: t.share_memory_())
def _获取名称(self): 返回
self..__name__
[文档] def extra_repr(self) -> str: 返回模块的额外表示。 打印自定义额外信息,您应该重新实现 此方法应用于您的模块。单行和多行均可。 字符串是可接受的。 """ 返回 ""
def __repr__(self): 我们将额外的 repr 视为子模块,每行一个项目 额外行 = [] 额外表示
= self.额外表示() # 空字符串将被分割成列表 [''] 如果 额外表示: 额外行 = 额外表示.分割("输入文本翻译为简体中文为:\n") 子行 = [] , 模块 self.模块.项目(): mod_str = 表示(模块) mod_str = _addindent(mod_str, 2) 子行.追加(“(” + key + "): " + mod_str) = 额外行 + 子行 主字符串 = self._获取名称() + “(” 如果 : # 简单的一行信息,大多数内置模块都会使用 如果 长度(额外行) == 1 not 子行: 主字符串 += 额外行[0] 否则: 主字符串 += "输入文本翻译为简体中文为:\n " + "输入文本翻译为简体中文为:\n ".加入() + "输入文本翻译为简体中文为:\n" 主字符串 += )" 返回 主字符串 def __dir__(self): 模块属性 = 目录(self.) attrs = 列表(self.字典.()) 参数 = 列表(self.参数.()) 模块 = 列表(self.模块.()) 缓冲区 = 列表(self._缓冲区.()) = 模块属性 + attrs + 参数 + 模块 + 缓冲区 # 删除非法 Python 变量名的属性 = [key key 如果 not [0].isdigit()] 返回 排序() def _为数据并行复制(self): 复制品 = self.__new__(类型(self)) 复制品.字典 = self.字典.复制() # 复制品本身没有参数,复制品引用原始 模块。 复制品.参数 = {} 复制品._缓冲区 = 复制品._缓冲区.复制() 复制品.模块 = 复制品.模块.复制() 复制品._是副本 = 真实 # 类型:忽略[赋值] 返回 复制品
[文档] def 编译(self, *args, **kwargs): """ 使用 :func:`torch.compile` 编译此模块的前向。 此模块的 `__call__` 方法已编译,所有参数都原样传递给 :func:`torch.compile`。 有关此函数参数的详细信息,请参阅 :func:`torch.compile`。 请参阅 :func:`torch.compile` 了解此函数的参数详情。 """ self._compiled_call_impl = torch.compile(self._call_impl, *args, **kwargs)

© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,并使用 Read the Docs 提供的主题。

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

查找开发资源,获取您的疑问解答

查看资源