Разница между разложением собственных значений матрицы Ruby и Numpy - PullRequest
1 голос
/ 01 апреля 2019

Я пытаюсь использовать матричный класс Ruby (2.5.1) для вычисления разложения по сингулярным значениям.При создании кода я обнаружил разницу между результатами Python Numpy SVD и соответствующим подходом Ruby Matrix.Базовый подход заключается в следующем:

  • A: Матрица, подлежащая обработке
  • X: A * AT Матрица A, умноженная на матрицу A, транспонированную
  • Y: AT *Матрица А, транспонированная, умноженная на Матрицу А

с этим:

  • U состоит из столбцов собственных векторов X
  • S - диагональматрица собственных значений квадратного корня, упорядоченных по размеру
  • V, состоит из собственных векторов строки Y

Следующий матричный продукт снова производит матрицу A:

  • A = U S VT

Сравнение класса Ruby Matrix и Numpy дает те же результаты, вплоть до n от U <4. Но как только n> 4 в пределах U результаты столбцов 4 и выше начинают отличаться от результатов 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)

Matrix U

-7.40847968e-01 -1.08616810e-01 1.98359970e-01 5.12144302e-01 -3.71090574e-01

...

Собственный вектор с

2.32131207 1.47894683 0.65132674

Матрица VT

-0,50752384 -0,6681011 -0,54411439

-0,85772795 0,45183049 0,24525898

-0,08198967 -0,59117691 0,802,237373

* матрица Ригса *1055* 1056следующие результаты:

Матрица U (первый ряд)

[0,7408479676229094, -0,1086168097636038, -0,1983599695144702, -0,5690831468812522, -0,27594269683347544]

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 * 10 ** Eigenvector s

[2.3213120745694042, 1.478946829710326, 0,6513267439220222]

1068 * Матрица VT 1070 * [+0,5075238412366166, +0,6681010991839039, +0,544114392242743] 1072 * [- +0,8577279545170795, +0,4518304852203834, +0,2452589828435646] 1074 * [- +0,08198967383992087, -0,5911769057522231,0.8023637326604754]

Разница между отрицательными и положительными значениями основана на вычислении собственных значений и не влияет на общий результат.Счетчик абсолютных значений.

Когда вы смотрите на результат матрицы U кода Ruby, он начинает отличаться от кода Numpy, начиная со столбца 4 +

. Сигма и матрица Vok.

В качестве теста вы также можете запустить этот код со следующей матрицей

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.Таким образом, общая система оказалась работоспособной.

У кого-нибудь была идея, почему результаты отличаются?

Любая помощь приветствуется

Krid

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...