简体   繁体   English

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

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

i am making a mode that the prediction is a metrix from a conv layer.我正在制作一种模式,预测是来自 conv 层的矩阵。 my loss function is我的损失函数是

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

the shapes that printed out from the arguments are从参数打印出来的形状是

(?, 7, 14, 5) (?, 7, 14, 5)

(?, ?, ?, ?) (?, ?, ?, ?)

the labels are in the shape of 7x14x5.标签的形状为 7x14x5。

it seems like the loss function gets called for a list of predictions instead of one prediction at a time.似乎损失函数被调用以获取一系列预测,而不是一次一个预测。 I am relatively new to Keras and don't really understand how these things work.我对 Keras 比较陌生,不太了解这些东西是如何工作的。

this is my model这是我的模型

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())

I am getting an error like我收到类似的错误

ValueError: slice index 7 of dimension 1 out of bounds. ValueError:维度 1 的切片索引 7 越界。 for 'loss/max_pooling2d_5_loss/custom_loss/strided_slice_92' (op: 'StridedSlice') with input shapes: [?,7,14,5], [2], [2], [2] and with computed input tensors: input[1] = <0 7>, input[2] = <1 8>, input[3] = <1 1>.对于 '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>。

I think I know this is because of the arguments to the loss function is given in many predictions at a time with 4D.我想我知道这是因为在使用 4D 时在许多预测中都给出了损失函数的参数。

how can I fix?我该如何解决? is the problem in the way I assign the loss function or in the loss function.是我分配损失函数的方式或损失函数的问题。 for now, the output of the loss function is a float.现在,损失函数的输出是一个浮点数。 but what is it supposed to be.但它应该是什么。

To answer some of your concerns,为了回答您的一些疑虑,

I don't see anyone use loops in the loss function我没有看到有人在损失函数中使用循环

Usually it's a pretty bad practice.通常这是一个非常糟糕的做法。 Deep nets train on millions of samples usually.深度网络通常在数百万个样本上进行训练。 Having loops instead of using vectorized operations therefore, will really bring down your model performance.因此,使用循环而不是使用矢量化操作会真正降低您的模型性能。

Implementing without loops.实现无循环。

I'm not sure if I've exactly captured what you wanted in your loss function.我不确定我是否在损失函数中准确地捕捉到了你想要的东西。 But I'm quite sure it's very close (if not this is what you needed).但我很确定它非常接近(如果不是,这就是您所需要的)。 I could have compared your loss against mine with fixed random seeds to see if I get exactly the result given by your loss function.我可以用固定的随机种子将你的损失与我的损失进行比较,看看我是否得到了你的损失函数给出的结果。 However, since your loss is not working, I can't do that.但是,由于您的损失不起作用,我不能这样做。

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