Python 用TensorFlow进行两两距离计算

Python 用TensorFlow进行两两距离计算,python,tensorflow,distance,Python,Tensorflow,Distance,我试图推动这篇文章: 特别是第2节中的方程式(3) 很快,我想对每个小批量的特性进行成对距离计算,并将此损耗插入到一般网络损耗中。 我只有批次的Tesnor(16个样本)、批次的标签张量和批次特征张量 找了好一阵子,我还是搞不懂以下几点: 1) 如何将批次划分为阳性(即相同标签)和阴性对。因为张量不是迭代的,所以我不知道如何得到哪个样本有哪个标签,然后划分向量,或者得到张量的哪些索引属于每个类 2) 如何对批量张量中的某些指数进行成对距离计算 3) 我还需要为负面例子定义一个新的距离函数 总的来

我试图推动这篇文章: 特别是第2节中的方程式(3)

很快,我想对每个小批量的特性进行成对距离计算,并将此损耗插入到一般网络损耗中。 我只有批次的Tesnor(16个样本)、批次的标签张量和批次特征张量

找了好一阵子,我还是搞不懂以下几点:

1) 如何将批次划分为阳性(即相同标签)和阴性对。因为张量不是迭代的,所以我不知道如何得到哪个样本有哪个标签,然后划分向量,或者得到张量的哪些索引属于每个类

2) 如何对批量张量中的某些指数进行成对距离计算

3) 我还需要为负面例子定义一个新的距离函数

总的来说,我需要得到哪些索引属于哪个类,对所有正对进行正对距离计算。对所有负对进行另一次计算。然后将所有这些加在一起,计入网络损耗

任何帮助(对三个问题中的一个或多个问题)都将不胜感激。

1) 您应该在将数据馈送到会话之前进行配对采样。为每一对标记一个布尔标签,对于匹配的对,y=1,否则为0

2) 3)只需计算每对的两个pos/neg项,并让0-1标签y选择要添加到损失中的项


首先创建占位符,y_u表示布尔标签

dim = 64
x1_ = tf.placeholder('float32', shape=(None, dim))
x2_ = tf.placeholder('float32', shape=(None, dim))
y_ = tf.placeholder('uint8', shape=[None])   # uint8 for boolean
然后,该函数可以创建损失张量

def loss(x1, x2, y):
    # Euclidean distance between x1,x2
    l2diff = tf.sqrt( tf.reduce_sum(tf.square(tf.sub(x1, x2)),
                                    reduction_indices=1))

    # you can try margin parameters
    margin = tf.constant(1.)     

    labels = tf.to_float(y)

    match_loss = tf.square(l2diff, 'match_term')
    mismatch_loss = tf.maximum(0., tf.sub(margin, tf.square(l2diff)), 'mismatch_term')

    # if label is 1, only match_loss will count, otherwise mismatch_loss
    loss = tf.add(tf.mul(labels, match_loss), \
                  tf.mul((1 - labels), mismatch_loss), 'loss_add')

    loss_mean = tf.reduce_mean(loss)
    return loss_mean

loss_ = loss(x1_, x2_, y_)
然后输入数据(例如随机生成):

简短回答 我认为最简单的方法是离线采样对(即在TensorFlow图之外)。
您可以为一批对及其标签(正或负,即同一类或不同类)创建
tf.placeholder
,然后您可以在TensorFlow中计算相应的损失


使用代码
  • 您可以脱机对其进行采样。您对
    batch\u size
    输入对进行采样,并输出
    batch\u size
    图形对的左元素
    [batch\u size,input\u size]
    。您还可以输出形状
    [batch\u size,]
  • pairs\u left=np.zero((批处理大小、输入大小))
    pairs\u right=np.zero((批处理大小、输入大小))
    标签=np.零((批次大小,1))#例如:[[0.],[1.],[1.],[0.]
    
  • 然后创建与这些输入对应的Tensorflow占位符。在代码中,您将在
    sess.run()
  • pairs\u left\u node=tf.placeholder(tf.float32,[batch\u size,input\u size])
    pairs\u right\u node=tf.placeholder(tf.float32,[批处理大小,输入大小])
    labels\u node=tf.placeholder(tf.float32,[batch\u size,1])
    
  • 现在我们可以对输入执行前馈(假设您的模型是线性模型)
  • W=…#形状[输入大小,特征大小]
    输出左=tf.matmul(成对左节点,W)#形状[批次大小,特征大小]
    输出右=tf.matmul(成对右节点,W)#形状[批次大小,特征大小]
    
  • 最后我们可以计算成对损失。
  • l2_损耗_对=tf.reduce_和(tf.square(输出左-输出右),1)
    正损耗=l2损耗对
    负损耗=tf.nn.relu(余量-l2损耗对)
    最终损失=tf.mul(标签节点,正损失)+tf.mul(1.-标签节点,负损失)
    


    就这样!现在,您可以通过良好的脱机采样对此损失进行优化。

    如果您的距离度量是欧几里德的,您可以使用tf.gather创建一个仅出于感兴趣的向量的矩阵,然后有一种有效的方法来计算所有成对距离,正如它所工作的那样!非常感谢你!顺便说一句,最好使用reLu而不是max。但我使用的其余代码都是原样。谢谢
    margin
    的值应该是多少?@Mithun这是一个可以调整的参数。我不确定现在的最佳实践是什么,但Caffe中的默认值是1.0()
    batchsize = 4
    x1 = np.random.rand(batchsize, dim)
    x2 = np.random.rand(batchsize, dim)
    y = np.array([0,1,1,0])
    
    l = sess.run(loss_, feed_dict={x1_:x1, x2_:x2, y_:y})