Python 如何并行化scipy余弦相似度计算

Python 如何并行化scipy余弦相似度计算,python,multithreading,scipy,multiprocessing,cosine-similarity,Python,Multithreading,Scipy,Multiprocessing,Cosine Similarity,我通过读取目录中的大量文件生成了一个大数据帧。我已经设法并行化了在解析中读取文件的部分。我获取这些数据并为下一步生成数据帧。这就是计算相似度矩阵 现在,我试图计算数据帧行之间的余弦相似性。因为它是一个大数据帧,所以需要很长的时间(小时)才能运行。我怎样才能并行化这个过程 下面是我当前计算余弦相似性的代码,该代码在单个线程上运行: df = df.fillna(0) data = df.values m, k = data.shape mat = np.zeros((m, m)) """ s

我通过读取目录中的大量文件生成了一个大数据帧。我已经设法并行化了在解析中读取文件的部分。我获取这些数据并为下一步生成数据帧。这就是计算相似度矩阵

现在,我试图计算数据帧行之间的余弦相似性。因为它是一个大数据帧,所以需要很长的时间(小时)才能运行。我怎样才能并行化这个过程

下面是我当前计算余弦相似性的代码,该代码在单个线程上运行:

df = df.fillna(0)

data = df.values
m, k = data.shape

mat = np.zeros((m, m))

"""
scipy cosine similarity is between 0-2 instead of -1 to 1 
in that case 1 is 0 and 2 is -1
"""
for i in xrange(m):
    for j in xrange(m):
        if i != j:
            mat[i][j] = 1 - cosine(data[i,:], data[j,:])
        else:
            mat[i][j] = 1. # 0 if we don't do 1-cosine()

首先,我假设您的
cosine
scipy.space.distance.cosine
,其关键计算是:

dist = 1.0 - np.dot(u, v) / (norm(u) * norm(v))
看来我可以用以下方法代替你的双回路:

data1 = data/np.linalg.norm(data,axis=1)[:,None]
mat1 = np.einsum('ik,jk->ij', data1, data1)
也就是说,在开始时将数据标准化一次,而不是在每个节点。然后使用
einsum
计算整套
dot
产品

对于一个小测试用例(m,k=4,3),这比双循环快25倍

注意:我只针对一个小型
数据
数组测试了您的答案

scipy.spactial.distance.norm
cosine
有一些我没有执行的检查

einsum
虽然在中等大小的数组上可以快速完成这类任务,但在使用较大的数组时可能会陷入困境,并且在逐个元素
dot
之前会遇到内存错误。而且底层的
dot
库可能会更好地调整以处理多核机器

但是,即使
数据
太大,一次调用
einsum
也无法处理,您也可以将计算分解为块,例如

mat[n1:n2,m1:m2] = np.einsum('ik,jk->ij', data1[n1:n2,:], data1[m1:m2,:])

我想给你指出

注意pool.map(函数,iterable)


然后构建三角形位置元组集,编写适当的函数并启动。

您是否已经尝试过
squareform(pdist(data,'cosine'))
?也可以从
scipy.spatial.distance
。它应该比双for-loop快得多。这个:
scipy.spatial.distance.cosine
?@hpaulj是的,我用的是
scipy.spatial.distance.cosine
你认为
sklearn
更好吗?有机会聊天吗?我还有一个问题?我很乐意这样做。你知道如何设置吗?问题不是这样:)我找到了聊天的地方,我想知道当线程变长时,系统会做些什么。看起来仍然需要很长时间。我将尝试你的第二种方法,它分为两部分。