python – 重构自定义丢失函数中的张量

我有一个类似于
this question的问题.我试图在keras中设计一个损失函数,如下所示:

def depth_loss_func(lr):
    def loss(actual_depth,pred_depth):
        actual_shape = actual_depth.get_shape().as_list()
        dim = np.prod(actual_shape[1:])
        actual_vec = K.reshape(actual_depth,[-1,dim])
        pred_vec = K.reshape(pred_depth,[-1,dim])
        di = K.log(pred_vec)-K.log(actual_vec)
        di_mean = K.mean(di)
        sq_mean = K.mean(K.square(di))

        return (sq_mean - (lr*di_mean*di_mean))
    return loss

基于this question给出的答案.但是,我收到一个错误:

 TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType'

具体而言,此语句提供以下输出

(Pdb) actual_depth.get_shape()
TensorShape([Dimension(None), Dimension(None), Dimension(None)])

后端是TensorFlow.谢谢你的帮助.

最佳答案 当我像这样调用np.prod()时,我设法用Tensor of shape(None,None,None,9)重现你的异常:

from keras import backend as K

#create tensor placeholder
z = K.placeholder(shape=(None, None, None, 9))
#obtain its static shape with int_shape from Keras
actual_shape = K.int_shape(z)
#obtain product, error fires here... TypeError between None and None
dim = np.prod(actual_shape[1:])

发生这种情况是因为您尝试将两个类型为None的元素相乘,即使您对actual_shape进行切片(因为多于1个元素为None).在某些情况下,如果在切片后只剩下一个非类型元素,您甚至可以在None和int之间获得TypeError.

看一下你提到的answer,它们指明在这些情况下该做什么,引用它:

For the cases where more than 1 dimension are undefined, we can use tf.shape() with tf.reduce_prod() alternatively.

基于此,我们可以分别使用K.shape()(docs)和K.prod()(docs)将这些操作转换为Keras API:

z = K.placeholder(shape=(None, None, None, 9))
#obtain Real shape and calculate dim with prod, no TypeError this time
dim = K.prod(K.shape(z)[1:])
#reshape
z2 = K.reshape(z, [-1,dim])

此外,对于只有一个维度未定义的情况,请记住使用K.int_shape(z)或其包装器K.get_variable_shape(z)而不仅仅是get_shape(),这也在后端(docs)中定义.希望这能解决你的问题.

点赞