如何对 3D 矩阵执行 SVD 重建?

How to perform SVD reconstruction for a 3D matrix?

我了解如何对 2D 情况执行 SVD 重建,

import numpy as np
a = np.random.rand(20, 20)
u, s, vh = np.linalg.svd(a)
b = u * s @ vh
assert np.allclose(a, b)

但我不明白如何对 3D 情况进行 SVD 重建(特别是对于 (k,k,n) 矩阵,其中 n 是第三维)

ValueError                                Traceback (most recent call last)
<ipython-input-131-40a909c464ae> in <module>
      2 a = np.random.rand(20, 20, 40)
      3 u, s, vh = np.linalg.svd(a)
----> 4 b = u * s @ vh
      5 assert np.allclose(a, b)

ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 40 is different from 20)

不幸的是,文档https://numpy.org/doc/stable/reference/generated/numpy.linalg.svd.html 只有 2D 和 4D 情况的示例。我将如何在 3D 案例中执行重建?

首先,尝试一个 non-square 矩阵:

s 将两个维度中最小的作为大小(其他条目将始终为零)。我们可以对其他矩阵进行切片,删除将乘以零的部分得到这个

np
a = np.random.rand(20, 30)
u, s, vh = np.linalg.svd(a)
b = (u[:,:len(s)] * s) @ vh[:len(s),:]

多维 SVD 将使用最后两个维度简单地将 2D SVD 应用于每个矩阵。输出将具有与输入相同的 N-2 维,而另一个将与将 SVD 应用于单个矩阵时相同。所以我们可以写一个重构如下

a = np.random.rand(20, 30, 40)
u, s, vh = np.linalg.svd(a)
b = (u[...,:,:s.shape[-1]] * s[...,None,:]) @ vh[..., :s.shape[-1],:]
assert np.allclose(a, b)

(这将在 30 x 40 维的矩阵上 运行 20 个 SVD)