Shortcuts

torch._lowrank 的源代码

```html
"""实现低秩矩阵的各种线性代数算法。
"""

__all__ = ["svd_lowrank", "pca_lowrank"]

from typing import Optional, Tuple

import torch
from torch import Tensor
from . import _linalg_utils as _utils
from .overrides import handle_torch_function, has_torch_function


def get_approximate_basis(
    A: Tensor, q: int, niter: Optional[int] = 2, M: Optional[Tensor] = None
) -> Tensor:
    """返回张量 :math:`Q`,具有 :math:`q` 个正交列,使得 :math:`Q Q^H A` 近似于 :math:`A`。如果指定了 :math:`M`,则 :math:`Q` 使得 :math:`Q Q^H (A - M)` 近似于 :math:`A - M`。

    .. 注意:: 该实现基于 Halko 等人 2009 年的算法 4.4。

    .. 注意:: 对于一个 k 秩矩阵 :math:`A` 的充分近似,其中 k 是未知的但可以估计,:math:`Q` 列的数量 q 可以根据以下标准选择:通常,:math:`k <= q <= min(2*k, m, n)`。对于大型的低秩矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。

    .. 注意:: 要获得可重复的结果,请重置伪随机数生成器的种子

    参数::
        A (Tensor): 输入张量,大小为 :math:`(*, m, n)`

        q (int): :math:`Q` 列所跨越的子空间的维度。

        niter (int, 可选): 进行子空间迭代的次数;``niter`` 必须是一个非负整数。在大多数情况下,默认值 2 已经足够。

        M (Tensor, 可选): 输入张量的均值,大小为 :math:`(*, 1, n)`。

    参考文献::
        - Nathan Halko, Per-Gunnar Martinsson, 和 Joel Tropp, 使用随机性寻找结构:用于构建近似矩阵分解的概率算法, arXiv:0909.4061 [math.NA; math.PR], 2009 (可在 `arXiv `_ 获取)。
    """

    niter = 2 if niter is None else niter
    m, n = A.shape[-2:]
    dtype = _utils.get_floating_dtype(A)
    matmul = _utils.matmul

    R = torch.randn(n, q, dtype=dtype, device=A.device)

    # 以下代码可以通过使用 torch.geqrf + torch.ormqr 来加速,但 geqrf 不可微分
    A_H = _utils.transjugate(A)
    if M is None:
        Q = torch.linalg.qr(matmul(A, R)).Q
        for i in range(niter):
            Q = torch.linalg.qr(matmul(A_H, Q)).Q
            Q = torch.linalg.qr(matmul(A, Q)).Q
    else:
        M_H = _utils.transjugate(M)
        Q = torch.linalg.qr(matmul(A, R) - matmul(M, R)).Q
        for i in range(niter):
            Q = torch.linalg.qr(matmul(A_H, Q) - matmul(M_H, Q)).Q
            Q = torch.linalg.qr(matmul(A, Q) - matmul(M, Q)).Q

    return Q


[docs]def svd_lowrank( A: Tensor, q: Optional[int] = 6, niter: Optional[int] = 2, M: Optional[Tensor] = None, ) -> Tuple[Tensor, Tensor, Tensor]: r"""返回矩阵的奇异值分解 ``(U, S, V)``,批量矩阵或稀疏矩阵 :math:`A`,使得 :math:`A \approx U diag(S) V^T`。如果指定了 :math:`M`,则对矩阵 :math:`A - M` 进行 SVD。 .. 注意:: 该实现基于 Halko 等人 2009 年的算法 5.1。 .. 注意:: 要获得可重复的结果,请重置伪随机数生成器的种子 .. 注意:: 输入假设为低秩矩阵。 .. 注意:: 通常,对于密集矩阵,使用全秩 SVD 实现 :func:`torch.linalg.svd`,因为其性能高出 10 倍。低秩 SVD 对于 :func:`torch.linalg.svd` 无法处理的超大稀疏矩阵将非常有用。 参数:: A (Tensor): 输入张量,大小为 :math:`(*, m, n)` q (int, 可选): 对 A 的略微高估的秩。 niter (int, 可选): 进行子空间迭代的次数;niter 必须是一个非负整数,默认为 2 M (Tensor, 可选): 输入张量的均值,大小为 :math:`(*, 1, n)`。 参考文献::
优云智算