keras zca_whitening - 没有错误,没有生成输出
keras zca_whitening - no error, no output generated
在使用 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)
这里有什么我遗漏的吗?
将 x_train
修改为 (3, 64, 64).
您可以使用以下代码完成此操作:x_train = x_train.transpose((2,1,0))
这主要是由于theano和tensorflow后端的切换。检查 Keras 文档中的 dim_order
。
我不同意@Avjiit 认为问题是由于形状错误造成的。这个问题很常见,因为 confirmed by the keras main contributors the problem is that the zca-calculation takes very, very long, because it uses numpy.linalg.svd()
即使在矩阵 (n*m*3) 上计算量很大,n~m~100.
有一些方法可以快速计算 svd 的近似值,例如 scikitlearn, truncated svd by irlb 的随机 svd、Lanczos 方法 svd,但它们在数值上并不总是稳定的。
我想我找到了另一种非常简单的方法,它非常快速并且给出与标准方法完全相同的结果!如果您有一个形状为 (m x n) 的数据矩阵,它会有所帮助,其中 m 远小于 n - 例如您的图像(m~1000)比像素数(n~100 x 100 x 3 = 30000 像素)少得多。在这种情况下,keras 会用 sigma.shape=(30000,30000)
计算 linalg.svd(sigma)
,这在计算上太耗费精力并且需要很长时间。但是在一个很好的近似中,不是在 (n x n) 矩阵上计算 svd,而是在 (m x m) 矩阵上计算它,只需旋转输入数据 X 或翻转 sigma
计算的顺序看起来像sigma = np.dot(flat_x, flat_x.T) / flat_x.shape[0]
。使用这种方法,计算只需要大约。 10 秒,如果 m~1000 和 n~30000。好消息是 linalg.svd(sigma)
的特征向量在两种情况下都相同,直到一个因子,请参阅 here,幻灯片 30。您可以在您的数据集或内置的 cifer 集上对此进行测试from keras.datasets import cifar10
.
可以找到数学依据 here and 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)
在使用 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)
这里有什么我遗漏的吗?
将 x_train
修改为 (3, 64, 64).
您可以使用以下代码完成此操作:x_train = x_train.transpose((2,1,0))
这主要是由于theano和tensorflow后端的切换。检查 Keras 文档中的 dim_order
。
我不同意@Avjiit 认为问题是由于形状错误造成的。这个问题很常见,因为 confirmed by the keras main contributors the problem is that the zca-calculation takes very, very long, because it uses numpy.linalg.svd()
即使在矩阵 (n*m*3) 上计算量很大,n~m~100.
有一些方法可以快速计算 svd 的近似值,例如 scikitlearn, truncated svd by irlb 的随机 svd、Lanczos 方法 svd,但它们在数值上并不总是稳定的。
我想我找到了另一种非常简单的方法,它非常快速并且给出与标准方法完全相同的结果!如果您有一个形状为 (m x n) 的数据矩阵,它会有所帮助,其中 m 远小于 n - 例如您的图像(m~1000)比像素数(n~100 x 100 x 3 = 30000 像素)少得多。在这种情况下,keras 会用 sigma.shape=(30000,30000)
计算 linalg.svd(sigma)
,这在计算上太耗费精力并且需要很长时间。但是在一个很好的近似中,不是在 (n x n) 矩阵上计算 svd,而是在 (m x m) 矩阵上计算它,只需旋转输入数据 X 或翻转 sigma
计算的顺序看起来像sigma = np.dot(flat_x, flat_x.T) / flat_x.shape[0]
。使用这种方法,计算只需要大约。 10 秒,如果 m~1000 和 n~30000。好消息是 linalg.svd(sigma)
的特征向量在两种情况下都相同,直到一个因子,请参阅 here,幻灯片 30。您可以在您的数据集或内置的 cifer 集上对此进行测试from keras.datasets import cifar10
.
可以找到数学依据 here and 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)