【问题标题】:How to make a custom loss function in Keras properly如何在 Keras 中正确地制作自定义损失函数
【发布时间】:2020-04-11 15:23:47
【问题描述】:

我正在制作一种模式,即预测是来自 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] = ,输入[2] = ,输入[3] = 。

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

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

【问题讨论】:

  • 我参考了这个来得到这个想法,stackoverflow.com/questions/41707621/…
  • 另一件事是我没有看到有人在损失函数中使用循环,为什么会这样,它与速度有关吗?如何在不使用循环的情况下以有效的方式实现此功能
  • 你能口头解释一下你需要在损失函数中做什么吗?不是很清楚

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


【解决方案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)

【讨论】:

  • 感谢您的回答,我将需要研究您回答的每一行,看看这就是我想要的。最重要的是我想学习如何做到这一点,所以谢谢。研究完我会回复你的
  • 你能看看你代码中的第二部分(创建第一个通道张量)吗,看起来你只是在访问 y_pred 中的数据,但请注意我同时使用这两个部分,我正在尝试如果 y_pred 中的第一个为 0,则得到所有五个变量的所有平方误差的损失(如果第一个值为 0,则其余的没有用,如果第一个值为 1,则考虑所有五个变量。
  • 我试图根据这个视频实现一个基本的 yolo 算法,你可以看看,它解释了我试图实现的 loos 函数。 youtube.com/…
  • @Eshaka 是的,你可以两者兼得,但我摆脱了y_true,因为y_true(在你的情况下,gt[0] 为零。(y_pred - 0)是 y_pred。
  • 我想你现在对这个模型有一个粗略的了解,我应该为此使用的指标如何,'准确性不合适'
猜你喜欢
  • 2018-02-08
  • 1970-01-01
  • 2018-03-01
  • 2020-12-19
  • 2017-12-18
  • 2020-03-27
  • 1970-01-01
  • 2020-08-01
  • 2018-11-24
相关资源
最近更新 更多