带矩阵乘法的Keras自定义损失函数(梯度误差)

时间:2019-09-04 19:31:59

标签: tensorflow keras

我正在尝试重新创建模型,概述了一篇论文(Anomaly Detection using Deep Learning based Image Completion)以便在Keras中完成图像,但是我目前仍然迷失在损失函数上:

Loss function

  • ⊙表示逐元素矩阵乘法
  • ‖⋅‖1表示L1矩阵范数
  • 在Keras中,F是预测值,X是真实值。

我写的是下面的

import keras.backend as K
import tensorflow as tf
import numpy as np


def l1_reconstruction_loss(batch_size, mask_loss_weight=0.90, mask_size=32, img_size=128):
    n_pixels = img_size * img_size
    pad_size = int((img_size - mask_size) / 2)
    mask = np.ones((batch_size, mask_size, mask_size, 3))
    mask = np.pad(mask, ((0, 0), (pad_size, pad_size), (pad_size, pad_size), (0, 0)), 'constant')
    inv_mask = np.logical_not(mask).astype(np.float32)

    def _loss_func(y_true, y_pred):
        mask_tf = tf.convert_to_tensor(mask, np.float32)
        inv_mask_tf = tf.convert_to_tensor(inv_mask, np.float32)
        inv_mask_true = tf.math.multiply(y_true, inv_mask_tf)
        pred_dot_inv_mask_true = tf.matmul(y_pred, inv_mask_true)
        true_sub_pred_dot_inv_mask_true = tf.math.subtract(y_true, pred_dot_inv_mask_true)

        inner_expr_a = tf.math.multiply(mask_tf, true_sub_pred_dot_inv_mask_true)

        inner_expr_b = tf.math.multiply(inv_mask_tf, true_sub_pred_dot_inv_mask_true)

        mask_loss = mask_loss_weight * K.sum(K.abs(inner_expr_a)) / n_pixels + (1 - mask_loss_weight) * K.sum(K.abs(inner_expr_b)) / n_pixels
        return mask_loss

    def loss_func(y_true, y_pred):
        return _loss_func(y_pred, y_true)

    return loss_func

编辑:我修改了损失函数代码,不再遇到与梯度有关的错误。

它导致错误:

tensorflow.python.framework.errors_impl.InvalidArgumentError: In[0] mismatch In[1] shape: 3 vs. 128: [128,128,128,3] [128,128,128,3] 0 0
     [[{{node loss/layer17_loss/MatMul}}]]

模型编译步骤:

model.compile(loss=l1_reconstruction_loss(batch_size=128, mask_size=32, img_size=128),optimizer=optimizer)

型号:

img_input = layers.Input(shape=(img_size, img_size, 3))

    # This will mask the central region (square), of image, replacing it with black.
    # x = layers.Lambda(
    #     function=lambda imgs: tf.map_fn(lambda x: mask_img(img=x, mask_size=mask_size, img_size=img_size), imgs)
    # )(img_input)

    # Layer 1
    x = layers.Conv2D(32,
                      kernel_size=5,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer1')(img_input)
    # Layer 2
    x = layers.Conv2D(64,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer2')(x)
    # Layer 3
    x = layers.Conv2D(64,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer3')(x)
    # Layer 4
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=2,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer4')(x)
    # Layer 5
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer5')(x)

    # Layer 6
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer6')(x)

    # Layer 7
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(2, 2),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer7')(x)

    # Layer 8
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(4, 4),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer8')(x)

    # Layer 9
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(8, 8),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer9')(x)

    # Layer 10
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(16, 16),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer10')(x)

    # Layer 11
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer11')(x)

    # Layer 12
    x = layers.Conv2D(128,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer12')(x)

    # Bilinear Upscaling/Upsampling
    x = layers.UpSampling2D(size=2, interpolation='bilinear')(x)

    # Layer 13
    x = layers.Conv2D(64,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer13')(x)

    # Layer 14
    x = layers.Conv2D(64,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer14')(x)

    # Layer 15
    x = layers.Conv2D(32,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer15')(x)

    # Layer 16
    x = layers.Conv2D(16,
                      kernel_size=3,
                      strides=1,
                      dilation_rate=(1, 1),
                      kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                      bias_initializer=initializers.Zeros(),
                      padding='same',
                      activation='elu',
                      name='layer16')(x)

    # Layer 17
    out = layers.Conv2D(3,
                        kernel_size=3,
                        strides=1,
                        dilation_rate=(1, 1),
                        kernel_initializer=initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None),
                        bias_initializer=initializers.Zeros(),
                        padding='same',
                        activation='elu',
                        name='layer17')(x)

我在做什么错了?

0 个答案:

没有答案