我正在尝试zero-center
和whiten
CIFAR10
数据集,但我得到的结果看起来像随机噪音!
Cifar10
数据集包含60,000
大小为32x32
的彩色图片。训练集包含50,000
,测试集分别包含10,000
图像
以下代码片段显示了我为使数据集变白而执行的过程:
# zero-center
mean = np.mean(data_train, axis = (0,2,3))
for i in range(data_train.shape[0]):
for j in range(data_train.shape[1]):
data_train[i,j,:,:] -= mean[j]
first_dim = data_train.shape[0] #50,000
second_dim = data_train.shape[1] * data_train.shape[2] * data_train.shape[3] # 3*32*32
shape = (first_dim, second_dim) # (50000, 3072)
# compute the covariance matrix
cov = np.dot(data_train.reshape(shape).T, data_train.reshape(shape)) / data_train.shape[0]
# compute the SVD factorization of the data covariance matrix
U,S,V = np.linalg.svd(cov)
print 'cov.shape = ',cov.shape
print U.shape, S.shape, V.shape
Xrot = np.dot(data_train.reshape(shape), U) # decorrelate the data
Xwhite = Xrot / np.sqrt(S + 1e-5)
print Xwhite.shape
data_whitened = Xwhite.reshape(-1,32,32,3)
print data_whitened.shape
输出:
cov.shape = (3072L, 3072L)
(3072L, 3072L) (3072L,) (3072L, 3072L)
(50000L, 3072L)
(50000L, 32L, 32L, 3L)
(32L, 32L, 3L)
并尝试显示生成的图像:
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.misc import imshow
print data_whitened[0].shape
fig = plt.figure()
plt.subplot(221)
plt.imshow(data_whitened[0])
plt.subplot(222)
plt.imshow(data_whitened[100])
plt.show()
顺便说一下data_train[0].shape
是(3,32,32)
,
但是如果我根据我得到的那些重塑了白化的图像
TypeError: Invalid dimensions for image data
这只是一个可视化问题吗?如果是这样我怎么能确定这种情况呢?
更新:
感谢@AndrasDeak,我以这种方式修复了可视化代码,但输出仍然是随机的:
data_whitened = Xwhite.reshape(-1,3,32,32).transpose(0,2,3,1)
print data_whitened.shape
fig = plt.figure()
plt.subplot(221)
plt.imshow(data_whitened[0])
更新2:
这是我运行下面给出的一些命令时得到的结果:
从下面可以看出,图像可以很好地显示图像,但是试图重塑它,会弄乱图像。
# output is of shape (N, 3, 32, 32)
X = X.reshape((-1,3,32,32))
# output is of shape (N, 32, 32, 3)
X = X.transpose(0,2,3,1)
# put data back into a design matrix (N, 3072)
X = X.reshape(-1, 3072)
plt.imshow(X[6].reshape(32,32,3))
plt.show()
答案 0 :(得分:12)
让我们来看看这个。正如您所指出的,CIFAR包含存储在矩阵中的图像;每个图像都是一行,每行有3072列uint8
个数字(0-255)。图像为32x32像素,像素为RGB(三通道颜色)。
# https://www.cs.toronto.edu/~kriz/cifar.html
# wget https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
# tar xf cifar-10-python.tar.gz
import numpy as np
import cPickle
with open('cifar-10-batches-py/data_batch_1') as input_file:
X = cPickle.load(input_file)
X = X['data'] # shape is (N, 3072)
事实证明,列的排序有点滑稽:所有红色像素值首先出现,然后是所有绿色像素,然后是所有蓝色像素。这使得查看图像变得棘手。这样:
import matplotlib.pyplot as plt
plt.imshow(X[6].reshape(32,32,3))
plt.show()
给出了这个:
因此,为了便于查看,让我们使用reshape
和transpose
来调整矩阵的维度:
# output is of shape (N, 3, 32, 32)
X = X.reshape((-1,3,32,32))
# output is of shape (N, 32, 32, 3)
X = X.transpose(0,2,3,1)
# put data back into a design matrix (N, 3072)
X = X.reshape(-1, 3072)
现在:
plt.imshow(X[6].reshape(32,32,3))
plt.show()
给出:
好的,ZCA美白。我们经常提醒说,在对数据进行白化之前将数据置零,这一点非常重要。此时,观察您包含的代码。据我所知,计算机视觉将色彩通道视为另一个特征维度;对于图像中的单独RGB值没有什么特别之处,就像单独的像素值没什么特别之处一样。他们只是数字功能。因此,在您计算平均像素值时,尊重颜色通道(即,您的mean
是r,g,b
值的元组),我们只计算平均值图像值。请注意,X
是一个包含N行和3072列的大矩阵。我们会将每一列视为"同一类物品"与其他每一栏一样。
# zero-centre the data (this calculates the mean separately across
# pixels and colour channels)
X = X - X.mean(axis=0)
此时,我们还要进行全局对比度标准化,这通常应用于图像数据。我将使用L2规范,这使得每个图像都具有矢量幅度1:
X = X / np.sqrt((X ** 2).sum(axis=1))[:,None]
可以轻松使用其他内容,例如标准偏差(X = X / np.std(X, axis=0)
)或最小 - 最大缩放到某个区间,如[-1,1]。
几乎就在那里。在这一点上,我们还没有对我们的数据进行过大的修改,因为我们只是对它进行了移位和缩放(线性变换)。要显示它,我们需要将图像数据恢复到范围[0,1],所以让我们使用辅助函数:
def show(i):
i = i.reshape((32,32,3))
m,M = i.min(), i.max()
plt.imshow((i - m) / (M - m))
plt.show()
show(X[6])
这里的孔雀看起来稍微亮一点,但这仅仅是因为我们已经拉伸其像素值以填补区间[0,1]:
ZCA美白:
# compute the covariance of the image data
cov = np.cov(X, 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) # zca is (N, 3072)
看一看(show(zca[6])
):
现在孔雀看起来确实不同了。您可以看到ZCA已经通过色彩空间旋转了图像,因此它看起来像旧电视上的图片,而Tone设置不正常。但仍然可以识别。
大概是因为我使用的epsilon
值,我转换后的数据的协方差并不完全相同,但它相当接近:
>>> (np.cov(zca, rowvar=True).argmax(axis=1) == np.arange(zca.shape[0])).all()
True
我不完全确定如何理清你所拥有的问题;你的麻烦似乎在于你原始数据的形状,所以我建议你在尝试转向零中心和ZCA之前先对它进行排序。
一方面,更新中四个图的第一个图表看起来不错,这表明您已经以正确的方式加载了CIFAR数据。我想,第二个图由toimage
生成,它将自动确定哪个维度具有颜色数据,这是一个很好的技巧。另一方面,之后出现的东西看起来很奇怪,所以似乎某些地方出了问题。我承认我不能完全遵循你的剧本状态,因为我怀疑你正在以交互方式工作(笔记本),当他们不工作时重试一些事情(更多关于这一点),以及您使用的代码尚未在您的问题中显示。特别是,我不确定您是如何加载CIFAR数据的;您的屏幕截图显示了某些print
语句(Reading training data...
等)的输出,然后将train_data
复制到X
并打印shape
X
1}},形状已经重新变形为(N, 3, 32, 32)
。就像我说的,更新情节1会倾向于表明重塑已经正确发生。从图3和图4可以看出,我认为你在某个地方对于矩阵尺寸的混淆,所以我不确定你是如何进行重塑和转置的。
请注意,由于以下原因,要小心重塑和转置非常重要。 X = X.reshape(...)
和X = X.transpose(...)
代码正在修改矩阵 。如果你多次这样做(比如jupyter笔记本中的意外),你会一遍又一遍地对矩阵的轴进行洗牌,并且绘制数据看起来会非常奇怪。当我们迭代重塑和转置操作时,此图像显示了进展:
这种进展不会循环,或者至少不会快速循环。由于数据中的周期性规律(如图像的32像素行结构),您倾向于在这些不正确的重塑转换图像中进行条带化。我想知道你的更新中你的四个图中的第三个是否会发生什么,这看起来比你问题的原始版本中的图像更随机。
您的更新的第四个图是孔雀的颜色底片。我不知道你是怎么得到的,但我可以用以下方式重现你的输出:
plt.imshow(255 - X[6].reshape(32,32,3))
plt.show()
给出:
如果您使用我的show
帮助程序功能,并且混淆了m
和M
,则可以解决此问题的一种方法,如下所示:
def show(i):
i = i.reshape((32,32,3))
m,M = i.min(), i.max()
plt.imshow((i - M) / (m - M)) # this will produce a negative img
plt.show()
答案 1 :(得分:2)
我遇到了同样的问题:结果投影值已关闭:
浮动图像应该是每个
的[0-1.0]值def toimage(data):
min_ = np.min(data)
max_ = np.max(data)
return (data-min_)/(max_ - min_)
注意:仅将此功能用于可视化!
但请注意如何计算“去相关”或“白化”矩阵@wildwilhelm
zca_matrix = np.dot(U, np.dot(np.diag(1.0/np.sqrt(S + epsilon)), U.T))
这是因为相关矩阵的特征向量的U矩阵实际上是这样的:SVD(X)= U,S,V但是U是X * X的EigenBase而不是X https://en.wikipedia.org/wiki/Singular-value_decomposition
作为最后一点,我宁愿只考虑统计单位的像素和RGB通道的模态而不是图像作为统计单位和像素作为模态。 我在CIFAR 10数据库上尝试了这个,它运行得非常好。
图像示例:顶部图像的RGB值为“withened”,Bottom为原始
图像示例2:没有ZCA转换在火车和损失中的表现
图像示例3:ZCA转换在火车和损失中的表现
答案 2 :(得分:0)
如果要线性缩放图像以使其均值和单位范数为零,则可以执行与Tensofrlow的tf.image.per_image_standardization
相同的图像增白。在编写完文档后,您需要使用以下公式独立地标准化每张图片:
(image - image_mean) / max(image_stddev, 1.0/sqrt(image_num_elements))
请记住,mean
和standard deviation
应该在图像中的所有值上计算。这意味着我们不需要指定沿其计算的轴/轴。
不使用Tensorflow的方法是使用numpy
,如下所示:
import math
import numpy as np
from PIL import Image
# open image
image = Image.open("your_image.jpg")
image = np.array(image)
# standardize image
mean = image.mean()
stddev = image.std()
adjusted_stddev = max(stddev, 1.0/math.sqrt(image.size))
standardized_image = (image - mean) / adjusted_stddev