Python 在Numpy中从SVD分解得到负S值?

Python 在Numpy中从SVD分解得到负S值?,python,numpy,linear-algebra,svd,Python,Numpy,Linear Algebra,Svd,我想使用ZCA使CIFAR10数据集变白。输入的X_列为形状(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 decomp

我想使用ZCA使CIFAR10数据集变白。输入的
X_列
为形状(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
你知道为什么会发生这种事吗


更新:重新启动内核以释放cpu和RAM资源,并再次尝试运行此代码。在
np.sqrt()。不确定是否有帮助,但我还附上了cpu和ram利用率数据:


以下是一些想法。我没有你的数据集,所以我不能完全肯定这些会解决你的问题,但我有足够的信心将其作为一个答案而不是评论发布

首先。您的
X_列
是40'000乘3072,其中每行是一个数据向量,每列是一个变量或特征。您需要3072乘3072的协方差矩阵:传入
rowvar=False
np.cov

我真的不知道为什么四万乘四万协方差矩阵的奇异值分解会发散。假设您有足够的RAM来存储12GB的协方差矩阵,我能想到的一件事是数字溢出,因为您可能没有像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
将numpy导入为np
X_flat=np.rand.rand(40000,32*32*3)
X_零均值=X_平坦-np.均值(X_平坦,0)
cov=np.cov(X_零均值,rowvar=False)
U、 S,V=np.linalg.svd(cov)
ε=1e-5
zca_矩阵=np.dot(U,np.dot(np.diag(1.0/np.sqrt(S+epsilon)),U.T))

zca=np.dot(zca_矩阵,X_zeromean.T)#
X列车的
dtype
是什么?它是浮动的吗?或者
int
X\u列车
float32
X_flat
也是
float32
cov
float64
。抓得好!我猜中的代码不正确。代码的最后一行不是应该是
zca=np.dot(X_zeromean,zca\u matrix)
吗?
S
的负值仍然很奇怪。零意义不会改变np.cov的输出,因此我怀疑它与此有关。我有64GB的内存,所以也不会是这样。Numpy至少应该对可能发生的事情提出一些其他警告。是的,这不太可能,但零意义(以及标准化为单位方差?)可能会有所帮助:40e3*32*32*3*128是1.5e10,此时
float32
被推得很远:
np.spating(np.float32(1.5e10))
是1024。可以想象,外部产品的样品会被推到这些水平。在计算
cov
之前,您可以尝试将整个数据数组强制转换为float64。但理想的情况是计算瘦SVD,并由此计算协方差矩阵。