keras zca_whitening - 没有错误,没有生成输出

时间:2016-11-22 07:07:03

标签: python python-2.7 image-processing keras

使用zca_whitening时,我的代码卡在某处,既不显示任何错误也不显示输出。当我跳过zca_whitening并应用其他转换时,代码运行完美。我在这里附上代码片段。如果我在这里做错了,我会帮助我:

datagen = ImageDataGenerator(zca_whitening=True)
datagen.fit(x_train)

其中>> x_train是一组训练图像(dim = 50 x 64 x 64 x 3)。运行datagen.fit后,代码显示没有进一步的输出或错误,似乎让进程运行了无限时间。

另一方面,这些转换完美地运作:

datagen = ImageDataGenerator(rotation_range=0.90,
    width_shift_range=0.2,
    height_shift_range=0.2,
    fill_mode='nearest',
    horizontal_flip=True,
    vertical_flip=True)
datagen.fit(x_train)

这里有什么我想念的吗?

2 个答案:

答案 0 :(得分:1)

修改x_train以使其具有形状(3, 64, 64).

您可以使用以下代码执行此操作:x_train = x_train.transpose((2,1,0))

这主要是由于theano和tensorflow后端之间的切换。在Keras文档中查看dim_order

答案 1 :(得分:0)

我不同意@Avjiit的问题是由于形状错误。这个问题很常见,并且由keras主要贡献者confirmed提出,问题是zca计算需要非常非常长的时间,因为z uses numpy.linalg.svd()即使在矩阵上也很繁琐( n * m * 3),n〜m〜100。

有一些方法可以计算svd的快速近似值,例如scikitlearn的随机svd,irlb的截断svd,Lanczos方法svd,但是它们并不总是数值稳定的。

我认为我发现了另一种非常简单的方法,该方法非常快捷,并且得到与标准方法完全相同的结果!如果您有一个形状为(m x n)的数据矩阵,其中m比n小得多-例如,您的图像(m〜1000)少于像素数(n〜100 x 100 x 3 = 30000像素)。在这种情况下,keras将使用linalg.svd(sigma)来计算sigma.shape=(30000,30000),这在计算上太费力了,而且要花很长时间。但是可以很好地近似,而不是在(nxn)矩阵上计算svd,您可以在(mxm)矩阵上进行计算,只需旋转输入数据X或翻转sigma计算的顺序即可sigma = np.dot(flat_x, flat_x.T) / flat_x.shape[0]。使用这种方法,计算仅需约。如果m〜1000和n〜30000,则为10秒。好消息是,linalg.svd(sigma)的特征向量在两种情况下都是相同的,但不超过一个因子,请参见here,幻灯片30。您可以在自己的数据集或内置的cifer集上进行测试与from keras.datasets import cifar10

可以找到herehere的数学依据。为了直观起见,我分享了这些图片:

enter image description here enter image description here

以下是用于创建zca计算的修改后的keras代码。您可以使用它来修改位于here的keras zca代码。我所做的修改是在需要时放置if子句以转置数据矩阵:

from keras.datasets import cifar10
import numpy as np
from scipy import linalg

(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X = X_train[:1000]
flat_x = np.reshape(x, (x.shape[0], x.shape[1] * x.shape[2] * x.shape[3]))

# normalize x:
flat_x = flat_x / 255.
flat_x = flat_x - flat_x.mean(axis=0)

# CHANGES HAPPEN BELOW.
# if m>n execute the svd as usual
if flat_x.shape[0] => flat_x.shape[1]:
    sigma = np.dot(flat_x.T, flat_x) / flat_x.shape[0]
    u, s, _ = linalg.svd(sigma)
# and if m<n do the trnaspose trick
if flat_x.shape[0] < flat_x.shape[1]:
    sigma = np.dot(flat_x, flat_x.T) / flat_x.shape[0]
    u, s, _ = linalg.svd(sigma)
    u = np.dot(flat_x.T, u) / np.sqrt(s*flat_x.shape[0])

s_inv = 1. / np.sqrt(s[np.newaxis] + 0.1) # the 0.1 is the epsilon value for zca
principal_components = (u * s_inv).dot(u.T)
whitex = np.dot(flat_x, principal_components)