我正在尝试使用Ruby(2.5.1)矩阵类来计算奇异值分解。在构建代码时,我发现Python Numpy SVD结果与相应的Ruby Matrix方法之间存在差异。基本方法如下:
与此:
以下矩阵乘积再次生成矩阵A:
将Ruby Matrix类和Numpy进行比较,得出n等于U <4的结果相同。但是,一旦U中的n> 4,第4列和up的结果就会与Numpy结果有所不同。我现在想知道我是在这里做错什么,还是一般的Matrix类有问题。
对于Numpy,我使用了以下代码
# Calculate and reconstruct SVD
from numpy import array
from numpy import diag
from numpy import dot
from numpy import zeros
from scipy.linalg import svd
# define a matrix
A = array([[1,1,1], [0,1,1], [1,0,0], [0,1,0], [1,0,0]])
print(A)
# Singular-value decomposition
U, s, VT = svd(A)
print('Matrix U')
print(U)
print('Eigenvektor')
print(s)
print('Matrix VT')
print(VT)
# create m x n Sigma matrix
Sigma = zeros((A.shape[0], A.shape[1]))
# populate Sigma with n x n diagonal matrix
Sigma[:A.shape[1], :A.shape[1]] = diag(s)
# reconstruct matrix
B = U.dot(Sigma.dot(VT))
print(B)
对于Ruby计算,我使用了以下代码:
require 'matrix'
a = Matrix[ [1,1,1], [0,1,1], [1,0,0], [0,1,0], [1,0,0]]
x = a * a.transpose
y = a.transpose * a
u = Matrix::EigenvalueDecomposition.new(x)
u_ev = u.eigenvector_matrix().to_a
v = Matrix::EigenvalueDecomposition.new(y)
v_ev = v.eigenvector_matrix().transpose.to_a
u_ev.map! {|row| row.reverse}
v_ev.reverse!
puts 'Matrix U'
u = Matrix[*u_ev]
puts u.to_a.map(&:inspect)
puts 'Matrix V'
vt = Matrix[*v_ev]
puts vt.to_a.map(&:inspect)
puts 'Eigenvalues S'
p sqrt_diagonal_values = v.eigenvalues().map {|value| Math.sqrt(value)}.reverse
Numpy代码的结果是(U的第一行的示例)
矩阵U
-7.40847968e-01 -1.08616810e-01 1.98359970e-01 5.12144302e-01 -3.71090574e-01
...
特征向量s
2.32131207 1.47894683 0.65132674
Matrix VT
-0.50752384 -0.6681011 -0.54411439
-0.85772795 0.45183049 0.24525898
-0.08198967 -0.59117691 0.80236373
Ruby Matrix Eigensystem代码产生以下结果:
矩阵U(第一行)
[0.7408479676229094,-0.1086168097636038,-0.1983599695144702,-0.5690831468812522,-0.27594269683347544]
...
特征向量s
[2.3213120745694042、1.478946829710326、0.6513267439220222]
Matrix VT
[0.5075238412366166,0.6681010991839039,0.544114392242743]
[-0.8577279545170795,0.4518304852203834,0.2452589828435646]
[-0.08198967383992087,-0.5911769057522231,0.8023637326604754]
正负值之间的差异是基于特征值的计算,并不影响整体结果。绝对值计数。
当您查看Ruby代码的Matrix U的结果时,它开始与从第4+列开始的Numpy代码有所不同
Sigma和V矩阵都可以。
作为测试,您也可以使用以下矩阵运行此代码
A = array([[4,-5,-1],[7,-2,3],[-1,4,-3],[8,2,6]]) #for Python
a = Matrix[[4,-5,-1],[7,-2,3],[-1,4,-3],[8,2,6]] #for Ruby
在这种情况下,两个结果都相同。当您检查A = USVT时,结果将再次生成原始的A矩阵。因此,通用系统似乎可以正常工作。
有人知道为什么结果不同吗?
任何帮助表示赞赏
克里德