两天前我开始玩TensorFlow了,我想知道是否有三重奏和实施的对比损失。
我一直在关注the documentation,但我还没有找到关于这些事情的任何示例或描述。
答案 0 :(得分:69)
更新(2018/03/19):我写了一篇blog post详细说明了如何在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中采样更有效,但解释它们需要整篇博文!
答案 1 :(得分:11)
半硬性负挖掘的三联体损失现已在tf.contrib
中实施,如下所示:
triplet_semihard_loss(
labels,
embeddings,
margin=1.0
)
其中:
参数数量:
标签:1-D tf.int32具有多类形状[batch_size]的张量 整数标签。
嵌入:2-D float嵌入向量的张量。嵌入应该 是l2标准化。
返回:
有关详细信息,请查看以下链接:
答案 2 :(得分:5)
蒂亚戈,我不认为你使用的是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