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 の類似度です。これは、行のペアワイズ コサイン類似度に非常に似ています。したがって、ペアワイズコサイン類似度を計算する効率的な並列アルゴリズムがあれば、それは私にとってもうまくいくでしょう。

問題: この内積は 1 つの 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 に答える