实现各种低秩矩阵的线性代数算法。
全部 = [
"SVD 低秩", "pca_lowrank"]
from 打字
导入
可选
导入
火炬
from 火炬
导入 _linalg_utils as _utils,
张量
from torch.overrides 导入 handle_torch_function, has_torch_function
定义
获取近似基(
A: 张量,
q: int,
奈特:
可选[int] = 2,
M: 可选[
张量] =
无,
) -> 张量:
返回张量 :math:`Q`,其 :math:`q` 个列正交,使得
math:`Q Q^H A` 近似于 :math:`A`。如果指定了 :math:`M`,则 :math:`Q` 满足
math:`Q Q^H (A - M)`
不实例化任何张量,近似 :math:`A - M`
的大小为 :math:`A` 或 :math:`M`
.. note:: 实现基于 Halko 等人 2009 年的算法 4.4
Halko 等人,2009 年。
.. 注意:: 对于一个 k-rank 矩阵的充分近似
math:`A`,其中 k 事先未知但可以
估计,Q 列的数量 q 可以
依据以下标准选择:一般来说,
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
.. 注意:: 为了获得可重复的结果,请重置伪随机数生成器的种子
伪随机数生成器
Args::
A (Tensor):输入张量,大小为 :math:`(*, m, n)`
q(整数):由 :math:`Q` 张成的子空间的维度
列。
niter(整数,可选):要进行的子空间迭代次数;
``niter`` 必须是一个
非负整数。在大多数情况下,默认值 2 已经足够。
默认值 2 已经足够。
M (Tensor,可选):输入张量的均值,大小为
math:`(*, m, n)`。
参考文献:
- Nathan Halko, Per-Gunnar Martinsson 和 Joel Tropp, 寻找结构中的随机性:用于构建近似矩阵分解的概率算法,
结构与随机性:构建近似矩阵分解的概率算法,
结构与随机性:构建近似矩阵分解的概率算法,
arXiv:0909.4061 [math.NA; math.PR], 2009(可在)
`arXiv `_)
"""
迭代次数 = 2
如果
迭代次数
是
无
否则
液滴
dtype = _utils.获取浮点数据类型(A)
如果
不 A.
是复杂的()
否则 A.dtype
矩阵乘法 = _utils.
矩阵乘法
R = 火炬.randn(A.
形状[-1
] q,
数据类型=
数据类型,
设备=A.
设备)
# 使用 torch.geqrf + torch.ormqr 可以使以下代码运行更快
# 但 geqrf 不可微分
X = 矩阵乘法(A, R)
如果 M
是
不
无:
X = X - 矩阵乘法(M, R)
Q = 火炬.
线性代数.
二维码(X).Q
对于 _
在
范围(
奈特):
X = 矩阵乘法(A.mH, Q)
如果 M
是
不
无:
X = X - 矩阵乘法(M.mH, Q)
Q = 火炬.
线性代数.
二维码(X).Q
X = 矩阵乘法(A, Q)
如果 M
是
不
无:
X = X - 矩阵乘法(M, Q)
Q = 火炬.
线性代数.
二维码(X).Q
返回 Q
[文档]
定义 svd_lowrank(
A: 张量,
q: 可选[int] = 6,
奈特:
可选[int] = 2,
M: 可选[
张量] =
无,
) -> 元组[
张量,
张量,
张量
]
r返回矩阵的奇异值分解(U, S, V),
或者稀疏矩阵 :math:`A` 的批次,或者
\(A \approx U \operatorname{diag}(S) V^{\text{H}}\)。如果给出 \(:math:`M`\),则对矩阵 \(:math:`A - M`\)
计算矩阵 \(:math:`A - M`\)
.. note:: 实现基于 Halko 等人 2009 年的算法 5.1
Halko 等人,2009 年。
.. 注意:: 对于一个 k-rank 矩阵的充分近似
math:`A`,其中 k 事先未知但可以
估计,Q 列的数量 q 可以
依据以下标准选择:一般来说,
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
对于低秩的大矩阵,取 :math:`q = k + 5..10`。如果 k 相对于 :math:`min(m, n)` 较小,选择 :math:`q = k + 0..2` 可能就足够了。
.. 注意:: 这是一个随机化方法。为了获得可重复的结果,请
设置伪随机数生成器的种子
.. 注意:: 通常情况下,对于密集矩阵,请使用全秩奇异值分解实现
func:`torch.linalg.svd`,因为它在密集矩阵上的效率是 10 倍
具有更高的性能特性。低秩奇异值分解
对于无法处理的巨大稀疏矩阵将很有用。
func:`torch.linalg.svd` 无法处理。
参数:
一个(张量):大小为 :math:`(*, m, n)` 的输入张量
q(整数,可选):A 的略微高估的秩。
niter(整数,可选):进行子空间迭代的次数;niter 必须是非负数
进行;niter 必须是非负数
整数,默认值为 2
M(张量,可选):输入张量的均值,大小为
math:`(*, m, n)`,将被广播到该函数中 A 的大小
的尺寸。
参考文献:
- Nathan Halko, Per-Gunnar Martinsson, 和 Joel Tropp, 寻找结构的方法:随机概率算法在
随机化结构:概率算法在
构建近似矩阵分解
arXiv:0909.4061 [数学.NA; 数学.PR], 2009(可在
arXiv(https://arxiv.org/abs/0909.4061)
"""
如果
不
火炬.
算子.
是否正在脚本化():
张量操作 = (A, M)
如果
不
设置(
地图(
类型,
张量操作)).
是否是子集(
(火炬.
张量,
类型(
无))
) 和
有 torch 功能(
张量操作):
返回 handle_torch_function(
低秩奇异值分解,
张量操作, A, q=q,
奈特=
奈特, M=M
)
返回 _svd_lowrank(A, q=q,
奈特=
奈特, M=M)
定义 _svd_lowrank(
A: 张量,
q: 可选[int] = 6,
奈特:
可选[int] = 2,
M: 可选[
张量] =
无,
) -> 元组[
张量,
张量,
张量
]
# 算法 5.1 见 Halko 等人,2009 年
q = 6 如果 q
是
无
否则 q
m, n = A.形状[-2
]
矩阵乘法 = _utils.
矩阵乘法
如果 M
是
不
无:
M = M.广播到(A.
尺寸())
假设 A 是高矩阵
如果 m < n:
A = A.mH
如果 M
是
不
无:
M = M.mH
Q = 获取近似基(A, q,
奈特=
奈特, M=M)
B = 矩阵乘法(Q.mH, A)
如果 M
是
不
无:
B = B - 矩阵乘法(Q.mH, M)
U, S, Vh = 火炬.
线性代数.svd(B, full_matrices=False)
V = Vh.mH
U = Q.矩阵乘法(U)
如果 m < n:
U, V = V, U
返回 U, S, V
[文档]
定义
pca 低秩(
A: 张量,
q: 可选[int] =
无,
中心:
布尔值 = True,
奈特:
整型 = 2,
) -> 元组[
张量,
张量,
张量
]
r对低秩矩阵、矩阵批或稀疏矩阵执行线性主成分分析(PCA)
此函数返回一个 namedtuple(U,S,V),它是奇异值分解的近似最优解
该函数返回一个 namedtuple(U,S,V),它是奇异值分解的近似最优解
该函数返回一个 namedtuple(U,S,V),它是奇异值分解的近似最优解
以矩阵 :math:`A` 为中心的矩阵,满足 :math:`A ≈ U \operatorname{diag}(S) V^{\text{H}}`
.. note:: `(U, S, V)` 与 PCA 的关系如下:
- :math:`A` 是一个包含 `m` 个样本的数据矩阵,
``n`` 个特征
- 主成分方向由 :math:`V` 列表示
- :math:`S ** 2 / (m - 1)` 包含特征值
math:`A^T A / (m - 1)` 是协方差
``A`` 当提供 ``center=True`` 时。
`- ``matmul(A, V[:, :k])`` 将数据投影到前 k 个`
`主成分`
`.. note:: 与标准 SVD 不同,返回的矩阵大小取决于指定的秩和 q`
`.. note:: 与标准 SVD 不同,返回的矩阵大小取决于指定的秩和 q`
以下为值:
- :math:`U` 是 m x q 矩阵
- :math:`S` 是 q 维向量
- :math:`V` 是 n x q 矩阵
.. 注意:: 为了获得可重复的结果,请重置伪随机数生成器的种子
伪随机数生成器
参数:
A(张量):大小为 :math:`(*, m, n)` 的输入张量
q(int,可选):略微高估的秩
`A`。默认情况下,`q = min(6, m,`
`n)`。
center (bool, 可选): 如果为 True,则居中输入张量,
否则,假设输入是
居中。
niter(int,可选):子空间迭代的次数;
进行;niter 必须是非负整数,默认为 2。
默认为 2。
参考文献:
- Nathan Halko, Per-Gunnar Martinsson 和 Joel Tropp, 寻找结构中的随机性:用于构建近似矩阵分解的概率算法,
结构与随机性:构建近似矩阵分解的概率算法,
结构与随机性:构建近似矩阵分解的概率算法,
arXiv:0909.4061 [math.NA; math.PR], 2009(可在)
`arXiv `_)
"""
如果
不
火炬.
算子.
是否正在脚本化():
如果
类型(A)
是
不
火炬.
张量
和
有 torch 功能((A,)):
返回 handle_torch_function(
pca 低秩, (A,), A, q=q,
中心=
中心,
奈特=
迭代次数
)
(m, n) = A.形状[-2
]
如果 q
是
无:
q = 最小值(6, m, n)
elif 不 (q
≥ 0
和 q <=
最小值(m, n)):
抛出
值错误(
f"q(="{q}
必须是非负整数且不大于 min(m, n)={
最小值(m, n)}"
)
如果
不 (niter
≥ 0):
抛出
值错误(f"niter(={
奈特}
必须是非负整数)
dtype = _utils.获取浮点数据类型(A)
如果
不
中心:
返回 _svd_lowrank(A, q,
奈特=
奈特, M=
无)
如果 _utils.is_sparse(A):
如果
长度(A.
形状) != 2:
抛出
值错误(
主成分分析(PCA)低秩输入应为一个二维张量)
c = 火炬.
稀疏.
总和(A,
维度=(-2,)) / m
# 重新塑形 c
列索引 = c.
索引()[0]
索引 =
火炬.
零值(
2,
长度(
列索引),
数据类型=
列索引.
数据类型,
设备=
列索引.
设备,
)
索引[0] =
列索引
C_t = 火炬.
稀疏 Coo 张量(
索引, c.
值(), (n, 1),
数据类型=
数据类型,
设备=A.
设备
)
ones_m1_t = 火炬.
一(A.
形状
[-2] + (1, m),
数据类型=
数据类型,
设备=A.
设备)
M = 火炬.
稀疏.mm(
C_τ,
ones_m1_τ).mT
返回
_svd_低秩(A, q,
奈特=
奈特, M=M)
否则:
C = A.均值(
维度=(-2,),
保持维度=True)
返回 _svd_lowrank(A - C, q,
奈特=
奈特, M=
无)