導入
文章をベクトルに変換できたら、次はベクトル同士がどれだけ「似ているか」を数値化します。定番の指標がコサイン類似度です。1に近いほどよく似ていて、0に近いほど無関係です。
説明
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer
docs = [
"I love machine learning and data science",
"Deep learning is a part of machine learning",
"The weather today is sunny and warm",
]
vec = TfidfVectorizer().fit(docs)
mat = vec.transform(docs)
query = "machine learning"
q = vec.transform([query])
scores = cosine_similarity(q, mat)[0]
for doc, s in zip(docs, scores):
print(f"{s:.3f} {doc}")
vec.transform([query]) で、質問文 query も docs と同じ語彙・同じ基準でベクトルに変換します。cosine_similarity(q, mat) は、質問ベクトル q と各文書ベクトル mat の向きの近さを計算します。結果を見ると、"machine learning" という語を含む1文目・2文目のスコアが高く、天気の話をしている3文目は低くなっているはずです。これがまさに検索の基本動作――質問に近い文書ほどスコアが高くなる――です。
コサイン類似度が「向き」だけを見て「長さ」を無視する指標だという点も重要です。長い文書ほど単語数が多くなりますが、ベクトルの長さで割って正規化するので、文書が長いか短いかにあまり影響されずに比較できます。
やってみよう
query を "weather" や "data science" に変えて実行し直し、スコアの順位がどう入れ替わるか確かめてみましょう。
演習
scores の中で最もスコアが高い文書を、np.argmax を使って特定し、その文書(docs[インデックス])を print で表示してください。
ヒント2を見る
print(docs[np.argmax(scores)]) のように、そのインデックスで docs から文書を取り出します。