【问题标题】:Is it possible to write a custom loss function that is based on the difference of sample outputs in a batch in Keras?是否可以根据 Keras 中批次中样本输出的差异编写自定义损失函数?
【发布时间】:2019-09-29 11:03:07
【问题描述】:

我正在尝试在 Keras 中实现损失函数,它可以执行以下操作:

假设 y0, y1, ..., yn 是模型 batch output 对于一个批输入 x0, x1, ..., xn,这里 batch_size 是 n+1,输出 yi 为每个 xi 是一个标量值,我希望损失函数计算该批次的 整体损失,如下所示:

K.log(K.sigmoid(y1-y0))+K.log(K.sigmoid(y2-y1))+...+K.log(K.sigmoid(yn-yn-1))

我正在考虑使用 Lambda 层首先将批量输出 [y0,y1,...,yn] 转换为 [y1-y0, y2-y1, ...,yn-yn-1],然后使用转换后的输出上的自定义损失函数。

但是,我不确定 Keras 是否能够理解 Lambda 层中没有要更新的权重,并且我不清楚 Keras 将如何通过 Lambda 层将梯度传播回,因为Keras 通常要求每个层/损失函数对单个样本输入进行操作,但我的层将获取一批样本的全部输出。以前有没有人解决过类似的问题?谢谢!

【问题讨论】:

    标签: tensorflow keras


    【解决方案1】:

    像下面这样的切片对你有用吗(虽然我没有使用 keras)。

    batch = 4
    num_classes = 6
    logits = tf.random.uniform(shape=[batch, num_classes])
    
    logits1 = tf.slice(logits, (0, 0), [batch, num_classes-1])
    logits2 = tf.slice(logits, (0, 1), [batch, num_classes-1])
    
    delta = logits2 - logits1
    loss = tf.reduce_sum(tf.log(tf.nn.sigmoid(delta)), axis=-1)
    
    with tf.Session() as sess:
      logits, logits1, logits2, delta, loss  = sess.run([logits, logits1, logits2, 
                                                         delta, loss])
    
      print 'logits\n', logits
      print 'logits2\n', logits2
      print 'logits1\n', logits1
      print 'delta\n', delta
      print 'loss\n', loss
    

    结果:

    logits
    [[ 0.61241663  0.70075285  0.98333454  0.4117974   0.5943476   0.84245574]
     [ 0.02499413  0.22279179  0.70742595  0.34853518  0.7837007   0.88074362]
     [ 0.35030317  0.36670768  0.64244425  0.87957716  0.22823489  0.45076978]
     [ 0.38116801  0.39040041  0.82510674  0.64789391  0.45415008  0.03520513]]
    logits2
    [[ 0.70075285  0.98333454  0.4117974   0.5943476   0.84245574]
     [ 0.22279179  0.70742595  0.34853518  0.7837007   0.88074362]
     [ 0.36670768  0.64244425  0.87957716  0.22823489  0.45076978]
     [ 0.39040041  0.82510674  0.64789391  0.45415008  0.03520513]]
    logits1
    [[ 0.61241663  0.70075285  0.98333454  0.4117974   0.5943476 ]
     [ 0.02499413  0.22279179  0.70742595  0.34853518  0.7837007 ]
     [ 0.35030317  0.36670768  0.64244425  0.87957716  0.22823489]
     [ 0.38116801  0.39040041  0.82510674  0.64789391  0.45415008]]
    delta
    [[ 0.08833623  0.28258169 -0.57153714  0.18255019  0.24810815]
     [ 0.19779766  0.48463416 -0.35889077  0.43516552  0.09704292]
     [ 0.01640451  0.27573657  0.23713291 -0.65134227  0.22253489]
     [ 0.0092324   0.43470633 -0.17721283 -0.19374382 -0.41894495]]
    loss
    [-3.41376281 -3.11249781 -3.49031925 -3.69255161]
    

    【讨论】:

    • 谢谢,但我正在尝试将 batch_size 维度减少 1,而不是特征维度,这很令人困惑,我将更新问题并进行更多说明。
    • 也许我错过了什么,如果减少是批量的,为什么类似的切片不起作用?
    • 这就是我的意思:logits = tf.random.uniform(shape=[batch, 1]) logits1 = tf.slice(logits, (0, 0), [batch-1, 1]) logits2 = tf.slice(logits, (1, 0), [batch-1, 1])
    • 感谢格林尼斯!这个和我之前做的差不多,我直接用了y_pred[1:,:]-y_pred[:-1,:],代码可以运行,但是好像keras没有搞好反向传播,需要自定义损失函数返回每个样本的损失,当我将它们放在一起时,它无法弄清楚如何分解它们。你有什么想法可以解决这个问题吗?
    • 我明白你的意思。我做了一些搜索,发现了这个悬而未决的问题,这似乎很相关:github.com/tensorflow/tensorflow/issues/22059。如果我理解正确的话,我们也在优化一个变量。
    猜你喜欢
    • 1970-01-01
    • 2020-12-03
    • 2021-09-21
    • 2019-06-19
    • 2019-10-12
    • 2021-02-24
    • 2021-12-15
    • 1970-01-01
    • 2021-12-02
    相关资源
    最近更新 更多