• 文档 >
  • 模块代码 >
  • torch >
  • torch.nn.utils.parametrizations
快捷键

torch.nn.utils.parametrizations 的源代码

# mypy: 允许未类型化定义
来自 枚举 导入 自动, 枚举
来自 打字 导入 可选

导入 火炬
导入 torch.nn.functional 作为 F
来自 火炬 导入 张量
来自 torch.nn.modules 导入 模块
来自 torch.nn.utils 导入 参数化


__all__ = [正交, 谱范数, 权重范数]


def _is_orthogonal(Q, eps=):
    n, k = Q.尺寸(-2), Q.尺寸(-1)
    Id = 火炬.眼睛(k, 数据类型=Q.数据类型, 设备=Q.设备)
    一个合理的 eps,但不要太大
    eps = 10.0 * n * 火炬.finfo(Q.数据类型).eps
    返回 火炬.allclose(Q.mH @ Q, Id, 精度=eps)


def _正交化_(A):
    假设 A 是一个高矩阵。

计算 Q 因子,使得 A = QR(A 可能是复数),并且 diag(R)是实数且非负。
"源代码"
    X, 塔乌 = 火炬.geqrf(A)
    Q = 火炬.线性代数.ouseholder 乘积(X, )
    X 的对角线是 R 的对角线(R 总是实数),所以我们通过其符号进行归一化
    Q *= X.对角线(dim1=-2, dim2=-1).sgn().展平(-2)
    返回 Q


 _OrthMaps(枚举):
    矩阵指数 = 自动()
    凯莱 = 自动()
    ouseholder = 自动()


 _正交(模块):
    基础: 张量

    def 初始化(
        self, 重量, 正交映射: _OrthMaps, *, 使用平凡化=真实
    ) -> :
        超级().初始化()

        # 房屋持有者复数
        # 对于复数张量,无法从反射器计算必要的张量 `tau`。
        # linalg.householder_product。
        # 要看到这一点,请注意反射器的形状如下:
        # 0 0 0
        # * 0 0
        # * * 0
        # 对于复矩阵,给出 n(n-1) 个(实)参数。现在,你需要 n^2 个参数
        将单元矩阵参数化。单独保存 tau 也不行,因为
        并非每个 `(A, tau)` 的组合都给出一个幺正矩阵,这意味着如果我们优化
        将它们作为独立的张量时,我们不会保持约束
        等价的推理也适用于矩形矩阵
        如果 重量.是复杂的()  正交映射 == _OrthMaps.房屋持有者:
            提升 ValueError(
                "房屋持有者参数化不支持复数张量。"
            )

        self.形状 = 重量.形状
        self.正交映射 = 正交映射
        如果 使用平凡化:
            self.注册缓冲区(基础, )

    def 前向(self, X: 火炬.张量) -> 火炬.张量:
        n, k = X.尺寸(-2), X.尺寸(-1)
        交换 = n < k
        如果 交换:
            X = X.mT
            n, k = k, n
        # 这里 n > k 且 X 是一个高矩阵
        如果 (
            self.正交映射 == _OrthMaps.矩阵指数
             self.正交映射 == _正交映射.凯莱
        ):
            我们只需要 n x k - k(k-1)/2 个参数
            X = X.三角()
            如果 n != k:
                嵌入到一个正方形矩阵中
                X = 火炬.(
                    [X, X.新零(n, n - k).展开(*X.shape[-2] -1, -1)], 暗淡=-1
                )
            A = X - X.mH
            A 是斜对称的(或斜厄米对称的)
            如果 self.正交映射 == _OrthMaps.矩阵指数:
                Q = 火炬.矩阵指数(A)
            elif self.正交映射 == _OrthMaps.凯莱:
                # 计算凯莱收缩 (I+A/2)(I-A/2)^{-1}
                Id = 火炬.眼睛(n, 数据类型=A.数据类型, 设备=A.设备)
                Q = 火炬.线性代数.求解(
                    火炬.添加(Id, A, 阿尔法=-0.5), 火炬.添加(Id, A, 阿尔法=0.5)
                )
            # Q 现在是正交(或幺正)的,大小为(..., n, n)
            如果 n != k:
                Q = Q[..., :k]
            # Q 的大小是 X(尽管可能是转置的)
        否则:
            # X 是实数,因为我们不支持复数形式的豪斯霍尔德变换
            A = X.三角(对角线=-1)
            塔乌 = 2.0 / (1.0 + (A * A).总和(暗淡=-2))
            Q = 火炬.线性代数.ouseholder 乘积(A, )
            # X 的对角线是 1 和 -1
            因此我们不想通过这个来区分或者更新 X 的对角线,所以进行了类型转换
            Q = Q * X.对角线(dim1=-2, dim2=-1).int().展平(-2)

        如果 有属性(self, 基础):
            Q = self.基础 @ Q
        如果 交换:
            Q = Q.mT
        返回 Q  # type: ignore[possibly-undefined]

    @torch.自动微分.不梯度()
    def 右逆(self, Q: 火炬.张量) -> 火炬.张量:
        如果 Q.形状 != self.shape:
            提升 ValueError(
                f预期是一个矩阵或矩阵批次的形状{self.shape}. 
                f"获得了一个形状的张量"{Q.shape}
            )

        Q 初始化 = Q
        n, k = Q.尺寸(-2), Q.尺寸(-1)
        转置 = n < k
        如果 转置:
            Q = Q.mT
            n, k = k, n

        # 我们始终确保在每条路径上都要复制 Q
        如果 not 有属性(self, "基础"):
            # 右逆 [右逆 expm cayley]
            # 如果我们不使用 use_trivialization=True,我们只需实现前向的逆
            # 映射对于豪斯霍尔德映射。为了理解这一点,考虑 Cayley 映射,
            我们需要找到一个矩阵 \(X \in \mathbb{R}^{n \times k}\),使得:
            \(Y = \text{torch.cat}([X.tril(), X.new_zeros(n, n - k).expand(*X.shape[:-2], -1, -1)], dim=-1)\)
            \(A = Y - Y.mH\)
            \(cayley(A)[:, :k]\)
            不清楚如何给出原始张量。
            或许通过类似于 QR 的代数操作?
            爱德曼、阿里亚斯和史密斯中的推论 2.2?
            如果 (
                self.正交映射 == 正交映射.凯莱
                 self.正交映射 == 正交映射.矩阵指数
            ):
                提升 不支持的操作异常(
                    "无法将矩阵指数赋值 "
                    "或凯莱参数化赋值,当 use_trivialization=False 时。"
                )

            # 如果参数化等于 _OrthMaps.householder,则通过 QR 分解使 Q 正交。
            # 这里 Q 总是真实的,因为我们不支持 householder 和复矩阵。
            # 见注解[Householder 复数]
            A, 塔乌 = 火炬.geqrf(Q)
            # 我们希望有一个分解 X = QR,使得 diag(R) > 0,否则我们可以
            # 将正交矩阵 Q 分解为 Q = (-Q)@(-Id),这是一个有效的 QR 分解
            Q 的对角线是 R 的 qr 分解的对角线
            A.对角线(dim1=-2, dim2=-1).sign_()
            # 等于零是可以的,因为 LAPACK 在不希望时返回精确的零
            # 不使用特定的反射
            A.对角线(dim1=-2, dim2=-1)塔乌 == 0.0] *= -1
            返回 A.mT 如果 transpose 否则 A
        否则:
            如果 n == k:
                我们检查 Q 是否正交
                如果 not _is_orthogonal(Q):
                    Q = _make_orthogonal(Q)
                否则:  # 是正交的
                    Q = Q.克隆()
            否则:
                # 完成将一个 Q 矩阵转换为一个 n x n 正交矩阵
                N = 火炬.randn(
                    *(Q.尺寸()[:-2] + (n, n - k)), 数据类型=Q.数据类型, 设备=Q.设备
                )
                Q = 火炬.([Q, N] 暗淡=-1)
                Q = _make_orthogonal(Q)
            self.基础 = Q

            # 返回 -Id 是必要的,因为我们使用对角线
            # 使用 Householder 参数化。使用 -Id 使得:
            householder(torch.zeros(m,n)) == torch.eye(m,n)
            普通版本的 eye_like
            neg_Id = 火炬.与...相同形状的零(Q_init)
            否定 ID.对角线(dim1=-2, dim2=-1).填充_(-1.0)
            返回 负标识符


