我通过读取目录中的大量文件来生成大型数据框。我设法并行化了解析文件的部分。我获取该数据并为下一步生成数据帧。这是计算相似度矩阵。
现在,我正在尝试计算数据帧行之间的余弦相似度。由于它是一个大型数据框,因此需要很长时间(小时)才能运行。如何并行化此过程。
这是我目前计算在单线程上运行的余弦相似度的代码:
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()
答案 0 :(得分:1)
首先,我假设您的cosine
是scipy.spatial.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)
即,在开始时将data
标准化一次,而不是在每个节点处标准化。然后使用einsum
计算整套dot
产品。
对于小测试用例(m,k = 4,3),这比双循环快25倍。
警告:我只测试了一个小data
数组的答案。
scipy.spactial.distance.norm
和cosine
有一些我尚未实施的检查。
einsum
虽然在适度大小的数组上快速处理这类事情,但是可能会遇到较大的数组,并且会在元素dot
之前遇到内存错误。并且可以更好地调整底层dot
库以处理多核机器。
但即使data
过大而无法通过调用einsum
来处理,也可以将计算分解为块,例如
mat[n1:n2,m1:m2] = np.einsum('ik,jk->ij', data1[n1:n2,:], data1[m1:m2,:])
答案 1 :(得分:0)
我想指出你https://docs.python.org/2/library/multiprocessing.html
的方向记下pool.map(函数,可迭代)
然后构建一组三角形位置元组,编写相应的函数并消失。