如何在Keras中正确制作自定义损失函数

时间:2019-12-19 03:05:25

标签: python tensorflow keras conv-neural-network loss-function

我正在做出一种模式,即预测是来自转换层的metrix。 我的损失函数是

def custom_loss(y_true, y_pred):
    print("in loss...")
    final_loss = float(0)
    print(y_pred.shape)
    print(y_true.shape)
    for i in range(7):
        for j in range(14):
            tl = float(0)
            gt = y_true[i,j]
            gp = y_pred[i,j]
            if gt[0] == 0:
                tl = K.square(gp[0] - gt[0])
            else:
                for l in range(5):
                    tl = tl + K.square(gp[l] - gt[l])/5
            final_loss = final_loss + tl/98
    return final_loss

从参数打印出来的形状是

(?, 7,14,5)

(?,?,?,?)

标签的形状为7x14x5。

似乎损失函数需要一次预测列表,而不是一次预测。我对Keras不太陌生,还不太了解这些工作原理。

这是我的模特

model = Sequential()
input_shape=(360, 640, 1)

model.add(Conv2D(24, (5, 5), strides=(1, 1), input_shape=input_shape))
model.add(MaxPooling2D((2,4), strides=(2, 2)))

model.add(Conv2D(48, (5, 5), padding="valid"))
model.add(MaxPooling2D((2,4), strides=(2, 2)))

model.add(Conv2D(48, (5, 5), padding="valid"))
model.add(MaxPooling2D((2,4), strides=(2, 2)))

model.add(Conv2D(24, (5, 5), padding="valid"))
model.add(MaxPooling2D((2,4), strides=(2, 2)))

model.add(Conv2D(5, (5, 5), padding="valid"))
model.add(MaxPooling2D((2,4), strides=(2, 2)))


model.compile(
    optimizer="Adam",
    loss=custom_loss,
    metrics=['accuracy'])

print(model.summary())

我收到类似

的错误

ValueError:维度1的切片索引7超出范围。对于具有输入形状:[?, 7,14,5],[2],[2],[2]和计算出的输入张量:'input [ 1] = <0 7>,输入[2] = <1 8>,输入[3] = <1 1>。

我想我知道这是因为在许多4D预测中一次都给出了损失函数的参数。

我该如何解决?我分配损失函数或损失函数的方式存在问题。 现在,损失函数的输出为浮点型。但这应该是什么。

1 个答案:

答案 0 :(得分:1)

要回答您的一些担忧,

  

我看不到有人在损失函数中使用循环

通常,这是一个非常糟糕的做法。深网通常会训练数百万个样本。因此,使用循环而不是使用向量化运算会确实降低模型的性能。

没有循环的实现。

我不确定我是否已经准确地捕捉到了损失函数中想要的东西。但是我很确定它已经非常接近(如果不是,这就是您所需要的)。我可以用固定的随机种子将您对我的损失与我的损失进行比较,以查看我是否完全得到了损失函数给出的结果。但是,由于您的损失无法解决,我无法做到这一点。

def custom_loss_v2(y_true, y_pred):
  # We create MSE loss that captures what's in the else condition -> shape [batch_size, height, width]
  mse = tf.reduce_mean((y_true-y_pred)**2, axis=-1)

  # We create pred_first_ch tensor that captures what's in the if condition -> shape [batch, height, width]
  pred_first_ch = tf.gather(tf.transpose(y_pred**2, [3,0,1,2]),0)

  # We create this to get a boolean array that satisfy the conditions in the if else statement
  true_first_zero_mask = tf.equal(tf.gather(tf.transpose(y_true, [3,0,1,2]),0), 0)

  # Then we use tf.where with reduce_mean to get the final loss
  res = tf.where(true_first_zero_mask, pred_first_ch, mse)
  return tf.reduce_mean(res)