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

标签 python numpy linear-algebra svd

我想使用 ZCA 对 CIFAR10 数据集进行白化处理。输入 X_train 的形状为 (40000, 32, 32, 3),其中 40000 是图像的数量,32x32x3 是每个图像的大小。我正在使用 this answer 中的代码为此目的:

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 利用率数据:

activity monitor figures

最佳答案

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

首先。您的 X_train 是 40'000 x 3072,其中每个 是一个数据向量,每个 是一个变量或特征。您需要 3072 x 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(np.linalg.svd 带有 full_matrices=False 标志)并直接从那里计算白化矩阵,而无需评估昂贵的外积为协方差矩阵。)

关于python - 从 Numpy 的 SVD 分解中获得负 S 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55131665/

相关文章:

python - 根据列排列/排序 Pandas 数据框数据中的数据

numpy - 优化 Python KD 树搜索

algorithm - 如何在 d 维球/球体内生成均匀的随机点?

matlab - 病态线性系统

python - django 如何获取 manytomany 字段的计数

arrays - Pandas:从 numpy 数组中填充数据框列的缺失值

python - 如何根据公差更改cv::Mat值

c++ - 四元数是非常相似旋转的翻转符号吗?

python - 使用 django-filter 记住 django-tables2 中的 URL 参数

python - 输出 stdin 的每第 n 个字节