[文档]def 正交的( 模块: 模块, 名称: 字符串 = 权重, 正交映射: 可选[字符串] = , *, 使用平凡化: 布尔类型 = True, ) -> 模块: r将正交或单位矩阵参数化应用于矩阵或矩阵批。 设 :math:`\mathbb{K}` 为 :math:`\mathbb{R}` 或 :math:`\mathbb{C}` 参数化的矩阵 :math:`Q \in \mathbb{K}^{m \times n}` 是 **正交** 的 .. math:: \begin{align*} \( Q^{\text{H}}Q = \mathrm{I}_n \) (如果 \( m \geq n \)) QQ^{\text{H}} = \mathrm{I}_m \text{(如果 } m < n \text{)} \end{align*} 当 \( Q \) 是复数时,\( Q^{\text{H}} \) 是共轭转置 当 \( Q \) 是实值时,其转置 \( \mathrm{I}_n \) 是 \( n \) 维单位矩阵。 简单来说,当 \( m \geq n \) 时,\( Q \) 将具有正交归一列。 否则,具有正交归一行。 如果张量具有超过两个维度,我们将其视为形状为`(..., m, n)`的矩阵批次。 矩阵 :math:`Q` 可以通过三种不同的 `orthogonal_map` 在原始张量的基础上进行参数化: - ``"matrix_exp"``/``"cayley"``: the :func:`~torch.matrix_exp` :math:`Q = \exp(A)` and the `Cayley map`_ math:`Q = (\mathrm{I}_n + A/2)(\mathrm{I}_n - A/2)^{-1}` are applied to a skew-symmetric math:`A` to give an orthogonal matrix. - ``"householder"``: 使用 Householder 反射器计算乘积 (:func:`~torch.linalg.householder_product`). ``"matrix_exp"``/``"cayley"`` 通常比 ``"householder"`` 更快地使参数化权重收敛,但它们在计算非常瘦或非常宽的矩阵时速度较慢。 ``"householder"``, 但它们在计算非常瘦或非常宽的矩阵时速度较慢。 如果 `use_trivialization=True`(默认),参数化实现了“动态平凡化框架” 额外矩阵 :math:`B \in \mathbb{K}^{n \times n}` 存储于 `module.parametrizations.weight[0].base`。这有助于 参数化层的收敛以牺牲一些额外内存使用为代价。 查看《流形上基于梯度的优化的平凡化》_。 math:`Q` 的初始值: 如果原始张量未参数化且`use_trivialization=True`(默认),初始值 原张量 \( Q \) 的特征值是正交的(或在复数情况下是酉的) 并且它通过 QR 分解进行正交化(参见:func:torch.linalg.qr)。 同样,当未参数化且 `orthogonal_map="householder"` 时,即使 `use_trivialization=False`,也会发生这种情况。 否则,初始值是所有已注册的组成结果 应用于原始张量的参数化。 .. 注意:: 此函数使用参数化功能实现 在::func:`~torch.nn.utils.parametrize.register_parametrization`。 .. _`凯莱映射`: https://zh.wikipedia.org/wiki/凯莱变换#矩阵映射 .. _`流形上基于梯度的优化的平凡化`: https://arxiv.org/abs/1909.09501 Args: 模块 (nn.Module):注册参数化的模块。 名称 (str, 可选):要正交化的张量的名称。默认值:`"weight"`。 orthogonal_map (str, 可选): 以下之一:``"matrix_exp"``, ``"cayley"``, ``"householder"``。 默认:如果矩阵是方阵或复数,则为 ``"matrix_exp"``, 否则为 ``"householder"``。 use_trivialization (bool, 可选): 是否使用动态平凡化框架。 默认:``True``。 返回: 将具有正交参数化的原始模块注册到指定的 重量 示例:: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_LAPACK) >>> orth_linear = 正交线性层(nn.Linear(20, 40)) >>> orth_linear ParametrizedLinear( in_features=20, out_features=40, bias=True (parametrizations): ModuleDict( (weight): ParametrizationList( (0): _正交() ) ) ) >>> # xdoctest: +IGNORE_WANT >>> Q = orth_linear.weight >>> torch.dist(Q.T @ Q, torch.eye(20)) tensor(4.9332e-07) "源代码" 权重 = getattr(模块, 名称, ) 如果 not isinstance(重量, 张量): 提升 ValueError( f模块{模块}'没有名为'的参数或缓冲区{名称} ) 我们可以将其实现为 1 维张量的球面映射 但我认为这会让更多的人受害而不是受益 如果 重量.维数 < 2: 提升 ValueError( 预期得到一个矩阵或矩阵批 f获得一个张量{重量.ndim}尺寸." ) 如果 正交映射 : 正交映射 = ( 矩阵指数 如果 重量.尺寸(-2) == 重量.尺寸(-1) 重量.是复杂的() 否则 户主 ) 正交枚举 = getattr(_正交映射, 正交映射, ) 如果 orth_enum : 提升 ValueError( '正交映射必须是 "matrix_exp"、"cayley" 或 "householder" 之一。' f"获取:"{orthogonal_map}" ) orth = 正交(重量, 正交枚举, 使用平凡化=使用平凡化) 参数化.注册参数化(模块, 名称, 正交, 不安全=True) 返回 模块
_权重归一化(模块): def 初始化( self, 暗淡: 可选[int] = 0, ) -> : 超级().初始化() 如果 维度 : 维度 = -1 self.维度 = 维度 def 前向(self, 重量_g, 重量_v): 返回 火炬._权重归一化(重量_v, 重量_g, self.暗淡) def 右逆矩阵(self, 重量): 重量_g = 火炬.除维度外的范数(重量, 2, self.暗淡) 重量_v = 权重 返回 重量_g, 重量_v
[文档]def 重量归一化(模块: 模块, 名称: 字符串 = 权重, 暗淡: 整型 = 0): r将权重归一化应用于给定模块中的参数。 .. math:: \mathbf{w} = g \dfrac{\mathbf{v}}{\|\mathbf{v}\|} 权重归一化是一种重新参数化方法,将权重张量的幅度与其方向解耦。这取代了指定的参数。 权重张量的幅度与其方向解耦。这取代了指定的参数。 通过:attr:`name`使用两个参数:一个指定大小,另一个指定方向。 默认情况下,使用`dim=0`时,范数是独立于每个输出通道/平面的计算的。 要计算整个权重张量的范数,请使用。 要计算整个权重张量的范数,请使用。 `dim=None` 查看 https://arxiv.org/abs/1602.07868 Args: 模块(Module):包含模块 名称(str,可选):权重参数的名称 dim(int,可选):计算范数的维度 返回: 带权重范数钩子的原始模块 示例:: >>> m = weight_norm(nn.Linear(20, 40), name='weight') >>> m ParametrizedLinear( in_features=20, out_features=40, bias=True (parametrizations): ModuleDict( (weight): ParametrizationList( (0): _WeightNorm() ) ) ) >>> m.parametrizations.weight.original0.size() torch.Size([40, 1]) >>> m.parametrizations.weight.original1.size() torch.Size([40, 20]) "源代码" _权重归一化 = 权重归一化(暗淡) 参数化.注册参数化(模块, 名称, _权重归一化, 不安全=True) def _权重归一化兼容钩子( state_dict, 前缀, 本地元数据, 严格的, 缺少键, 预期之外的键, 错误信息, ): g 键 = f"{前缀}{名称}_g" v 键 = f"{前缀}{名称}_v" 如果 g 键 状态字典 v 键 state_dict: 原始 0 = state_dict.弹出(g 键) 原始文本 1 = state_dict.弹出(v_键) state_dict[f"{前缀}参数化。{名称}.原始 0] = 原始 0 state_dict[f"{前缀}参数化{名称}.原始 1] = 原始 1 模块._register_load_state_dict_pre_hook(_权重归一兼容钩子) 返回 模块
_频谱归一(模块): def 初始化( self, 重量: 火炬.张量, n 次幂迭代次数: 整型 = 1, 暗淡: 整型 = 0, eps: 浮点数 = 1e-12, ) -> : 超级().初始化() 维数 = 重量.维数 如果 维度 >= 维数 维度 < -ndim: 提升 索引错误( "维度超出范围(预期应在范围内“) f"[ "{ndim}, {维数 - 1}]但得到{暗淡})" ) 如果 n_power_iterations 0: 提升 ValueError( 预期 n_power_iterations 为正数,但 f获取 n_power_iterations={n_power_iterations}" ) self.维度 = 维度 如果 维度 >= 0 否则 维度 + 维数 self.eps = eps 如果 维数 > 1: 对于 ndim == 1,我们不需要进行近似(参见 _SpectralNorm.forward) self.n_power_iterations = n_power_iterations weight_mat = self.重塑权重为矩阵(重量) h, w = 权重矩阵.尺寸() u = 权重矩阵.新空(h).正常的(0, 1) v = 权重矩阵.新空(w).正常的(0, 1) self.注册缓冲区("_u", F.normalize(u, 暗淡=0, eps=self.eps)) self.注册缓冲区("_v", F.normalize(v, 暗淡=0, eps=self.eps)) 从 u, v 初始化为一些合理的值开始,通过执行幂方法迭代 幂方法的迭代次数 self._幂方法(权重矩阵, 15) def 将权重重塑为矩阵(self, 重量: 火炬.张量) -> 火炬.张量: # 预设条件 断言 重量.维数 > 1 如果 self.维度 != 0: # 将维度排列到前面 权重 = 重量.排列( self.暗淡, *(d d 范围(重量.暗淡()) 如果 d != self.暗淡) ) 返回 重量.展平(1) @torch.自动微分.不梯度() def 功率法(self, 权重矩阵: 火炬.张量, n 次幂迭代: int) -> : # 请参阅 torch/nn/utils/spectral_norm.py 中的原始注释 # NB: 如果设置 `do_power_iteration`,则 `u` 和 `v` 向量将在 **原地** 更新。这非常重要 # 因为在 `DataParallel` 前向传播中,向量(作为缓冲区)是从并行化模块广播到每个模块副本的 # 因为在 `DataParallel` 前向传播中,向量(作为缓冲区)是从并行化模块广播到每个模块副本的 # 因为在 `DataParallel` 前向传播中,向量(作为缓冲区)是从并行化模块广播到每个模块副本的 # 这是一个动态创建的新模块对象。每个副本 # 都运行自己的谱范数幂迭代。所以简单地将 # 更新后的向量分配给该函数运行的模块,将导致 # 更新永远丢失。下次并行化 # 模块被复制,使用相同的随机初始化的向量! # 广播并使用! # 因此,为了使更改回传,我们依赖于两个 重要行为(也通过测试强制执行): 1. `DataParallel` 不克隆存储的广播张量 # 已在正确设备上;并且它确保 # 并行模块已经在`device[0]`上。 # 2. 如果`out=`参数中的输出张量具有正确的形状,它将 # 只需填充值即可。 # 因此,由于对所有元素都执行了相同的幂迭代, 仅更新张量而不改变设备,将确保设备上的模块副本更新_u 向量 在`device[0]`上的模块副本将通过共享存储来并行化模块 然而,在原地更新`u`和`v`之后,我们需要**克隆** # 然而,在原地更新`u`和`v`之后,我们需要**克隆** 在使用之前先对它们进行归一化处理。这是为了支持 通过两次前向传递进行反向传播,例如,GAN 训练中的常见模式: GAN 训练中的损失函数:损失 = D(real) - D(fake)。否则,引擎将 抱怨需要进行第一次前向传播的变量 (即第二个前向中的 u 和 v 向量)在第二个前向中发生变化。 预设条件 断言 权重矩阵.维数 > 1 _ 范围(n 次幂迭代次数): 权重的谱范数等于 `u^T W v`,其中 `u` 和 `v` 是第一左和右奇异向量。 这种幂迭代产生 `u` 和 `v` 的近似值。 self._u = F.normalize( 火炬.mv(权重矩阵, self.下划线), # 类型:忽略[has-type] 暗淡=0, eps=self.eps, 输出=self._u, # 类型:忽略[has-type] ) self._v = F.normalize( 火炬.mv(权重矩阵.H, self._u), # 类型:忽略[has-type] 暗淡=0, eps=self.eps, 输出=self.下划线, # 类型:忽略[has-type] ) def 前向(self, 重量: 火炬.张量) -> 火炬.张量: 如果 重量.维数 == 1: 更快更精确的路径,无需进行任何近似 返回 F.normalize(重量, 暗淡=0, eps=self.eps) 否则: weight_mat = self._reshape_weight_to_matrix(重量) 如果 self.训练: self.功率法(权重矩阵, self.n 次幂迭代) # 请参阅上方,了解为何需要克隆 u = self._u.克隆(内存格式=火炬.连续格式) v = self.下划线.克隆(内存格式=火炬.连续格式) 正确计算此方法应该是通过 F.bilinear,但 # 它似乎存在一些效率问题: # https://github.com/pytorch/pytorch/issues/58093 sigma (由于 sigma 是数学和工程领域的通用符号,通常不进行翻译,因此保持原文不变。) = 火炬.点积(u, 火炬.mv(权重矩阵, v)) 返回 权重 / 西格玛 def 右逆(self, : 火炬.张量) -> 火炬.张量: #我们可能在这里断言传递的值已经 #满足约束 返回 value
[文档]def 谱范数( 模块: 模块, 名称: 字符串 = 权重, n 次迭代功率: 整型 = 1, eps: 浮点数 = 1e-12, 暗淡: 可选[int] = , ) -> 模块: r将频谱归一化应用于给定模块中的参数。 .. math:: \mathbf{W}_{SN} = \dfrac{\mathbf{W}}{\sigma(\mathbf{W})}, \sigma(\mathbf{W}) = \max_{\mathbf{h}: \mathbf{h} \ne 0} \dfrac{\|\mathbf{W} \mathbf{h}\|_2}{\|\mathbf{h}\|_2}, 当应用于向量时,它简化为。 .. math:: \mathbf{x}_{SN} = \dfrac{\mathbf{x}}{\|\mathbf{x}\|_2} = \dfrac{\mathbf{x}}{\sqrt{x_1^2 + x_2^2 + \cdots + x_n^2}} 光谱归一化稳定了判别器(评论家)的训练 通过降低 Lipschitz 常数在生成对抗网络(GANs)中 模型。:math:`σ` 通过执行一次迭代进行近似。 每次访问权重时使用`幂方法`。如果维度的 权重张量大于 2 时,在幂迭代中将其重塑为 2D 获取谱范数的方法。 请参阅《用于生成对抗网络的谱归一化》_ 。 .. _`幂方法`: https://en.wikipedia.org/wiki/Power_iteration 谱归一化用于生成对抗网络 .. 注意:: 此函数使用参数化功能实现 在::func:`~torch.nn.utils.parametrize.register_parametrization`。它是一个 重新实现::func:`torch.nn.utils.spectral_norm`。 .. 注意:: 当此约束被注册时,与最大奇异值关联的单个向量是估计的,而不是随机采样。 这些向量随后在执行 `power method`_ 的 :attr:`n_power_iterations` 次迭代时更新。 执行 :attr:`n_power_iterations` 次的 `power method`_ 操作。 以模块在 `训练` 模式下被访问。 .. 注意:: 如果是 `_SpectralNorm` 模块,即 `module.parametrization.weight[idx]`, 在移除时处于训练模式,它将执行另一个幂迭代。 如果您想避免这个迭代,请将模块设置为评估模式。 在删除之前。 Args: 模块(nn.Module):包含模块。 名称(str,可选):权重参数的名称。默认值:``"weight"``。 n_power_iterations(int,可选):幂迭代次数。 计算谱范数。默认值:``1``。 eps (float, 可选): ε用于数值稳定性 计算范数。默认值:``1e-12``。 dim (int, 可选): 对应输出数量维度的整数。 默认:``0``,除非是实例化的模块 ConvTranspose{1,2,3}d,当其为``1``时 返回: 将具有新参数化的原始模块注册到指定的 权重 示例:: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_LAPACK) >>> # xdoctest: +IGNORE_WANT("非确定性") >>> snm = spectral_norm(nn.Linear(20, 40)) >>> snm ParametrizedLinear( in_features=20, out_features=40, bias=True (parametrizations): ModuleDict( (weight): ParametrizationList( (0): _SpectralNorm() ) ) ) >>> torch.linalg.matrix_norm(snm.weight, 2) 张量(1.0081, grad_fn=) "源代码" 权重 = getattr(模块, 名称, ) 如果 not isinstance(重量, 张量): 提升 ValueError( f模块{模块}'没有名为'的参数或缓冲区{名称} ) 如果 维度 : 如果 isinstance( 模块, ( 火炬.nn.ConvTranspose1d, 火炬.nn.ConvTranspose2d, 火炬.nn.ConvTranspose3d, ), ): 维度 = 1 否则: 维度 = 0 参数化.注册参数化( 模块, 名称, _频谱归一(重量, n 次幂迭代次数, 暗淡, eps) ) 返回 模块

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源