两个二元张量之间的成对欧几里德距离

时间:2018-03-28 17:18:53

标签: python tensorflow linear-algebra euclidean-distance

我正在尝试计算Tensorflow中两个二进制区域/体积/超体积中所有点之间的成对距离。

E.g。在2D中,区域被定义为具有1和0的二进制张量:

input1 = tf.constant(np.array([[1,0,0], [0,1,0], [0,0,1]))
input2 = tf.constant(np.array([[0,1,0], [0,0,1], [0,1,0]))

input1有3分,input2有2分。

到目前为止,我已设法将二进制张量转换为空间坐标数组:

coord1 = tf.where(tf.cast(input1, tf.bool))
coord2 = tf.where(tf.cast(input2, tf.bool))

其中,coord1将具有shape=(3,2),而coord2将具有shape=(2,2)。第一个维度是指点数,第二个维度是指空间坐标(在本例中为2D)。

我想要的结果是shape=(6, )的张量,其中区域中所有点之间的成对欧几里德距离。 示例(距离的顺序可能不正确):

output = [1, sqrt(5), 1, 1, sqrt(5), 1]

由于TensorFlow对于循环不是很好而且在我的实际应用中,每个张量中的点数是未知的,我想我可能在这里缺少一些线性代数。

2 个答案:

答案 0 :(得分:1)

我对Tensorflow不熟悉,但我从阅读this的理解是,底层NumPy数组应该很容易从您的数据中提取。所以我将提供一个解决方案,展示如何计算3x2和2x2 NumPy阵列之间的成对欧几里德距离,并希望它有所帮助。

生成与数据形状相同的随机NumPy数组:

from cloudant.client import Cloudant
from cloudant.error import CloudantException
from cloudant.result import Result, ResultByKey
import cloudant
import pandas as pd
import json

serviceUsername = "x"
servicePassword = "y"
serviceURL = "z"
client = Cloudant(serviceUsername, servicePassword, url=serviceURL)
client.connect()

database1 = client['comfort']
userID= input("what is your user ID?")

for item in database1:
  if userID == 'user_id':
    print(item)

导入相关的SciPy函数并运行:

what is your user ID?ss


> HTTPError                                 Traceback (most recent call
> last)
>     <ipython-input-7-98e9b2d333f5> in <module>()
>           4 userID= input("what is your user ID?")
>           5 
>     ----> 6 for item in database1:
>           7     if userID == 'user_id':
>           8         print(item)
>     
>     ~\Anaconda3\lib\site-packages\cloudant\database.py in __iter__(self, remote)
>         634                                                   # next_startkey
>         635                     include_docs=True,
>     --> 636                     startkey=next_startkey
>         637                 ).get('rows', [])
>         638 
>     
>     ~\Anaconda3\lib\site-packages\cloudant\database.py in all_docs(self, **kwargs)
>         391                         '/'.join([self.database_url, '_all_docs']),
>         392                         self.client.encoder,
>     --> 393                         **kwargs)
>         394         return resp.json()
>         395 
>     
>     ~\Anaconda3\lib\site-packages\cloudant\_common_util.py in get_docs(r_session, url, encoder, headers, **params)
>         263     else:
>         264         resp = r_session.get(url, headers=headers, params=f_params)
>     --> 265     resp.raise_for_status()
>         266     return resp
>         267 
>     
>     ~\Anaconda3\lib\site-packages\requests\models.py in raise_for_status(self)
>         933 
>         934         if http_error_msg:
>     --> 935             raise HTTPError(http_error_msg, response=self)
>         936 
>         937     def close(self):
>     
>     HTTPError: 429 Client Error: Too Many Requests too_many_requests You've exceeded your current limit of 5 requests per second for query
> class. Please try later. for url:
> https://2b5a4b.......

这将返回一个3x2数组,但您可以使用coord1 = np.random.random((3, 2)) coord2 = np.random.random((2, 2)) 来获得所需的长度为6的1维数组。

答案 1 :(得分:0)

我只用矩阵乘法和换位得出答案。这利用了距离可以用内积(d^2 = x^2 + y^2 - 2xy)表示的事实:

input1 = np.array([[1,0,0],[0,1,0],[0,0,1]])
input2 = np.array([[1,1,0],[0,0,1],[1,0,0]])
c1 = tf.cast(tf.where(tf.cast(input1, tf.bool)), tf.float32)
c2 = tf.cast(tf.where(tf.cast(input2, tf.bool)), tf.float32)

distances = tf.sqrt(-2 * tf.matmul(c1, tf.transpose(c2)) + tf.reduce_sum(tf.square(c2), axis=1)
                + tf.expand_dims(tf.reduce_sum(tf.square(c1), axis=1), axis=1))

with tf.Session() as sess:
     d = sess.run(distances)

由于Tensorflow默认广播,因此阵列具有不同的尺寸并不重要。

希望它对某人有帮助。