コサイン類似度とは何か?定義・計算式・実装・応用までを解説する実務ガイド

コサイン類似度とは — 概要

コサイン類似度(cosine similarity)は、ベクトル間の類似度を測る代表的な指標の一つで、情報検索(IR)、自然言語処理(NLP)、推薦システム、クラスタリングなど幅広い分野で使われます。2つのベクトルが成す角度の余弦(コサイン)に基づき、方向の類似性を評価します。特に文書や単語を高次元ベクトルで表現する場合(TF-IDFや埋め込みベクトルEmbeddingなど)に有用です。

数学的定義

ベクトル A, B に対するコサイン類似度は次のように定義されます:

cosθ = (A・B) / (||A|| ||B||)

  • A・B は内積(ドット積)、||A|| は A のノルム(通常はL2ノルム)です。
  • 値域は一般に -1 から 1。ただし、ベクトル要素が非負(例:TF-IDF)であれば 0 から 1 の範囲になります。
  • cosθ = 1 は完全一致(同一方向)、0 は直交(類似性なし)、-1 は反対方向を意味します。

幾何学的な解釈と性質

  • コサイン類似度は「長さ(スケール)ではなく方向」を評価します。すなわち、スカラー倍されたベクトルは同一とみなされます。
  • ノルムで割るため、データの大きさ(例:文書の長さ、ベクトルの大きさ)の影響を除去できます。
  • 単位ベクトルに正規化すると、コサイン類似度はユークリッド距離と簡単な関係があります:cosθ = 1 - 0.5 * ||û - v̂||^2(û, v̂ は正規化済みのベクトル)。これは角度と距離の橋渡しになります。
  • ゼロベクトルに対しては定義できません(ノルムがゼロのため)。

実用的な計算例(数値例)

簡単な数値例で直感をつかみます。

A = [1, 2, 3], B = [2, 0, 1] の場合:

  • 内積 A・B = 1*2 + 2*0 + 3*1 = 5
  • ||A|| = sqrt(1+4+9) = sqrt(14) ≒ 3.7417、 ||B|| = sqrt(4+0+1)=sqrt(5) ≒ 2.2361
  • cosθ = 5 / (sqrt(14)*sqrt(5)) ≒ 0.5976

実装例(Python)

代表的なライブラリを使ったコード例を示します(NumPy と scikit-learn)。

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
A = np.array([1,2,3]).reshape(1,-1)
B = np.array([2,0,1]).reshape(1,-1)
# numpy で直接計算
cos = A.dot(B.T) / (np.linalg.norm(A) * np.linalg.norm(B))
# scikit-learn で複数ベクトルの類似度を一括計算
sim_matrix = cosine_similarity(A, B)
print(cos, sim_matrix)

テキストを TF-IDF に変換して文章間の類似度を測る場合:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
docs = ["私は猫が好きです。", "猫が大好きな人です。"]
vec = TfidfVectorizer().fit_transform(docs)
sim = cosine_similarity(vec[0], vec[1])
print(sim)

主な用途と応用分野

  • 情報検索(検索クエリと文書の類似度評価):TF-IDF ベクトル同士の比較。
  • 自然言語処理:単語埋め込みや文エンベディング(Word2Vec, FastText, BERTなど)を用いた語や文の類似度。
  • 推薦システム:ユーザーベクトルとアイテムベクトルの類似性で推薦候補を並べる。
  • クラスタリングや近傍探索:コサイン類似度を距離尺度としてクラスタリング。
  • 画像検索(特徴ベクトルの類似性)や生体認証の特徴比較など。

利点

  • スケール(ベクトルの長さ)に依存しないため、文書長やスコアの大きさ差の影響を軽減できる。
  • 計算が比較的単純で、各種ライブラリで最適化された実装が豊富。
  • 疎な高次元ベクトル(TF-IDF など)に対しても効率的に扱える。

欠点・注意点(実務上の落とし穴)

  • ゼロベクトルは定義不能:特徴抽出で極端に情報がないとき注意。
  • 方向のみを見るため、情報量(強度)差が意味を持つケースでは適切でないことがある。
  • 高次元空間では「距離集中」や「次元の呪い」が起こりやすく、全ての距離が似通ってしまう現象に注意。
  • スパース表現での特徴重み付け(TF-IDF や正規化)の違いが結果に大きく影響する。
  • 1 - cosine_similarity(いわゆるコサイン距離)は厳密なメトリック(距離関数)の条件を満たさない場合がある。角度を用いた arccos を取ると真正の距離(metric)になり得る。
  • 負の値を取れる埋め込み(中心化や潜在意味空間)では類似度が負になりうる。非負データでは通常 0〜1 に限定される。

パフォーマンスとスケーラビリティの工夫

  • 全文検索や推薦で大量のベクトル比較が必要な場合、全検索(brute-force)は計算コストが高い。Nベクトル同士の比較は O(N^2)。
  • 近似近傍探索(ANN)ライブラリを活用する:Facebook の FAISS、Spotify の Annoy、HNSWlib などは大規模なベクトル類似検索に適する。
  • コサイン類似度は内積に基づくので、ベクトルを正規化しておけば内積=cosineとなり、効率的に高速行列積(BLAS/GPU)で計算できる。
  • 疎行列の取り扱い:scipy.sparse や専用のストレージを使ってメモリ効率を確保。

コサイン類似度と他の類似度指標(比較)

  • ユークリッド距離:ベクトルの差の大きさを見る。大きさも考慮に入れたい場合に有用。正規化済みなら角度情報と結び付く。
  • ジャッカード係数(Jaccard):集合的な重なり具合を見る。バイナリ特徴(存在/非存在)に向く。
  • 相関係数(Pearson):平均による中心化を行い線形関係を見る。スケールや平均の影響を除きたい場合に使用。
  • 選択は用途次第:TF-IDF+コサインは文書類似度で定番、バイナリ属性の類似度はJaccardが合うなど。

実務でよくあるテクニック

  • 特徴重み付け(TF-IDF、sublinear TF、IDF平滑化)でコサイン類似度の意味付けを改善する。
  • 前処理(ストップワード除去、ステミング、正規化)でノイズを減らす。
  • 次元削減(SVD, PCA, UMAP)でノイズや計算コストを削減しつつ類似性を保つ。
  • 閾値の選定:類似度スコアをそのまま閾値化する際はドメインに応じた閾値検証が必要。

よくある誤解

  • 「コサイン類似度が高い=意味的に同じ」は常に成立しない。特徴表現(ベクトル化)の品質に依存します。
  • 「1 - cosine_similarity が真の距離」は必ずしも正しくない。三角不等式など距離の公理に注意。

まとめ

コサイン類似度は、方向に着目してベクトル間の類似性を測るシンプルかつ強力な手法です。テキスト検索や埋め込みベースの類似検索で広く使われ、スケールの影響を排除する点が特に有利です。一方で、前処理や特徴重み付け、巨大データでの近傍探索の工夫、そして指標の意味を誤解しないことが重要です。用途に応じて他の距離や指標と比較し、適切な実装(正規化、ANNの利用、ライブラリ選定)を行えば、実務で非常に有用なツールになります。

参考文献