如何在 Keras 中创建这个自定义损失函数并确保它是可微的?

Posted

技术标签:

【中文标题】如何在 Keras 中创建这个自定义损失函数并确保它是可微的?【英文标题】:How to create this custom loss function in Keras and ensure it is differentiable? 【发布时间】:2018-03-23 21:59:10 【问题描述】:

我正在使用功能模型 API,我想在 Keras 中创建以下自定义损失函数:

损失方程图像

我正在实现一个无监督的 CNN,值 Ix、Iy、It 和 epsilon 是常数,u 和 v 是我要学习的参数。

到目前为止,我的尝试都失败了,当我尝试训练它时,我的模型返回一个 ValueError 说“不支持任何值”。谷歌搜索后,我发现这是由于我的损失不可区分。

有人可以告诉我如何以 Keras 可区分的方式正确创建此损失函数。我的代码如下,任何帮助将不胜感激。

def charbonnier(I_x, I_y, I_t, U, V, e):
    def charb(y_true, y_pred):
        loss = K.sqrt(K.pow((multiply([U, I_x]) + multiply([V, I_y]) + I_t), 2) + e)
        return K.mean(loss, axis=-1)
    return charb


   # Return the tf session used by the backend (optional)
   tf_session = K.get_session()




def cnn(frame1, frame2):
       # Concatenate the two images into one tensor.
    input_ = np.dstack((frame1, frame2))
    input_ = np.expand_dims(input_, axis=0)
    print(input_.shape)

    # Compute derivatives
    I_x, I_y, I_t = compute_derivatives(input_)

    #input_ = K.variable(input_)
    inp_shape = (1, frame1.shape[0], frame1.shape[1], 2)

    inp = Input(batch_shape=inp_shape)
    conv1 = Conv2D(256, (7, 7), activation='relu', padding='same')(inp)
    conv2 = Conv2D(256, (5, 5), activation='relu', padding='same')(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv2)
    conv3 = Conv2D(512, (5, 5), activation='relu', padding='same')(pool1)
    conv4 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv3)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool2)
    conv6 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv6)
    conv7 = Conv2D(1024, (3, 3), activation='relu', padding='same')(pool3)
    conv8 = Conv2D(512, (1, 1), activation='relu', padding='same')(conv7)
    pool4 = MaxPooling2D(pool_size=(2, 2))(conv8)
    conv9 = Conv2D(256, (5, 5), activation='relu', padding='same')(pool4)
    upsample1 = UpSampling2D(size=(2, 2))(conv9)
    conv10 = Conv2D(128, (5, 5), activation='relu', padding='same')(upsample1)
    upsample2 = UpSampling2D(size=(2, 2))(conv10)
    conv11 = Conv2D(64, (5, 5), activation='relu', padding='same')(upsample2)
    upsample3 = UpSampling2D(size=(2, 2))(conv11)
    conv12 = Conv2D(2, (15, 13), padding='same')(upsample3)
    leaky_relu = LeakyReLU(alpha=0.3)(conv12)
    upsample4 = UpSampling2D(size=(2, 2), name='flow')(leaky_relu)

    model = Model(inputs=inp, outputs=upsample4)

    U = K.variable(model.output[0, :, :, 0])
    V = K.variable(model.output[0, :, :, 1])
    e = K.constant(0.1)

    c_loss = charbonnier(I_x, I_y, I_t, U, V, e)

    model.compile(loss=c_loss, optimizer='adam')
    model.fit(input_, input_, batch_size=1, epochs=10)
    model.evaluate()

【问题讨论】:

【参考方案1】:

解决了。

变量 U 和 V 应按如下方式创建:

U = model.output[0, :, :, 0]
V = model.output[0, :, :, 1]

【讨论】:

以上是关于如何在 Keras 中创建这个自定义损失函数并确保它是可微的?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Keras 中创建一个依赖于纪元数的损失函数参数?

Keras 中的自定义损失函数 - 遍历 TensorFlow

Keras 中带有附加变量输入的自定义损失/目标函数

如何在 keras 中测试自定义损失函数?

如何在生成器提供的 Keras 自定义损失函数中访问样本权重?

如何在 Keras 自定义损失函数中使用张量?