Python 3.x 求两个巨大CSR矩阵行之间的欧氏距离

Python 3.x 求两个巨大CSR矩阵行之间的欧氏距离,python-3.x,sparse-matrix,knn,euclidean-distance,csr,Python 3.x,Sparse Matrix,Knn,Euclidean Distance,Csr,我有两个稀疏矩阵,A和B。A是120000*5000,B是30000*5000。我需要找到B中每一行与A中所有行之间的欧几里德距离,然后找到A中与B中所选行之间距离最小的5行。因为这是一个非常大的数据,我正在使用CSR,否则我会出现内存错误。很明显,对于A中的每一行,它计算(x_b-x_A)^2 5000次,并将它们相加,然后得到一个sqrt。这个过程需要很长时间,大概11天!有什么方法可以让我更有效地完成这项工作吗?我只需要到B中每行距离最小的5行 我正在实现K-最近邻,A是我的训练集,B是我

我有两个稀疏矩阵,A和B。A是120000*5000,B是30000*5000。我需要找到B中每一行与A中所有行之间的欧几里德距离,然后找到A中与B中所选行之间距离最小的5行。因为这是一个非常大的数据,我正在使用CSR,否则我会出现内存错误。很明显,对于A中的每一行,它计算(x_b-x_A)^2 5000次,并将它们相加,然后得到一个sqrt。这个过程需要很长时间,大概11天!有什么方法可以让我更有效地完成这项工作吗?我只需要到B中每行距离最小的5行


我正在实现K-最近邻,A是我的训练集,B是我的测试集。

我不知道是否可以“矢量化”该代码,以便它可以在本机代码而不是Python中运行。加速numpy和scipy的诀窍就是要做到这一点

如果您可以在1GHz的CPU中以本机代码运行该代码,并为时钟循环使用1条FP指令,您将在不到10小时的时间内完成。 (5000*2*30000*120000)/1024**3

将其提高到1.5Ghz x 2个CPU物理内核x 4路SIMD指令和乘法+运算(英特尔AVX扩展,可用于大多数CPU),您可以在一台中等规模的core i5机器上以2 x 100%的速度将数字压缩到一小时。但是,这需要在本机代码中进行完整的SIMD优化——这绝非一项琐碎的任务(尽管,如果您决定走这条路,关于S.O.的进一步问题可能会得到人们的帮助,让他们在SIMD编码中沾沾自喜:-)——例如,使用cython将C中的代码与Scipy接口并不困难(您只需使用该部件即可达到上述10小时的数值)

现在…至于算法优化,请保持Python:-)
事实上,您不需要完全计算A中所有行的距离-您只需要保留一个低5行的排序列表-任何时候平方和的累积大于第5行(到目前为止),您只需中止该行的计算

您可以使用Python的heapq操作:

import heapq
import math

def get_closer_rows(b_row, a):
    result = [(float("+inf"), None)  * 5]
    for i, a_row in enumerate(a):
        distance_sq = 0
        count = 0
        for element_a, element_b in zip(a_row, b_row):
            distance_sq += element_a * element_b
            if not count % 64 and distance_sq > result[4][0]:
                break
            count += 1
        else:
            heapq.heappush(result, (distance, i))
            result[:] = result[:5]
    return [math.sqrt(r) for r in result]

closer_rows_to_b = []
for row in b:
    closer_rows_to_b.append(get_closer_rows(row, a))
注意辅助的“计数”以避免昂贵的检索和比较所有乘法的值。 现在,如果您可以使用pypy而不是普通的Python来运行此代码,我相信它可以从JITting中获得全部好处,并且如果您使用纯Python(即:非numpy/scipy矢量化代码)来运行此代码,您可以比以前得到显著的改进