1

前処理および変換(BOW、TF-IDF)データの後、データセットの各要素とのコサイン類似度を計算する必要があります。現在、私はこれを実行します。この例ではscikit-learnを使用してコサインの類似性を効率的に計算する

cs_title = [cosine_similarity(a, b) for a in tr_title for b in tr_title] 
cs_abstract = [cosine_similarity(a, b) for a in tr_abstract for b in tr_abstract] 
cs_mesh = [cosine_similarity(a, b) for a in pre_mesh for b in pre_mesh] 
cs_pt = [cosine_similarity(a, b) for a in pre_pt for b in pre_pt] 

を、各入力変数、例えばtr_titleは、scipyのダウンロードスパース行列です。ただし、このコードでは、が非常にゆっくりと実行されます。より迅速に実行できるようにコードを最適化するために何ができますか?

答えて

3

パフォーマンスを向上させるには、リスト内包表記をベクトル化コードで置き換える必要があります。以下のスニペットに示すように、これは簡単にnumpyののpdistsquareformを介して実装することができます。

import numpy as np 
from sklearn.feature_extraction.text import CountVectorizer 
from scipy.spatial.distance import pdist, squareform 

titles = [ 
    'A New Hope', 
    'The Empire Strikes Back', 
    'Return of the Jedi', 
    'The Phantom Menace', 
    'Attack of the Clones', 
    'Revenge of the Sith', 
    'The Force Awakens', 
    'A Star Wars Story', 
    'The Last Jedi', 
    ] 

vectorizer = CountVectorizer() 
X = vectorizer.fit_transform(titles) 
cs_title = squareform(pdist(X.toarray(), 'cosine')) 

デモX.toarray().shape利回り(9L, 21L)が原因で上記の玩具の例では9つのタイトルがあること

In [87]: X 
Out[87]: 
<9x21 sparse matrix of type '<type 'numpy.int64'>' 
    with 30 stored elements in Compressed Sparse Row format> 

In [88]: X.toarray()   
Out[88]: 
array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0], 
     [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0], 
     [0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1], 
     [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]], dtype=int64) 

In [89]: vectorizer.get_feature_names() 
Out[89]: 
[u'attack', 
u'awakens', 
u'back', 
u'clones', 
u'empire', 
u'force', 
u'hope', 
u'jedi', 
u'last', 
u'menace', 
u'new', 
u'of', 
u'phantom', 
u'return', 
u'revenge', 
u'sith', 
u'star', 
u'story', 
u'strikes', 
u'the', 
u'wars'] 

In [90]: np.set_printoptions(precision=2) 

In [91]: print(cs_title) 
[[ 0. 1. 1. 1. 1. 1. 1. 1. 1. ] 
[ 1. 0. 0.75 0.71 0.75 0.75 0.71 1. 0.71] 
[ 1. 0.75 0. 0.71 0.5 0.5 0.71 1. 0.42] 
[ 1. 0.71 0.71 0. 0.71 0.71 0.67 1. 0.67] 
[ 1. 0.75 0.5 0.71 0. 0.5 0.71 1. 0.71] 
[ 1. 0.75 0.5 0.71 0.5 0. 0.71 1. 0.71] 
[ 1. 0.71 0.71 0.67 0.71 0.71 0. 1. 0.67] 
[ 1. 1. 1. 1. 1. 1. 1. 0. 1. ] 
[ 1. 0.71 0.42 0.67 0.71 0.71 0.67 1. 0. ]] 

お知らせおよび21の異なる語であり、cs_title9 by 9の配列である。

1

あなたのアカウントに2つのベクトルのコサイン類似度の二つの特徴を取って半分以上により、計算のそれぞれのための労力を軽減することができます

  1. 自体のベクトルのコサイン類似度が1です。
  2. ベクトルYとベクトルXのコサイン類似度は、ベクトルX持つベクトルYのコサイン類似度と同じです。

したがって、対角またはそれより下の要素を計算します。

編集:これを計算する方法は次のとおりです。特にcsは、類似係数の実際の計算に代わるダミー関数にすぎないことに注意してください。

title1 = 'A four word title' 
title2 = 'A five word title' 
title3 = 'A six word title' 
title4 = 'A seven word title' 

titles = [title1, title2, title3, title4] 
N = len(titles) 

import numpy as np 

similarity_matrix = np.array(N**2*[0],np.float).reshape(N,N) 

cs = lambda a,b: 10*a+b # just a 'pretend' calculation of the coefficient 

for m in range(N): 
    similarity_matrix [m,m] = 1 
    for n in range(m+1,N): 
     similarity_matrix [m,n] = cs(m,n) 
     similarity_matrix [n,m] = similarity_matrix [m,n] 

print (similarity_matrix) 

結果は次のとおりです。

[[ 1. 1. 2. 3.] 
[ 1. 1. 12. 13.] 
[ 2. 12. 1. 23.] 
[ 3. 13. 23. 1.]] 
+0

私はこれを考慮しましたが、同等の出力を製品に実装する方法がわかりませんでしたか? – user7347576

+0

あなたの質問に含まれているコードは、例えば 'cs_pt = [pre_pt in a pre_pt for a pre_pt]には、ベクトルを生成します。しかしコサインの類似点の集合ごとに行列を求めたくないですか? –

+0

ええ、それは望ましい出力でした... – user7347576

関連する問題