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
更好吗?有机会聊天吗?我还有一个问题?我很乐意这样做。你知道如何设置吗?问题不是这样:)我找到了聊天的地方,我想知道当线程变长时,系统会做些什么。看起来仍然需要很长时间。我将尝试你的第二种方法,它分为两部分。