使用TensorFlow实现交并比损失函数

7
这可能更多是关于Tensorflow梯度问题。我一直在尝试将交并比(IoU)作为损失函数实现,并遇到了一些问题。此处是计算IoU的代码片段:
def get_iou(masks, predictions):
    ious = []
    for i in range(batch_size):
        mask = masks[i]
        pred = predictions[i]
        masks_sum = tf.reduce_sum(mask)
        predictions_sum = tf.reduce_mean(pred)
        intersection = tf.reduce_sum(tf.multiply(mask, pred))
        union = masks_sum + predictions_sum - intersection
        iou = intersection / union
        ious.append(iou)
    return ious

iou = get_iou(masks, predictions)
mean_iou_loss = -tf.log(tf.reduce_sum(iou))
train_op = tf.train.AdamOptimizer(0.001).minimize(mean_iou_loss)

它按预测的那样工作。但我遇到的问题是损失不会减少。模型确实进行了训练,但结果不尽如人意,所以我想知道我是否正确地实现了它。我需要自己计算梯度吗?我可以使用 tf.gradients() 计算 这篇论文 派生的IoU损失的梯度,但我不确定如何将其与 tf.train.AdamOptimizer() 结合使用。通过阅读文档,我觉得 compute_gradientsapply_gradients 是我需要使用的命令,但我找不到任何关于如何使用它们的示例。我的理解是,Tensorflow图应该能够通过链式法则自动推导出梯度。因此,在这个问题中,甚至需要自定义梯度吗?如果自定义梯度不必要,则可能只是我遇到了一个病态问题,需要调整一些超参数。

注意: 我已经尝试了Tensorflow的IoU实现,tf.metrics.mean_iou() ,但每次都会输出 inf ,所以我已放弃使用它。


loss 是如何定义的?它与 mean_iou_loss 有什么关系? - Sharky
好眼力,我刚刚复制错了。mean_iou_loss是损失函数。已经在上面修正了。 - MasterYoda
1个回答

6

梯度计算发生在optimizer.minimize函数内部,因此,不需要在损失函数内显式使用。但是,你的实现缺少可优化、可训练的变量。

iou = get_iou(masks, predictions)
mean_iou_loss = tf.Variable(initial_value=-tf.log(tf.reduce_sum(iou)), name='loss', trainable=True)
train_op = tf.train.AdamOptimizer(0.001).minimize(mean_iou_loss)

除了数值稳定性、可微性和特定实现之外,这应该足以将其用作损失函数,随着迭代而改变。
另外也要看一下:

https://arxiv.org/pdf/1902.09630.pdf

为什么不使用IOU进行训练?


谢谢您的回答,不过这个修复方法并没有起作用。代码在定义张量变量阶段卡住了,即mean_iou_loss = tf.Variable(initial_value=-tf.log(tf.reduce_sum(iou)), name='loss', trainable=True) - MasterYoda
奇怪,它绝对应该可以工作。它是否抛出任何错误? - Sharky
这不是OOM问题;我已经尝试了批处理大小为1,并通过nvidia-smi检查了内存,但仍然没有改变。它似乎在树的各个部分都会卡住。我尝试将其初始化为常量而不是-tf.log(tf.reduce_sum(iou)),这样就可以正常工作了。 - MasterYoda
你使用什么类型、维度的输入数据? - Sharky
因此,为了获得边界框的预测,我必须执行一个´tf.argmax´操作,我认为梯度未定义。这可能是我的问题的根源。 - MasterYoda
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接