【问题标题】:Euclidean distance vs cosine distance in sparse vectors - How come Euclidean performs better?稀疏向量中的欧几里得距离与余弦距离 - 为什么欧几里得表现更好?
【发布时间】:2018-02-10 17:12:48
【问题描述】:

我有一个非常稀疏向量 df(超过 95% 的零)的数据集,我正在测量另一个稀疏向量 sample 之间的距离。

现在由于我处理的是非常稀疏的向量,我假设余弦距离的计算速度比欧几里得快得多,但事实似乎并非如此。

这是正常行为吗?还是我做错了什么?或者说余弦距离在稀疏向量中更有效,这甚至不是真的?

all_distances 包含多种距离,但我们这里只讨论scipy.spatial.distance.euclideanscipy.spatial.distance.cosine

我的代码

for d_name, d_func in all_distances.items():

    tot_time = []
    for i in range(100):
        start_time = time()
        df['distance'] = df.apply(d_func, axis=1, args=(sample,))
        df.sort_values(by='distance', ascending=True, inplace=True)
        df.drop('distance', axis=1, inplace=True)
        df = df.reset_index(drop=True)
        tot_time.append(time() - start_time)
    
     print("Mean time for {}: {}s".format(d_name, round(mean(tot_time), 4)))

结果:

余弦平均时间:0.8034s

欧几里得平均时间:0.708s

【问题讨论】:

  • 解释为什么你认为应该更快(只是因为稀疏)。您似乎没有使用 scipy sparse 矩阵。
  • 看公式docs.scipy.org/doc/scipy/reference/generated/… 我可以看到两个向量中的任何一个都为零的元素不需要计算,所以我相信余弦的迭代应该快得多,因为 95+ 百分比同一索引中的两个元素中的任何一个都为零。
  • 不,我没有使用 scipy.sparse 我实际上从未接触过它,如果它可以提高余弦性能,我很乐意听到我在这个用例中使用它
  • 测试零也需要时间;函数通常不会添加该步骤,除非它们期望稀疏输入。即使这样,最好提前告诉他们要跳过哪些计算。 Pandas 有自己的稀疏代码。
  • 那么我将如何处理稀疏向量中的不同距离函数?

标签: python performance math scipy mathematical-optimization


【解决方案1】:

余弦相似度需要两个输入向量的范数,以及它们之间的点积:

cos(theta) = dot(a,b) / (norm(a) * norm(b))

因此,即使点积仅在 a[i]b[i] 均非零时累加,您仍然需要累加 ab 的范数,这本身与累加的工作量差不多欧几里得距离。

无论如何,大部分工作都将通过稀疏向量进行迭代——请注意,它们之间的性能实际上并没有太大差异。但是,对差异的合理解释是余弦计算需要做更多的算术。

【讨论】:

  • 当然有一种方法可以避免计算规范,如果点为零.. 否?
  • 没错,但这不会为您节省太多时间——因为大部分工作都是遍历稀疏向量。然后,如果点 为零,您将需要再次遍历稀疏向量以计算范数,这几乎会使所需时间增加一倍。如果你写的是scipy.spatial.distance.cosine,你会接受这个赌注吗?
  • 显然不是,但是查看他们的文档,我在稀疏的相关模块中找不到任何东西。这有点离题了,但是任何已知的稀疏向量数学解决方案?我的意思是,我看到了 scipy 稀疏库,距离非常基本,但它不存在
猜你喜欢
  • 2013-03-02
  • 2015-07-15
  • 2014-02-04
  • 1970-01-01
  • 2014-03-07
  • 2010-12-15
  • 2013-10-24
相关资源
最近更新 更多