Как я могу восстановить исходную матрицу из компонентов SVD со следующими формами?

#numpy #scipy #numpy-ndarray #svd

Вопрос:

Я пытаюсь восстановить следующую матрицу формы (256 x 256 x 2) с компонентами SVD в виде

 U.shape = (256, 256, 256)
s.shape = (256, 2)
vh.shape = (256, 2, 2)
 

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

Ответ №1:

Из документации np.linalg.svd:

«… Если a имеет более двух измерений, то применяются правила вещания, как описано в :ссылка: routines.linalg-broadcasting . Это означает, что SVD работает в режиме «сложения»: он повторяет все индексы первых a.ndim - 2 измерений, и для каждой комбинации SVD применяется к двум последним индексам».

Это означает, что вам нужно только обработать s матрицу (или тензор в общем случае), чтобы получить правильный тензор. Точнее, то, что вам нужно сделать, — это заполнить s соответствующим образом, а затем взять только первые 2 столбца (или, как правило, количество строк, из vh которых должно быть равно количеству возвращаемых столбцов s ).

Вот рабочий код с примером для вашего случая:

 import numpy as np
mat = np.random.randn(256, 256, 2) # Your matrix of dim 256 x 256 x2
u, s, vh = np.linalg.svd(mat) # Get the decomposition
# Pad the singular values' arrays, obtain diagonal matrix and take only first 2 columns:
s_rep = np.apply_along_axis(lambda _s: np.diag(np.pad(_s, (0, u.shape[1]-_s.shape[0])))[:, :_s.shape[0]], 1, s)
mat_reconstructed = u @ s_rep @ vh
 

mat_reconstructed равно mat погрешности до точности.

Комментарии:

1. Спасибо, сэр, это было действительно полезно и сработало, как и ожидалось.

2. С удовольствием! 🙂

3. Привет, моя оригинальная матрица 30*2*50 и я получаю ошибку. Какой код я должен изменить?

4. @Agile_Eagle Эй, самый простой способ использовать этот код-применить mat.transpose((0,2,1)) его так, чтобы размер 2 был меньше или равен размеру 1. Код должен работать хорошо, чтобы вам нужно было только применить mat_reconstructed.transpose((0,2,1)) его еще раз, чтобы соответствующим образом расположить размеры.