77

疎行列のリストが与えられた場合、行列の各列 (または行) 間のコサイン類似度を計算する最良の方法は何ですか? n-choose-two を 2 回繰り返すのは避けたいと思います。

入力行列は次のとおりです。

A= 
[0 1 0 0 1
 0 0 1 1 1
 1 1 0 1 0]

スパース表現は次のとおりです。

A = 
0, 1
0, 4
1, 2
1, 3
1, 4
2, 0
2, 1
2, 3

Python では、行列入力形式を使用するのは簡単です。

import numpy as np
from sklearn.metrics import pairwise_distances
from scipy.spatial.distance import cosine

A = np.array(
[[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[1, 1, 0, 1, 0]])

dist_out = 1-pairwise_distances(A, metric="cosine")
dist_out

与えます:

array([[ 1.        ,  0.40824829,  0.40824829],
       [ 0.40824829,  1.        ,  0.33333333],
       [ 0.40824829,  0.33333333,  1.        ]])

完全な行列の入力では問題ありませんが、(行列のサイズとスパース性のため) スパース表現から始めたいと思います。これをどのように達成するのが最善かについてのアイデアはありますか? 前もって感謝します。

4

9 に答える 9

2

Vaali のソリューションからの構築:

def sparse_cosine_similarity(sparse_matrix):
    out = (sparse_matrix.copy() if type(sparse_matrix) is csr_matrix else
           sparse_matrix.tocsr())
    squared = out.multiply(out)
    sqrt_sum_squared_rows = np.array(np.sqrt(squared.sum(axis=1)))[:, 0]
    row_indices, col_indices = out.nonzero()
    out.data /= sqrt_sum_squared_rows[row_indices]
    return out.dot(out.T)

これは、スパース マトリックス (できれば csr_matrix) を取り、csr_matrix を返します。かなり最小限のメモリ オーバーヘッドで疎な計算を使用して、より集中的な部分を実行する必要があります。ただし、広範囲にテストしていないため、注意してください(更新:テストとベンチマークを行ったので、このソリューションに自信を持っています)

また、実際にどちらのソリューションが優れているかわからない場合に備えて、Waylonのソリューションのスパースバージョンを次に示します。

def sparse_cosine_similarity_b(sparse_matrix):
    input_csr_matrix = sparse_matrix.tocsr()
    similarity = input_csr_matrix * input_csr_matrix.T
    square_mag = similarity.diagonal()
    inv_square_mag = 1 / square_mag
    inv_square_mag[np.isinf(inv_square_mag)] = 0
    inv_mag = np.sqrt(inv_square_mag)
    return similarity.multiply(inv_mag).T.multiply(inv_mag)

どちらのソリューションも sklearn.metrics.pairwise.cosine_similarity と同等のようです

:-D

アップデート:

今、私は既存の Cython 実装に対して両方のソリューションをテストしました: https://github.com/davidmashburn/sparse_dot/blob/master/test/benchmarks_v3_output_table.txt そして、ほとんどの場合、最初のアルゴリズムが 3 つの中で最高のパフォーマンスを発揮するようです。 .

于 2018-08-30T19:45:05.520 に答える
1

scipy.sparseをチェックしてください。通常の行列を使用する方法と同じように、これらの疎行列に操作を適用できます。

于 2013-07-13T05:41:14.417 に答える