2016-06-07 75 views
4

我试图在TensorFlow中实现最大毛利损失。 的想法是,我有一些正面的例子,我品尝了一些负面的例子,想计算像TensorFlow中的最大毛利损失

\sum_{b}^{B} \sum_{n}^{N}max(0, 1 - score(p_b) + score(p_n))

其中B是我的批处理的大小,N是我要负的样本数使用。

我是tensorflow的新手,我很难实现它。 我的模型计算维度为B * (N + 1)的分数矢量,其中我交替阳性样本和阴性样本。例如,对于批量大小为2和2的反例,我有一个大小为6的向量,第一个正面例子的索引为0,第二个正面例子为第三个,而第二, 4和5. 理想的是获得像[1, 0, 0, 1, 0, 0]这样的值。

我能想出了如下,同时使用和条件:

# Function for computing max margin inner loop 
def max_margin_inner(i, batch_examples_t, j, scores, loss): 
    idx_pos = tf.mul(i, batch_examples_t) 
    score_pos = tf.gather(scores, idx_pos) 
    idx_neg = tf.add_n([tf.mul(i, batch_examples_t), j, 1]) 
    score_neg = tf.gather(scores, idx_neg) 
    loss = tf.add(loss, tf.maximum(0.0, 1.0 - score_pos + score_neg)) 
    tf.add(j, 1) 
    return [i, batch_examples_t, j, scores, loss] 

# Function for computing max margin outer loop 
def max_margin_outer(i, batch_examples_t, scores, loss): 
    j = tf.constant(0) 
    pos_idx = tf.mul(i, batch_examples_t) 
    length = tf.gather(tf.shape(scores), 0) 
    neg_smp_t = tf.constant(num_negative_samples) 
    cond = lambda i, b, j, bi, lo: tf.logical_and(
     tf.less(j, neg_smp_t), 
     tf.less(pos_idx, length)) 
    tf.while_loop(cond, max_margin_inner, [i, batch_examples_t, j, scores, loss]) 
    tf.add(i, 1) 
    return [i, batch_examples_t, scores, loss] 

# compute the loss 
with tf.name_scope('max_margin'): 
    loss = tf.Variable(0.0, name="loss") 
    i = tf.constant(0) 
    batch_examples_t = tf.constant(batch_examples) 
    condition = lambda i, b, bi, lo: tf.less(i, b) 
    max_margin = tf.while_loop(
     condition, 
     max_margin_outer, 
     [i, batch_examples_t, scores, loss]) 

的代码有两个回路,一个是外总和,另一个用于内部之一。我面临的问题是损失变量在每次迭代时都会累积错误,而不会在每次迭代后重置。所以它实际上根本不起作用。

此外,它似乎确实不符合tensorflow方式实施的东西。我想可能有更好的方法,更多矢量化的方法来实现它,希望有人会建议选项或者指点我的例子。

回答

6

首先我们需要清洁输入:

  • 我们想要正得分的阵列,形状的[B, 1]
  • 我们想要负得分的矩阵,形状[B, N]
import tensorflow as tf 

B = 2 
N = 2 
scores = tf.constant([0.5, 0.2, -0.1, 1., -0.5, 0.3]) # shape B * (N+1) 

scores = tf.reshape(scores, [B, N+1]) 

scores_pos = tf.slice(scores, [0, 0], [B, 1]) 

scores_neg = tf.slice(scores, [0, 1], [B, N]) 

现在我们只需要计算损失的矩阵即i。 e。每对的所有单项损失(正面,负面),并计算其总和。

loss_matrix = tf.maximum(0., 1. - scores_pos + scores_neg) # we could also use tf.nn.relu here 
loss = tf.reduce_sum(loss_matrix) 
+1

这是一个很好的回答Olivier,谢谢!其实你是两次转位,但这不是必需的。你可以直接做: scores = tf.reshape(scores,[B,N + 1]) scores_pos = tf.slice(scores,[0,0],[B,1]) scores_neg = tf.slice分数,[0,1],[B,N]) 请用此更新您的答案。 – w4nderlust

+0

你是对的!我想我以为'tf.slice'只能在第一维中切片,但我没有错 –