在Tensorflow中实现对比损失和三重损失
deep-learning
tensorflow
6
0

我从两天前开始使用TensorFlow,我想知道是否存在三重奏和对比损失。

我一直在查看文档 ,但尚未找到有关这些内容的任何示例或描述。

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

现在,在tf.contrib实现了具有半 tf.contrib 负挖掘的三重损失。

triplet_semihard_loss(
    labels,
    embeddings,
    margin=1.0
)

哪里:

精氨酸:

  • 标签:一维tf.int32张量,形状为[batch_size],为多类整数标签。

  • 嵌入:嵌入向量的二维浮点张量。嵌入应标准化l2。

  • 保证金:浮动,亏损定义中的保证金条款。

返回值:

  • Triplet_loss:tf.float32标量。

有关更多信息,请检查以下链接:

https://www.tensorflow.org/versions/master/api_docs/python/tf/contrib/losses/metric_learning/triplet_semihard_loss

收藏
评论

Tiago,我不认为您使用的是Olivier给出的相同公式。这是正确的代码(尽管确定公式,但不确定它是否会起作用):

def compute_euclidean_distance(x, y):
    """
    Computes the euclidean distance between two tensorflow variables
    """

    d = tf.reduce_sum(tf.square(tf.sub(x, y)),1)
    return d


def compute_contrastive_loss(left_feature, right_feature, label, margin):

    """
    Compute the contrastive loss as in


    L = 0.5 * Y * D^2 + 0.5 * (Y-1) * {max(0, margin - D)}^2

    **Parameters**
     left_feature: First element of the pair
     right_feature: Second element of the pair
     label: Label of the pair (0 or 1)
     margin: Contrastive margin

    **Returns**
     Return the loss operation

    """

    label = tf.to_float(label)
    one = tf.constant(1.0)

    d = compute_euclidean_distance(left_feature, right_feature)
    d_sqrt = tf.sqrt(compute_euclidean_distance(left_feature, right_feature))
    first_part = tf.mul(one-label, d)# (Y-1)*(d)

    max_part = tf.square(tf.maximum(margin-d_sqrt, 0))
    second_part = tf.mul(label, max_part)  # (Y) * max(margin - d, 0)

    loss = 0.5 * tf.reduce_mean(first_part + second_part)

    return loss
收藏
评论

更新(2018/03/19):我写了一篇博客文章,详细介绍了如何在TensorFlow中实现三重态损失。


您需要自己实现对比损失或三重损失,但是一旦知道了成对的或三元组的损失,就很容易了。


对比损失

假设您输入了数据对和它们的标签(正或负,即同一类或不同类)作为输入。例如,您将图像作为尺寸为28x28x1的输入:

left = tf.placeholder(tf.float32, [None, 28, 28, 1])
right = tf.placeholder(tf.float32, [None, 28, 28, 1])
label = tf.placeholder(tf.int32, [None, 1]). # 0 if same, 1 if different
margin = 0.2

left_output = model(left)  # shape [None, 128]
right_output = model(right)  # shape [None, 128]

d = tf.reduce_sum(tf.square(left_output - right_output), 1)
d_sqrt = tf.sqrt(d)

loss = label * tf.square(tf.maximum(0., margin - d_sqrt)) + (1 - label) * d

loss = 0.5 * tf.reduce_mean(loss)

三重损失

与对比损失相同,但三胞胎(锚,正,负)。您在这里不需要标签。

anchor_output = ...  # shape [None, 128]
positive_output = ...  # shape [None, 128]
negative_output = ...  # shape [None, 128]

d_pos = tf.reduce_sum(tf.square(anchor_output - positive_output), 1)
d_neg = tf.reduce_sum(tf.square(anchor_output - negative_output), 1)

loss = tf.maximum(0., margin + d_pos - d_neg)
loss = tf.reduce_mean(loss)

在TensorFlow中实现三元组损失或对比损失时,真正的麻烦是如何对三元组或三元组进行采样 。我将重点介绍生成三元组,因为它比生成对更困难。

最简单的方法是在Tensorflow图之外(即在python中)生成它们,然后通过占位符将它们提供给网络。基本上,您一次选择3张图像,前两张来自同一类别,第三张来自另一类别。然后,我们对这些三元组执行前馈,并计算三重态损失。

这里的问题是生成三元组很复杂。我们希望它们是有效的三元组,即正损失的三元组(否则损失为0且网络无法学习)。
要知道三元组是否好,您需要计算其损失,因此您已经通过网络进行了前馈...

显然,在Tensorflow中实现三重态损失很困难,并且有多种方法使其比在python中采样更有效,但要解释它们将需要一整篇博客文章!

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号