繁体   English   中英

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

[英]How to make a custom loss function in Keras properly

我正在制作一种模式,预测是来自 conv 层的矩阵。 我的损失函数是

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 越界。 对于 'loss/max_pooling2d_5_loss/custom_loss/strided_slice_92' (op: 'StridedSlice') 输入形状:[?,7,14,5], [2], [2], [2] 和计算输入张量: input[ 1] = <0 7>,输入[2] = <1 8>,输入[3] = <1 1>。

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

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

为了回答您的一些疑虑,

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

通常这是一个非常糟糕的做法。 深度网络通常在数百万个样本上进行训练。 因此,使用循环而不是使用矢量化操作会真正降低您的模型性能。

实现无循环。

我不确定我是否在损失函数中准确地捕捉到了你想要的东西。 但我很确定它非常接近(如果不是,这就是您所需要的)。 我可以用固定的随机种子将你的损失与我的损失进行比较,看看我是否得到了你的损失函数给出的结果。 但是,由于您的损失不起作用,我不能这样做。

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM