Получение особых значений столбцов данных NumPy в порядке - PullRequest
1 голос
/ 20 апреля 2019

Я хотел бы вычислить разложение матрицы по сингулярным значениям, и порядок значений по сингулярности важен. По умолчанию, кажется, numpy.linalg.svdscipy.linalg.svd) сортирует значения в единственном числе, поэтому я не могу сказать, какой столбец соответствует каждому значению в единственном числе.

Пример:

import numpy as np

X = np.array([[-74, 80, 18, -56, -112],
              [14, -69, 21, 52, 104],
              [66, -72, -5, 764, 1528],
              [-12, 66, -30, 4096, 8192],
              [3, 8, -7, -13276, -26552],
              [4, -12, 4, 8421, 16842]])

U, D, V = np.linalg.svd(X)
print(D)

Возвращает:

array([3.63684045e+04, 1.70701331e+02, 6.05331879e+01, 7.60190176e+00,
        1.17158094e-12])

Когда мне нужно:

array([1.70701331e+02, 6.05331879e+01, 7.60190176e+00, 3.63684045e+04, 
        1.17158094e-12])

Есть ли способ получить сингулярные значения (D), чтобы они не сортировались? Отношение X = UDV ^ T также должно быть сохранено.

Редактировать: Здесь нужен был какой-то контекст, чтобы прояснить мое недоразумение. Я пытался воспроизвести Раздел 2.3, Метод Разложения Дисперсии в этой статье .

1 Ответ

2 голосов
/ 21 апреля 2019

Когда вы говорите:

По умолчанию, по-видимому, numpy.linalg.svd (и scipy.linalg.svd) сортируют значения в единственном числе, что не позволяет мне определить, какой столбец соответствует каждому значению в единственном числе.

Я думаю, что вы делаете ошибку, в сингулярных значениях в «Разложении по сингулярным значениям» нет уникального порядка, все, что имеет значение, так это то, что порядок векторов столбцов U, D и V таков, что: U * D * V == X

Вот почему, по соглашению, они располагаются в порядке убывания, но, очевидно, вертикальные векторы унитарного базиса U и сопряженного транспонирования V также устанавливаются в таком порядке, что выполняется приведенная выше формула.

Если вы хотите получить доказательство, чтобы вычислить X обратно из U, D & V, вам нужно сделать:

from scipy import linalg

#decompose
U, D, V = np.linalg.svd(X)

# get dim of X
M,N = X.shape

# Construct sigma matrix in SVD (it simply adds null row vectors to match the dim of X 
Sig = linalg.diagsvd(D,M,N)

# Now you can get X back:
assert np.sum(np.dot(U, np.dot(Sig, V)) - X) < 0.00001
...