如何使用奇异值分解反转 numpy 矩阵?
How to invert numpy matrices using Singular Value Decomposition?
(在你告诉我之前,是的,我知道你应该 永远不要 反转矩阵。不幸的是,对于我的计算,我有一个我构建的矩阵,它必须是以某种方式颠倒了。)
我有一个很大的矩阵 M
,它是病态的。 numpy.linalg.cond(M)
输出大小为 e+22
的值。矩阵 M
的形状为 (1000,1000)
。
当然,numpy.linalg.inv()
会导致很多精度错误。所以,我使用 numpy.linalg.solve()
来反转矩阵。
考虑矩阵逆 A^{-1}
由 A * A^{-1} = Identity
定义。
numpy.linalg.solve()
计算确定的(即满秩)线性矩阵方程 ax = b 的“精确”解 x。
所以,我定义单位矩阵:
import numpy as np
iddmatrix = np.identity(100)
并求解:
inverse = np.linalg.solve(M, iddmatrix)
但是,因为我的矩阵 so 大而 so 病态,np.linalg.solve()
不会给出 "exact solution"。我需要另一种方法来反转矩阵。
- 用 SVD 实现这种逆的标准方法是什么?
- 我怎样才能使这个病态矩阵....定义明确?
如有任何建议,我们将不胜感激。谢谢!
由于 SVD 将矩阵 A 分解为 U*S*V,其中 S是对角线,U,V是正交的,它的逆是V'*inv(S)*U',对角矩阵的逆就是主对角线上数字的逆。
>>> A=np.random.rand(1000,1000)
>>> u,s,v=np.linalg.svd(A)
>>> Ainv=np.dot(v.transpose(),np.dot(np.diag(s**-1),u.transpose()))
考虑一下矩阵的 SVD 实际意味着什么。这意味着对于某些矩阵M
,那么我们可以将其表示为M=UDV*
(这里让*代表转置,因为我在堆栈溢出中没有看到这样做的好方法)。
if M=UDV*:
then: M^-1 = (UDV*)^-1 = (V*^-1)(D^-1)(U^-1)
但由于 U
的列是 MM*
的特征值,而 V
的列是 M\*M
的特征值,因此这些矩阵是它们自己的转置(因为特征向量是正交的)。所以我们得到:M^-1 = V(D^-1)U*
。取对角矩阵的逆矩阵就像取这些元素的乘法逆矩阵一样简单。
更好的排版(有点)在这里:http://adrianboeing.blogspot.com/2010/05/inverting-matrix-svd-singular-value.html
点积的第一个参数应该是v.transpose()
:
import numpy as np
from numpy.linalg import inv
def svdsolve(A):
u, s, v = np.linalg.svd(A)
Ainv = np.dot(v.transpose(), np.dot(np.diag(s**-1), u.transpose()))
return Ainv
temp = np.random.rand(1000, 1000)
np.allclose(svdsolve(temp), inv(temp))
>>> True
np.linalg.solve
将初始矩阵分解为 A = USV,因此逆矩阵只是 V' S-1 U'
(在你告诉我之前,是的,我知道你应该 永远不要 反转矩阵。不幸的是,对于我的计算,我有一个我构建的矩阵,它必须是以某种方式颠倒了。)
我有一个很大的矩阵 M
,它是病态的。 numpy.linalg.cond(M)
输出大小为 e+22
的值。矩阵 M
的形状为 (1000,1000)
。
当然,numpy.linalg.inv()
会导致很多精度错误。所以,我使用 numpy.linalg.solve()
来反转矩阵。
考虑矩阵逆 A^{-1}
由 A * A^{-1} = Identity
定义。
numpy.linalg.solve()
计算确定的(即满秩)线性矩阵方程 ax = b 的“精确”解 x。
所以,我定义单位矩阵:
import numpy as np
iddmatrix = np.identity(100)
并求解:
inverse = np.linalg.solve(M, iddmatrix)
但是,因为我的矩阵 so 大而 so 病态,np.linalg.solve()
不会给出 "exact solution"。我需要另一种方法来反转矩阵。
- 用 SVD 实现这种逆的标准方法是什么?
- 我怎样才能使这个病态矩阵....定义明确?
如有任何建议,我们将不胜感激。谢谢!
由于 SVD 将矩阵 A 分解为 U*S*V,其中 S是对角线,U,V是正交的,它的逆是V'*inv(S)*U',对角矩阵的逆就是主对角线上数字的逆。
>>> A=np.random.rand(1000,1000)
>>> u,s,v=np.linalg.svd(A)
>>> Ainv=np.dot(v.transpose(),np.dot(np.diag(s**-1),u.transpose()))
考虑一下矩阵的 SVD 实际意味着什么。这意味着对于某些矩阵M
,那么我们可以将其表示为M=UDV*
(这里让*代表转置,因为我在堆栈溢出中没有看到这样做的好方法)。
if M=UDV*:
then: M^-1 = (UDV*)^-1 = (V*^-1)(D^-1)(U^-1)
但由于 U
的列是 MM*
的特征值,而 V
的列是 M\*M
的特征值,因此这些矩阵是它们自己的转置(因为特征向量是正交的)。所以我们得到:M^-1 = V(D^-1)U*
。取对角矩阵的逆矩阵就像取这些元素的乘法逆矩阵一样简单。
更好的排版(有点)在这里:http://adrianboeing.blogspot.com/2010/05/inverting-matrix-svd-singular-value.html
点积的第一个参数应该是v.transpose()
:
import numpy as np
from numpy.linalg import inv
def svdsolve(A):
u, s, v = np.linalg.svd(A)
Ainv = np.dot(v.transpose(), np.dot(np.diag(s**-1), u.transpose()))
return Ainv
temp = np.random.rand(1000, 1000)
np.allclose(svdsolve(temp), inv(temp))
>>> True
np.linalg.solve
将初始矩阵分解为 A = USV,因此逆矩阵只是 V' S-1 U'