Ruby矩阵特征值分解和Numpy之间的区别

时间:2019-04-01 18:58:08

标签: ruby numpy matrix eigenvalue eigenvector

我正在尝试使用Ruby(2.5.1)矩阵类来计算奇异值分解。在构建代码时,我发现Python Numpy SVD结果与相应的Ruby Matrix方法之间存在差异。基本方法如下:

  • A:要处理的矩阵
  • X:A * AT矩阵A乘以转置的矩阵A
  • Y:AT * A矩阵A转置后与矩阵A相乘

与此:

  • U由X的特征向量的列组成
  • S是按大小排序的平方根特征值的对角矩阵
  • V由Y的行特征向量组成

以下矩阵乘积再次生成矩阵A:

  • A = U S VT

将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矩阵。因此,通用系统似乎可以正常工作。

有人知道为什么结果不同吗?

任何帮助表示赞赏

克里德

0 个答案:

没有答案