从Numpy中的SVD分解中获得负S值



我想使用ZCA使用CIFAR10数据集。输入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.winanaconda3-5.2.0envsdlwin36libsite- packagesipykernel_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

对为什么会发生这种情况有什么想法?


更新:重新启动内核以释放CPU和RAM资源,并尝试再次运行此代码。再次有同样的警告,以供应np.sqrt()的负值。不确定是否有帮助,但我还附加了CPU和RAM利用数字:

活动监视器数字

这里有几个想法。我没有您的数据集,所以我不能完全确定这些可以解决您的问题,但是我有足够的信心将其作为答案而不是评论。

首先。您的X_train为40'000 x 3072,其中每个 row 是一个数据向量,每个都是变量或功能。您需要3072乘3072的协方差矩阵:通过rowvar=False传递至np.cov

我不太确定为什么40'000 x 40'000协方差矩阵的SVD有所不同。假设您有足够的RAM来存储12 GB协方差矩阵,那么我能想到的一件事是数值溢出,因为您可能不会像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(带有full_matrices=False标志的np.linalg.svd)并直接从那里计算美白矩阵,而无需评估协方差矩阵的昂贵外部产品。)

相关内容

  • 没有找到相关文章

最新更新