我是Keras的新手,正尝试在Keras中实现与去相关的批处理Norm论文(https://arxiv.org/abs/1804.08450),作为一种学习体验。该层与标准批处理规范非常相似,但具有一些附加组件。
我们现在不再将输入数据居中放置在每一层上并通过方差进行归一化,而是将数据居中并应用通过对协方差矩阵进行特征值分解而计算出的白化变换。
整个过程清楚地列在论文中(算法1,第5页),仅由5个方程组成,其实现方式在下面的代码中进行了标记。我成功地重新实现了标准批处理规范层,但是在合并美白程序时却出现了NaN损失和低准确性。
我想知道是否应该遵循任何建议来调试此代码。我不确定我是否犯了维数错误或对方程的实现不正确,但会有所帮助。
如果您有兴趣,请在此处找到代码(已编辑,以包括DanielMöller的更正)。图层的输入是尺寸的张量(batch_size高宽通道)。
input_shape = K.int_shape(inputs) # (batch_size height width channels)
# unroll all dimensions except feature maps dim (c X hwb)
pool_shape = (-1, input_shape[-1])
x = K.reshape(x,pool_shape)
x = K.permute_dimensions(x, (1,0)) #if you do want to invert the dimensions
mean = K.mean(x,1,keepdims=True)
# standard batch norm
#stddev = K.std(x,1,keepdims=True) + self.epsilon
#normed = (x - mean) / stddev
#normed = K.reshape(normed,((-1,)+ input_shape[1:]))
# center inputs
centered_inputs = x - mean
#vvvvvERROR SOMEWHERE IN HEREvvvvv#
# compute covariance matrix for reshaped inputs xxt
covar = K.batch_dot(K.expand_dims(x, axis=-1), K.expand_dims(x, axis=-1),axes=(2,2))
# fuzz covariance matrix to prevent singularity
covar = covar + self.epsilon
# execute eigenvalue decomposition
#Lambda, D,_ = tf.svd(covar,compute_uv=True)
Lambda, D = tf.self_adjoint_eig(covar)
Lambda = tf.linalg.diag(Lambda)
# calculate PCA-whitening matrix 1/sqrt(L) * D^T
U = K.batch_dot(1. / K.sqrt(Lambda), D, axes=(2,2))
# calculate PCA-whitened activation x_a = U(x - \mu)
x_a = K.batch_dot(U, centered_inputs,axes=(2,1))
# calculate ZCA-whitened output Dx_a
x_whitened = K.batch_dot(D, x_a)
#^^^^^ERROR SOMEWHERE IN HERE^^^^^#
# reshape whitened activations back to input dimension
x_normed = K.permute_dimensions(x_whitened,(1,0)) # permute back to (bhw X c)
x_normed = K.reshape(x_normed,((-1,), input_shape[1:])) # reroll dimensions
答案 0 :(得分:1)
假设您的代码由Keras层(自定义层或Lambda层)执行。
我发现进行调试的最好方法是创建一个只有该层的小模型才能查看其输出。
如果问题出在代码内,那么我逐渐将return
语句移到我认为错误所在的位置。
debugModel = Sequential()
debugModel.add(MyCustomLayer(...., input_shape=some_shape))
创建虚拟数据或有用数据:
data = loadOrCreateSomeData()
或使用子模型从上一层获取数据:
subModel = Model(oldModel.inputs, oldModel.get_layer(nameOfATargetLayer).outputs)
data = subModel.predict(inputData)
拥有适合测试的数据后:
result = debugModel.predict(data)
未分组的尺寸
在以下几行中,您将以整形的方式反转维度,由于维度失去意义,这通常会完全弄乱您的数据。 (您没有进行适当的移调,只是以不同的方式重新组合了数字)
pool_shape = (input_shape[-1], np.prod(input_shape[1:-1])*self.batch_size)
x = K.reshape(x,pool_shape)
我想您应该尝试以下方法:
pool_shape = (-1, input_shape[-1])
x = K.reshape(x,pool_shape)
也许这是
x = K.permute_dimensions(x, (1,0)) #if you do want to invert the dimensions