[解決済み】2つのテキスト文書間の類似性を計算する方法は?
質問
私はNLPプロジェクトに携わっています。プログラミング言語は問いません(ただし、Pythonを希望します)。
2つの文書を取り出して、どの程度似ているかを判断したいのですが。
どのように解決するのですか?
一般的な方法は、文書をTF-IDFベクトルに変換し、その間の余弦類似度を計算することである。情報検索(IR)の教科書には必ず載っています。特に参照。 情報検索入門 は、無料でオンライン公開されています。
一対の類似性を計算する
TF-IDF(および類似のテキスト変換)は、Pythonパッケージで実装されています。 ジェンシム と scikit-learn . 後者のパッケージでは,cosine の類似性を計算するのは次のように簡単です.
from sklearn.feature_extraction.text import TfidfVectorizer
documents = [open(f).read() for f in text_files]
tfidf = TfidfVectorizer().fit_transform(documents)
# no need to normalize, since Vectorizer will return normalized tf-idf
pairwise_similarity = tfidf * tfidf.T
または、ドキュメントがプレーンな文字列である場合。
>>> corpus = ["I'd like an apple",
... "An apple a day keeps the doctor away",
... "Never compare an apple to an orange",
... "I prefer scikit-learn to Orange",
... "The scikit-learn docs are Orange and Blue"]
>>> vect = TfidfVectorizer(min_df=1, stop_words="english")
>>> tfidf = vect.fit_transform(corpus)
>>> pairwise_similarity = tfidf * tfidf.T
しかし、この種のタスクには Gensim の方がより多くのオプションがあるかもしれません。
参照 この質問 .
[免責事項: 私は scikit-learn TF-IDF の実装に携わりました].
結果の解釈
上から
pairwise_similarity
はScipyの
スパースマトリックス
は正方形で、行と列の数はコーパスの文書数と同じである。
>>> pairwise_similarity
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 17 stored elements in Compressed Sparse Row format>
スパース配列をNumPyの配列に変換するには、次のようにします。
.toarray()
または
.A
:
>>> pairwise_similarity.toarray()
array([[1. , 0.17668795, 0.27056873, 0. , 0. ],
[0.17668795, 1. , 0.15439436, 0. , 0. ],
[0.27056873, 0.15439436, 1. , 0.19635649, 0.16815247],
[0. , 0. , 0.19635649, 1. , 0.54499756],
[0. , 0. , 0.16815247, 0.54499756, 1. ]])
最終的な文書、"The scikit-learn docs are Orange and Blue"に最も近い文書を探したいとします。 このドキュメントのインデックス4は
corpus
. 最も似ているドキュメントのインデックスは、次のようにして見つけることができます。
その行の argmax を取ります。しかし、まず各文書のそれ自身に対する類似度を表す 1 をマスクする必要があります。
. 後者は、以下の方法で行うことができます。
np.fill_diagonal()
で、前者は
np.nanargmax()
:
>>> import numpy as np
>>> arr = pairwise_similarity.toarray()
>>> np.fill_diagonal(arr, np.nan)
>>> input_doc = "The scikit-learn docs are Orange and Blue"
>>> input_idx = corpus.index(input_doc)
>>> input_idx
4
>>> result_idx = np.nanargmax(arr[input_idx])
>>> corpus[result_idx]
'I prefer scikit-learn to Orange'
注意:疎な行列を使う目的は、大きなコーパスと語彙のために(かなりの量の)スペースを節約することです。 NumPyの配列に変換する代わりに、こうすることもできます。
>>> n, _ = pairwise_similarity.shape
>>> pairwise_similarity[np.arange(n), np.arange(n)] = -1.0
>>> pairwise_similarity[input_idx].argmax()
3
関連
-
[解決済み] Stupid Backoffの実装の明確化
-
TypeError: zip 引数 #1 は反復をサポートしなければならない 解決策。
-
BERT事前学習に基づく中国語名前付き固有表現認識のTensorFlow実装
-
pyhanlpレポートについて FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm' エラー解決法
-
[解決済み】2つのテキスト文書間の類似性を計算する方法は?
-
[解決済み] lemmatizationとstemmingの違いは何ですか?
-
[解決済み] 単語中の音節を検出する
-
[解決済み] Did you mean "を実装するには?重複
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Stupid Backoffの実装の明確化
-
TypeError: zip 引数 #1 は反復をサポートしなければならない 解決策。
-
BERT事前学習に基づく中国語名前付き固有表現認識のTensorFlow実装
-
pyhanlpレポートについて FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/jvm' エラー解決法
-
[解決済み】2つのテキスト文書間の類似性を計算する方法は?
-
[解決済み] lemmatizationとstemmingの違いは何ですか?
-
[解決済み] 単語中の音節を検出する
-
[解決済み] Did you mean "を実装するには?重複