【问题标题】:calculating distance matrix of a given row-wise vector matrix计算给定行向量矩阵的距离矩阵
【发布时间】:2013-05-09 20:13:45
【问题描述】:

假设我有一个矩阵 nxm 容纳行向量。我想要一个距离矩阵 nxn 来表示每个向量之间的距离。当我使用 Numpy 时,如何在 Python 中做到这一点。我知道 Scipy 会这样做,但我想弄脏我的手。我已经写了一个余弦相似度函数cos_dist(a,b),其中 a 和 b 是两个不同的向量。现在我需要一个调用函数,它可以有效地为每一对项目执行此操作。我该怎么做?

【问题讨论】:

  • 如果scipy可以,为什么不看一下相关函数的源码呢?它可能已经只依赖于 numpy。
  • 没有安装,我不是 SUDO
  • 你知道相关函数的名称吗?你可以谷歌搜索源代码。
  • 您可能想查看 python virtualenv,它允许您在任何地方安装 python 及其依赖项,而无需拥有sudo 权限。
  • @fgb 谢谢,但目的是编写高效的代码来学习不使用 scipy

标签: matrix numpy distance


【解决方案1】:

下面的代码显示了两个选项来做你所追求的。一个循环遍历数组两次并使用 Python 函数计算 cos_dist。第二个使用向量化的方法和broadcasting 获得相同的结果x1000 更快。

from __future__ import division
import numpy as np

def cos_dist(a, b):
    mod_a = np.sqrt(a.dot(a))
    mod_b = np.sqrt(b.dot(b))
    return a.dot(b) / mod_a / mod_b

a = np.random.rand(100, 4)

# Slow option
def slow_dist(a):
    items = a.shape[0]
    out_slow = np.ones((items,items))
    for j in xrange(items):
        for k in xrange(j+1, items):
            out_slow[j, k] = cos_dist(a[j], a[k])
            out_slow[k, j] = out_slow[j, k]
    return out_slow

# Faster option
from numpy.core.umath_tests import inner1d
def fast_dist(a):
    mod_a = np.sqrt(inner1d(a ,a))
    norm_a = a / mod_a[:, None]
    out_fast = inner1d(norm_a[:, None, :],
                       norm_a[None, :, :])
    return out_fast

以下是时间安排:

In [2]: %timeit slow_dist(a)
10 loops, best of 3: 67.6 ms per loop

In [3]: %timeit fast_dist(a)
10000 loops, best of 3: 60.5 us per loop

In [4]: np.allclose(slow_dist(a), fast_dist(a))
Out[4]: True

【讨论】:

    【解决方案2】:

    你为什么不检查一下 scipy 的 spatial.distance.pdist(),它计算 n 维空间中观测值之间的成对距离,并且有大量的距离函数可供选择?

    由于您没有安装 scipy 并且想使用 numpy 对此进行编码,因此我建议您学习its source code,该链接位于其文档页面的左上角。

    【讨论】:

    • 感谢您的努力,但还不够,因为有很多包装器
    • np。我希望它至少能让你朝着正确的方向开始。