实现三维tensor计算欧式距离

2019-06-27  本文已影响0人  全村希望gone

前言

在网上找不到实现三维tensor计算欧式距离的代码,tensorflow中也没有封装,于是自己写,写得时候有点曲折,花了两个小时,主要是因为三维tensor的维度问题,稍不注意便出错,还需要多用debug和print才能看懂,还有二维转三维,不得不说tf.expand_ndims真好用。Talk is cheap,show you the code.


补充

刚刚在项目中用了一下,发现根本不使用,如果你的tensor非常大,batch很多,那么运行起来会非常非常慢,但是稍小一点的tensor还是可以用的。

代码

import tensorflow as tf

a = tf.constant([[[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]],
                 [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]], dtype=tf.float32)


def euclidean_metric(embeddings):
    width = embeddings.shape.as_list()[1]
    # 容器,便于拼接之后的向量
    output = tf.sqrt(tf.reduce_sum(tf.square(embeddings[:, 0] - embeddings[:, 0]), axis=1, keepdims=True))
    # 两次循环是因为每个向量与其它向量都有一个欧式距离,而且欧氏距离矩阵的大小就是width*width
    for i in range(width):
        for j in range(width):
            # 计算距离
            distance = tf.sqrt(tf.reduce_sum(tf.square(embeddings[:, i] - embeddings[:, j]), axis=1, keepdims=True))
            # 在行的方向上拼接
            output = tf.concat([output, distance], 1)
    # 将最开始的容器去掉
    output_slice = tf.slice(output, [0, 1], [-1, width * width])
    # 升维,与原embeddings维度一致,方便后面reshape
    output_expand = tf.expand_dims(output_slice, -1)
    output_reshape = tf.reshape(output_expand, [-1, width, width])
    return output_reshape


with tf.Session() as sess:
    b = euclidean_metric(a)
    print(sess.run(b))import tensorflow as tf

a = tf.constant([[[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]],
                 [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]], dtype=tf.float32)

输出结果

[[[0.       2.236068 4.472136]
  [2.236068 0.       2.236068]
  [4.472136 2.236068 0.      ]]

 [[0.       2.236068 4.472136]
  [2.236068 0.       2.236068]
  [4.472136 2.236068 0.      ]]]
上一篇 下一篇

猜你喜欢

热点阅读