在Tensorflow中实现对比损失和三元组丢失

Tia*_*ira 38 deep-learning tensorflow

两天前我开始玩TensorFlow,我想知道是否有三重奏和实施的对比损失.

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

Oli*_*rot 72

更新(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)
Run Code Online (Sandbox Code Playgroud)

三胞胎损失

与对比度损失相同,但具有三元组(锚,正,负).你这里不需要标签.

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)
Run Code Online (Sandbox Code Playgroud)

在TensorFlow中实现三重态丢失或对比度损失时的真正问题是如何对三元组或三元组进行采样.我将专注于生成三元组,因为它比生成对更难.

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

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

显然,在Tensorflow中实现三元组丢失很难,并且有一些方法可以使它比在python中采样更有效,但解释它们需要整篇博文!

  • @HelloLili:我终于写了那篇博文.这是:https://omoindrot.github.io/triplet-loss (2认同)

小智 11

半硬度负采矿的三重损失现在实施tf.contrib如下:

triplet_semihard_loss(
    labels,
    embeddings,
    margin=1.0
)
Run Code Online (Sandbox Code Playgroud)

哪里:

ARGS:

  • labels:1-D tf.int32具有多类整数标签形状[batch_size]的张量.

  • 嵌入:2-D float嵌入向量的张量.嵌入应该是l2归一化的.

  • margin:浮动,保证定义中的保证金期限.

返回:

  • triplet_loss:tf.float32标量.

有关详细信息,请查看以下链接:

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


Was*_* Gr 5

蒂亚戈,我认为你没有使用奥利维尔给出的相同配方.这是正确的代码(不确定它会工作,只是修复公式):

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
Run Code Online (Sandbox Code Playgroud)