2

我有一个非常大(1.5M x 16M)的稀疏 csr scipy 矩阵 A。我需要计算的是每对行的相似性。我将相似性定义为:

Assume a and b are two rows of matrix A
a = (0, 1, 0, 4)
b = (1, 0, 2, 3)
Similarity (a, b) = 0*1 + 1*0 + 0*2 + 4*3 = 12

为了计算所有成对的行相似度,我使用这个(或余弦相似度):

AT = np.transpose(A)
pairs = A.dot(AT)

现在pairs[i, j] 是所有这样的i 和j 的第i 行和第j 行的相似度。这与行的成对余弦相似度非常相似。因此,如果有一种有效的并行算法可以计算成对余弦相似度,那么它也适用于我。

问题:这个点积非常慢,因为它只使用一个 cpu(我可以访问我服务器上的 64 个 cpu)。

我还可以将 A 和 AT 导出到一个文件并运行任何其他并行执行乘法运算的外部程序,并将结果返回给 Python 程序。

有没有更有效的方法来做这个点积?或并行计算成对相似度?

4

2 回答 2

4

我最终使用了 scikit-learn 的“余弦”距离度量及其 pairwise_distances 函数,它们支持稀疏矩阵并且高度并行化。

sklearn.metrics.pairwise.pairwise_distances(X, Y=None, metric='euclidean', n_jobs=1, **kwds)

我还可以将 A 分成 n 个水平部分,然后使用并行 python 包运行多个乘法,然后将结果水平堆叠。

于 2015-01-28T05:58:47.317 回答
1

我使用sklearn. 它不是并行的,但对于大型矩阵来说相当快。

from scipy.sparse import spdiags
from sklearn.preprocessing import normalize

def get_similarity_by_x_dot_x_greedy_for_memory(sp_matrix):
    sp_matrix = sp_matrix.tocsr()
    matrix = sp_matrix.dot(sp_matrix.T)
    # zero diagonal
    diag = spdiags(-matrix.diagonal(), [0], *matrix.shape, format='csr')
    matrix = matrix + diag
    return matrix

def get_similarity_by_cosine(sp_matrix):
    sp_matrix = normalize(sp_matrix.tocsr())
    return get_similarity_by_x_dot_x_greedy_for_memory(sp_matrix)
于 2015-04-01T08:28:28.380 回答