3秒でわかる
2つのベクトルの向きがどれだけ揃っているかを測る指標。長さに左右されないため、文章どうしの意味の近さの判定に広く使われます。
30秒図解
もう少し詳しく
どういうものか
コサイン類似度は、2つのベクトルがなす角度のコサインを取って、向きがどれだけ揃っているかを表す指標です。値は マイナス1 から 1 までで、1に近いほど同じ向き、0なら直交、マイナスなら逆向きを意味します。内積を、それぞれの長さの積で割って求めます。長さで割るため、ベクトルの大きさは結果に影響しません。
なぜ必要か
文章を数値の並びに変換すると、長い文はベクトルも長くなりがちです。距離で比べると、意味が近くても文の長さが違うだけで遠い判定になります。向きだけを見るこの指標なら、長さの差を無視して話題の近さを測れます。検索の並べ替えや、RAGで質問に近い文書を選ぶ処理は、ほぼこの計算で回っています。
具体例
import numpy as np
def cosine(a, b):
return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
q = np.array([1.0, 0.5, 0.0]) # 質問のベクトル
d1 = np.array([2.0, 1.0, 0.0]) # 向きが同じ 長さだけ2倍
d2 = np.array([0.0, 0.0, 3.0]) # 直交
print(cosine(q, d1)) # 1.0
print(cosine(q, d2)) # 0.0多数の文書から近い順に取り出す形にすると、そのまま検索になります。
scores = [(cosine(q, v), i) for i, v in enumerate(docs)]
top = sorted(scores, reverse=True)[:3]つまずきやすいところ
値が高い組み合わせを「意味が同じ」と読んでしまう誤解が多く見られます。測っているのは埋め込みモデルが作った空間での向きの近さであり、否定文と肯定文が高い値で並ぶこともあります。もうひとつ、正規化済みのベクトルどうしなら内積だけで順位は同じになるため、毎回長さを計算するのは無駄です。ベクトルDBで距離指標を選ぶときは、格納時に正規化されているかを確認します。スコアに固定のしきい値を置く運用も難しく、0.8という数字は埋め込みモデルが変われば別の意味になります。しきい値は自分のデータで実際に測り直して決めます。
覚え方
長さを捨てて向きだけ見る指標、と押さえます。だから文書の長短に左右されません。
似た用語との違い
| 指標 | 測るもの |
|---|---|
| コサイン類似度 | ベクトルの向きの近さ |
| ユークリッド距離 | 座標としての離れ具合 |
| 内積 | 向きと長さを合わせた量 |