- データサイエンティストはあらゆるものをベクトルに変換する。これはAIの言語である
- しかし、コサイン類似度を盲目的に適用すると、誤った方向に導かれる可能性がある
- この記事では、類似度をより意図的に使って、より良い結果を得る方法を説明する。
埋め込み(Embeddings)
- 埋め込みはベクトル化されたデータ表現であり、オブジェクト間の関係を表したり、似た項目を見つけたりするのに非常に有用
- たとえば、"brother" と "sister" は生のIDでは関係がないが、ベクトル化すると意味的な関係を表現できる
- ベクトルは機械学習モデルの入力構造として使われたり、それ自体で類似性探索に活用されたりする
- 大規模言語モデル(LLM)ベースの文埋め込みは、現在もっとも人気のある埋め込み活用例の一つ
- こうした強力な機能には、データセキュリティと意図的な利用に対する責任が伴う
例: コサイン類似度で文を比較する
- 3つの文を比較
- A: "Python can make you rich."
- B: "Python can make you itch."
- C: "Mastering Python can fill your pockets."
- 文字ベースの比較
- 生の文字列を比較すると、AとBは2文字差、AとCは21文字差
- しかし意味的には、AとCのほうがより近い(金銭に関する内容)
- ベクトルベースの比較
- OpenAI text-embedding-3-large を使って、次のような埋め込みベクトルを生成:
- A:
[-0.003738, -0.033263, -0.017596, 0.029024, -0.015251, ...]
- B:
[-0.066795, -0.052274, -0.015973, 0.077706, 0.044226, ...]
- C:
[-0.011167, 0.017812, -0.018655, 0.006625, 0.018506, ...]
- ベクトル次元数: 3072(長いが、品質を落とさずに縮小可能)
- コサイン類似度の計算
- AとC: 0.750(意味的に類似)
- AとB: 0.576(文字列としては類似)
- 結果: 意味は綴りよりも重要な類似性要素である
コサイン類似度とは何か?
- コサイン類似度(cosine similarity)は、2つのベクトル間の角度のコサインを計算して類似性を測る
- ベクトルは高次元空間に存在するため、直感的な幾何学的理解はしばしば当てはまらない
- 数学的には、正規化されたベクトルのドット積(dot product)
- 主な特性:
- 同一ベクトルは1
- ランダムなベクトルは0に近い(高次元での平均化効果)
- 結果の値は -1 から 1 の間にある
- この単純さは誤解を招きやすい
- 値が0〜1の範囲にあるからといって、確率や意味のある尺度だと誤解してはいけない
- 例: 0.6 という値が強い類似性を意味するとは限らない
- 負の値が意味的な反対を示すことはまれにある
- GloVe(
glove.6B.300d)を使って "dog" に似た単語を探すと:
- 近い単語は予想しやすい
- 最も遠い単語はしばしば意味のない結果になる
- コサイン類似度は「ダクトテープ」のように、シンプルかつ高速にさまざまなベクトル比較を可能にする
- しかしそれはあくまでその場しのぎであり、より深い問題を隠してしまうことがある
- 例: 配管をダクトテープで直すようなもので、信頼しづらく恒久的でもない
- コサイン類似度がうまく機能しているように見えることはあるが、失敗したときに原因を特定しづらい
- しばしば場当たり的な解決策に走り、それが新たな問題を生むこともある
コサイン類似度と相関係数の関係
- Pearson の相関係数は、3つの段階で計算される:
- 平均を引いてデータを中心化する
- ベクトルを単位ベクトルに正規化する
- 2つのベクトルのドット積(dot product)を計算する
- ベクトルが中心化・正規化されている場合:
- Pearson の相関係数 = コサイン類似度 = ドット積
- 実用上の使い方
- ペア比較のたびにベクトルを中心化したり正規化したりはしない
- その代わり、前処理しておいてドット積だけを計算する
- コサイン類似度が使えるなら、Pearson の相関係数も同様に使える
類似性指標としてコサイン類似度を使う際の問題
- コサイン類似度を機械学習モデルの学習目標として使うこと自体は、数学的には妥当
- 問題は、コサイン類似度の適合性を超えた領域で生じる:
- モデル学習に使われた損失関数がコサイン類似度ではない場合
- 学習目標が実際のアプリケーション要件と異なる場合
- 一般に、モデルは正規化されていないベクトルで学習される:
- 例: ドット積(dot product)ベースの確率予測とロジスティック損失関数を使用
- 一部のモデルはユークリッド距離を最小化し、同じクラスの項目が近くなるように学習する
- 正規化は数学的性質(結果を -1 から 1 に制限すること)を与えるが、これは「その場しのぎ」でもある
- 役立つこともあれば、そうでないこともある(参考論文)
- コサイン類似度、またはその直接的な関数で学習されたモデルだけが安全に使える
- モデルが明示的にコサイン類似度で学習されていても、「類似性」の定義は依然として曖昧
- 文芸評論家: テーマの共有
- 司書: ジャンル分類
- 読者: 感情的反応
- 組版担当者: ページ数と形式
- コサイン類似度は、多様な定義を単一の数値に単純化してしまうため、誤解を招きやすい
- 例: "espresso" と "cappuccino"
- word2vec はこの2語をほぼ同一とみなす(米国基準)
- しかしイタリアでは同一とはみなされない
コサイン類似度が失敗するケース
- シンプルな例: 鍵を探す質問
- 質問: "What did I do with my keys?"
- 比較対象の文:
- "I left them in my pocket"
- "They are on the table"
- "What did I put my wallet?"
- "What I did to my life?"
- 問題点
- コサイン類似度を使った結果:
- 最も近い文は適切な回答ではなく、別の質問だった("What I did to my life?")
- 意味的関連性ではなく、単純な文構造の類似に依存している
- Python に関する文は類似度がほぼ0に近く、無関係であることは適切に反映される
- 現実世界での限界
- 実際の応用では数千件の文書を扱うことになる
- コンテキストウィンドウを超える大規模データセットでは、さらに大きなノイズに敏感
- データセットが大きくなるほど、類似度スコアは高次元のルーレットゲームのように振る舞う
コサイン類似度の代わりに使えるものは何か?
最も強力なアプローチ
- LLM クエリの活用:
- 2つの項目を比較するために強力な言語モデルを使う
- 例: "Is {sentence_a} a plausible answer to {sentence_b}?"
- LLM を使えば意味のある比較が可能:
- 単純な質問と回答の区別
- JSON のような構造化形式で結果を返すことも可能
- ただし、データセットが大きい場合は非効率でコストも高い
埋め込みの最適化
- タスク別の埋め込み生成:
- 既存モデルの重みを調整する ファインチューニング(Fine-tuning)
- モデルの知識を活用して、新しく焦点の定まった埋め込みを作る 転移学習(Transfer Learning)
- 対称的な類似性:
- 「AとBは似ているか?」という問いをベクトル空間で表現する
- 不要な次元を減らし、関連する特徴だけを残す
- 非対称な類似性:
- 例: 「文書Bは質問Aに対する正しい答えか?」を確率として表現する
- クエリとキーをそれぞれ特化した空間に変換する
プロンプトエンジニアリング
- 文脈設定のためのプロンプト追加:
- 例: "Nationality of {person}" として国籍に関する文脈を強調する
- 単純なプロンプトより、具体的な文を使う:
- "This is a country that has produced many influential historical figures, including {person}"
- 結果の品質は大きく改善するが、完璧ではない
テキストの書き換えと文脈抽出
- 埋め込み前のテキスト前処理:
- 「次のテキストを標準的な英語で200語以内に要約せよ」のような簡単なプロンプトで、表面的な類似性を除去する
- 不要な形式要素(誤字、書式など)を無視して、内容に集中する
- 構造化された文脈の生成:
- 顧客との会話を要約して、明確な要件や問題点を抽出する:
- "会話を要約し、最大10個のMarkdownポイントで書け"
- ページ側も同じ形式に変換することで、より精密なマッチングが可能になる
結論
- さまざまな代替手法はコサイン類似度の欠点を補い、より信頼できる結果をもたらす
- プロジェクトの状況に応じて、適切なアプローチを選んで適用する
要約
- コサイン類似度の限界:
- コサイン類似度は -1 から 1 の値を返すが、これを確率と見なしてはならない
- ほとんどのモデルはコサイン類似度を目標に学習されておらず、その結果は保証されたものではない相関にすぎない
- モデルがコサイン類似度を学習していたとしても、その類似性の定義が自分たちの必要と一致するかを理解する必要がある
- ベクトル類似性を効果的に使う方法:
- データに特化した埋め込みを学習する
- 関連する側面に焦点を当てたプロンプトを設計する
- 埋め込み前にテキストを整理し、標準化する
2件のコメント
素晴らしい資料のまとめですね。
Hacker Newsの意見
コサイン類似度を使うRAGアプリケーションでは、結果を再順位付けするために「semantic re-ranker」や「L2 re-ranking model」を使うのがよい
単語ベクトルは、2つの単語が同じ文脈に現れなくても強く関連しうるという問題を解決する
アメリカではword2vecがespressoとcappuccinoをほぼ同一だと判断するかもしれないが、イタリアではそうではない
コサイン類似度は、ほとんどのディープラーニングベースのセマンティック検索で使われている
2つの項目を比較するには、LLMクエリを直接使うのが最も強力なアプローチである
HyDEは、質問に対する仮想的な回答を生成し、その類似性を比較する方法である
コサイン類似度とtop-k RAGは時代遅れに感じられる
RAGアプローチを試したあとに失望を感じ、モデルが学習中にRAGを実行できるよう構造化すべきだと考えている
3Dグラフィックスや物理学では重要性と正確性が明確だが、機械学習ではベクトル空間があまりに多くのものを表しているため、内積の使用が曖昧に感じられる