KERAS:零分区错误



我正在尝试在基线自动编码器中使用KERAS构建的每个层的激活值,因为我想基于Kullbach-Leibler(KL(差异,如下所示,PAG。14.

在这种情况下,我将计算每一层的KL差异,然后将它们全部与主要损耗函数相加,例如 MSE

因此,我在jupyter中制作了一个脚本,但是当我尝试编译时,我会始终获得ZeroDivisionError: integer division or modulo by zero。这是代码

import numpy as np
from keras.layers import Conv2D, Activation 
from keras.models import Sequential 
from keras import backend as K
from keras import losses
x_train = np.random.rand(128,128).astype('float32')
kl = K.placeholder(dtype='float32')
beta = K.constant(value=5e-1)
p = K.constant(value=5e-2)
# encoder
model = Sequential()
model.add(Conv2D(filters=16,kernel_size=(4,4),padding='same', 
name='encoder',input_shape=(128,128,1)))
model.add(Activation('relu'))
# get the average activation
A = K.mean(x=model.output)
# calculate the value for the KL divergence
kl = K.concatenate([kl, losses.kullback_leibler_divergence(p, A)],axis=0)
# decoder
model.add(Conv2D(filters=1,kernel_size=(4,4),padding='same', name='encoder'))
model.add(Activation('relu'))
B = K.mean(x=model.output)
kl = K.concatenate([kl, losses.kullback_leibler_divergence(p, B)],axis=0)

这里似乎是原因

/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py in _normalize_axis(axis, ndim)
989     else:
990         if axis is not None and axis < 0:
991             axis %= ndim <----------
992     return axis
993 

因此,平均计算中可能有问题。如果我打印值,我会得到

Tensor("Mean_10:0", shape=(), dtype=float32)

这很奇怪,因为权重和偏见是非零初始化的。因此,获取激活值可能有问题。

我真的不知道修复它,我不是一个熟练的程序员。谁能帮助我理解我错了?

首先,您不应该在层外进行计算。model必须跟踪所有计算。

  • 如果您需要在模型中间进行特定的计算,则应使用Lambda层。

  • 如果您需要在损失函数中使用特定的输出,则应将模型分配给该输出,并在自定义损失函数中进行计算。

在这里,我使用Lambda层来计算平均值,而customLoss计算kullback-leibler差异。

import numpy as np
from keras.layers import *
from keras.models import Model
from keras import backend as K
from keras import losses
x_train = np.random.rand(128,128).astype('float32')
kl = K.placeholder(dtype='float32') #you'll probably not need this anymore, since losses will be treated individually in each output.
beta = beta = K.constant(value=5e-1)
p = K.constant(value=5e-2) 

# encoder
inp = Input((128,128,1))
lay = Convolution2D(filters=16,kernel_size=(4,4),padding='same', name='encoder',activation='relu')(inp)
#apply the mean using a lambda layer: 
intermediateOut = Lambda(lambda x: K.mean(x),output_shape=(1,))(lay)

# decoder
finalOut = Convolution2D(filters=1,kernel_size=(4,4),padding='same', name='encoder',activation='relu')(lay)
#but from that, let's also calculate a mean output for loss:
meanFinalOut = Lambda(lambda x: K.mean(x),output_shape=(1,))(finalOut)
#Now, you have to create a model taking one input and those three outputs:
splitModel = Model(inp,[intermediateOut,meanFinalOut,finalOut]) 

最后,使用您的自定义损失功能编译您的模型(我们将稍后定义(。但是,由于我不知道您是否实际使用最终输出(不是指训练(,因此我建议创建一种培训模型,而另一种预测:

trainingModel = Model(inp,[intermediateOut,meanFinalOut])
trainingModel.compile(...,loss=customLoss)
predictingModel = Model(inp,finalOut)
#you don't need to compile the predicting model since you're only training the trainingModel 
#both will share the same weights, you train one, and predict in the other

我们的自定义损失功能应该处理kullback。

def customLoss(p,mean):
    return #your own kullback expression (I don't know how it works, but maybe keras' one can be used with single values?)

另外,如果您希望调用单个损失函数,而不是两个:

summedMeans = Add([intermediateOut,meanFinalOut])    
trainingModel = Model(inp, summedMeans)

最新更新