【发布时间】:2016-07-08 06:20:37
【问题描述】:
两天前我开始玩 TensorFlow,我想知道是否实现了三元组和对比损失。
我一直在查看the documentation,但我没有找到任何关于这些事情的示例或描述。
【问题讨论】:
两天前我开始玩 TensorFlow,我想知道是否实现了三元组和对比损失。
我一直在查看the documentation,但我没有找到任何关于这些事情的示例或描述。
【问题讨论】:
更新(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 中的采样更有效,但解释它们需要整篇博文!
【讨论】:
sess.run() 调用,您可以在图中添加tf.py_func 操作以过滤掉坏的三元组。
Triplet loss with semihardnegative mining现在在tf.contrib中实现,如下:
triplet_semihard_loss(
labels,
embeddings,
margin=1.0
)
地点:
参数:
标签:具有多类形状 [batch_size] 的一维 tf.int32 张量 整数标签。
嵌入:嵌入向量的二维浮点张量。嵌入应该 进行 l2 归一化。
返回:
欲了解更多信息,请查看以下链接:
【讨论】:
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
【讨论】: