Получение отрицательного значения S от разложения SVD в Numpy? - PullRequest
4 голосов
/ 13 марта 2019

Я хочу отбелить набор данных CIFAR10 с помощью ZCA.Вход X_train имеет форму (40000, 32, 32, 3), где 40000 - это количество изображений, а 32x32x3 - размер каждого изображения.Для этой цели я использую код из этого ответа :

X_flat = np.reshape(X_train, (-1, 32*32*3))
# compute the covariance of the image data
cov = np.cov(X_flat, rowvar=True)   # cov is (N, N)
# singular value decomposition
U,S,V = np.linalg.svd(cov)     # U is (N, N), S is (N,)
# build the ZCA matrix
epsilon = 1e-5
zca_matrix = np.dot(U, np.dot(np.diag(1.0/np.sqrt(S + epsilon)), U.T))
# transform the image data       zca_matrix is (N,N)
zca = np.dot(zca_matrix, X_flat)    # zca is (N, 3072)

Однако во время выполнения я обнаружил следующее предупреждение:

D:\toolkits.win\anaconda3-5.2.0\envs\dlwin36\lib\site- packages\ipykernel_launcher.py:8: RuntimeWarning: invalid value encountered in sqrt

Итак, послеЯ получил вывод SVD, я попытался:

print(np.min(S)) # prints -1.7798217

Что неожиданно, потому что S может иметь только положительные значения.Кроме того, результат отбеливания ZCA был неверным, и он содержал значения nan.

Я попытался воспроизвести это, повторно запустив этот же код во второй раз, и на этот раз я не встретил никаких предупреждений или каких-либо отрицательных S значений, но вместо этого я получил:

print(np.min(S)) # prints nan

Есть идеи, почему это могло произойти?


Обновление: Перезапустил ядро ​​для освобожденияресурсы процессора и оперативной памяти, и попытался снова запустить этот кодСнова получено то же предупреждение для кормления в отрицательных значениях до np.sqrt().Не уверен, поможет ли это, но я также приложил данные об использовании процессора и оперативной памяти:

показатели монитора активности

1 Ответ

2 голосов
/ 13 марта 2019

Вот пара идей.У меня нет вашего набора данных, поэтому я не могу быть полностью уверен, что это решит вашу проблему, но я достаточно уверен, чтобы опубликовать это как ответ, а не комментарий.

Сначала.Ваш X_train равен 40'000 на 3072, где каждая строка является вектором данных, а каждый столбец является переменной или функцией.Вы хотите, чтобы ковариационная матрица была 3072 к 3072: передать от rowvar=False до np.cov.

Я не совсем уверен, почему SVD ковариационной матрицы 40'000 на 40'000 расходится.Предполагая, что у вас достаточно ОЗУ для хранения ковариационной матрицы 12 ГБ, я могу думать только о переполнении чисел, потому что, возможно, вы не удаляете среднее значение данных, как это ожидается ZCA (и любой другой техникой отбеливания)?

Итак, второй.Удалите среднее значение: X_zeromean = X_flat - np.mean(X_flat, 0).

Если вы сделаете это, то последний шаг должен быть изменен чуть-чуть (чтобы выровнять размеры).Вот быстрая проверка с использованием единообразных случайных данных:

import numpy as np
X_flat = np.random.rand(40000, 32*32*3)
X_zeromean = X_flat - np.mean(X_flat, 0)
cov = np.cov(X_zeromean, rowvar=False)
U,S,V = np.linalg.svd(cov)
epsilon = 1e-5
zca_matrix = np.dot(U, np.dot(np.diag(1.0/np.sqrt(S + epsilon)), U.T))
zca = np.dot(zca_matrix, X_zeromean.T) # <-- transpose needed here

В качестве проверки работоспособности np.cov(zca) теперь очень близка к единичной матрице, по желанию (zca будет иметь перевернутые измерения в качестве входных данных).

(Как примечание, это действительно дорогой и численно нестабильный способ отбеливания массива данных: вам не нужно вычислять ковариацию, а затем брать SVD - вы выполняете вдвое больше работы.возьмите тощий SVD самой матрицы данных (np.linalg.svd с флагом full_matrices=False) и вычислите матрицу отбеливания непосредственно оттуда, даже не оценив дорогой внешний продукт для ковариационной матрицы.)

...