NetflixやSpotifyの「あなたにおすすめ」、ChatGPTの賢い回答、Google検索の精度の高さ…これらのAI技術の背後には「コサイン類似度」という数学的手法が使われていることをご存知でしょうか?
「コサイン類似度って何?数学は苦手なんだけど…」「AIでなぜ重要なの?」そんな疑問を持つ方も多いかもしれません。実は、コサイン類似度はAIにおける「類似性判定」の中核技術であり、現代のAIサービスになくてはならない存在なのです。
この記事では、数学が苦手な方でも理解できるよう、図解や具体例を交えながら、コサイン類似度の基本概念からAIでの実際の活用法、そしてPythonでの実装まで、段階的に解説していきます。
コサイン類似度って何?身近な例で理解しよう
「似ている」を数値化する技術
コサイン類似度とは、2つのデータがどれだけ「似ているか」を0から1の数値で表現する手法です。
身近な例で考えてみましょう:
🎬 映画の好みの類似度
・Aさん:アクション映画をよく見る、恋愛映画はたまに見る
・Bさん:アクション映画をよく見る、恋愛映画もよく見る
・Cさん:恋愛映画をよく見る、アクション映画は見ない
この場合、AさんとBさんは「アクション好き」という共通点があるため類似度が高く、AさんとCさんは好みが正反対なので類似度が低くなります。
ベクトルの角度で類似性を測る概念
コサイン類似度の特徴は、「方向性」に注目することです:
📊 2次元で考える例
・ユーザーA:アクション映画 = 4点、恋愛映画 = 2点
・ユーザーB:アクション映画 = 8点、恋愛映画 = 4点
数値は異なりますが、「アクション:恋愛 = 2:1」の比率が同じです。コサイン類似度では、この比率(方向性)が重要で、2人の類似度は1.0(完全に類似)となります。
日常生活での類似性判定との違い
従来の類似性判定では、数値の差を重視しがちです:
❌ 単純な差による判定
・ユーザーA:[4, 2] vs ユーザーB:[8, 4]
・差:4ずつ違うので「似ていない」
✅ コサイン類似度による判定
・方向性(比率):2:1 vs 2:1
・判定:「嗜好の方向性が同じなので似ている」
この特徴により、「量は違うが傾向は同じ」というパターンを正確に捉えることができるのです。
なぜAIでコサイン類似度が重要なのか?3つの理由
理由1: 高次元データでも安定して動作
AIが扱うデータは非常に高次元(数百〜数万次元)になることが多く、従来の距離計算では問題が生じます:
🔢 高次元での問題例
- 文書ベクトル:50,000語の辞書 = 50,000次元
- ユーザー行動ベクトル:10,000商品への評価 = 10,000次元
- 画像特徴ベクトル:ResNetの特徴量 = 2,048次元
このような高次元空間では、ユークリッド距離などの手法は「距離の呪い」により、すべての点がほぼ等距離になってしまいます。しかし、コサイン類似度は角度を測るため、高次元でも安定して動作します。
理由2: 文書やユーザーの好みを数値化できる
自然言語処理では、文書を数値ベクトルに変換して処理します:
📝 文書ベクトル化の例
・文書A:「人工知能は機械学習と深層学習で構成される」
・文書B:「深層学習は人工知能の重要な技術である」
これらを単語の出現頻度でベクトル化すると:
・文書A:[人工知能:1, 機械学習:1, 深層学習:1, 技術:0, 重要:0]
・文書B:[人工知能:1, 機械学習:0, 深層学習:1, 技術:1, 重要:1]
コサイン類似度により、共通語彙「人工知能」「深層学習」の存在から、2つの文書の関連性を数値で評価できます。
理由3: 計算効率とスケーラビリティの両立
大規模なAIシステムでは、数百万〜数億のアイテム間で類似度を計算する必要があります:
⚡ 計算効率の特徴
- 並列計算が可能:GPU/TPUでの高速処理に適している
- 近似計算手法が豊富:LSH(Locality Sensitive Hashing)等で高速化
- スパースベクトル対応:ゼロ要素が多いデータでも効率的
これにより、Netflixの数千万ユーザー × 数万作品の推薦計算なども実用的な時間で実行できるのです。
【数学嫌いでもOK】コサイン類似度の仕組みを図解で理解
ベクトルとは何か?(2次元から高次元まで)
ベクトルとは、複数の数値を並べたリストのようなものです:
🎯 2次元ベクトルの例
・ユーザーAの映画評価:[アクション:4, 恋愛:2] = (4, 2)
・ユーザーBの映画評価:[アクション:3, 恋愛:3] = (3, 3)
これを座標平面上の点として描くと、原点(0,0)から各点への矢印がベクトルになります。
📈 高次元への拡張
3次元以上は図示できませんが、概念は同じです:
・3次元:[アクション:4, 恋愛:2, コメディ:3]
・5次元:[アクション:4, 恋愛:2, コメディ:3, ホラー:1, SF:5]
・50,000次元:文書中の各単語の出現回数
角度で類似性を測る理由
角度に注目する理由は、方向性が類似性を表すからです:
🔄 角度と類似性の関係
- 角度 0° = コサイン値 1.0 = 完全に同じ方向(最も類似)
- 角度 45° = コサイン値 0.71 = やや類似
- 角度 90° = コサイン値 0.0 = 無関係
- 角度 180° = コサイン値 -1.0 = 正反対(最も非類似)
なぜ距離ではなく角度なのか?
距離による類似度では、「量の多さ」に影響されてしまいます:
・ユーザーA:[2, 1] (控えめな評価をする人)
・ユーザーB:[10, 5] (高い評価をつけがちな人)
・ユーザーC:[3, 3] (バランス良く評価する人)
距離で測ると、AとBは遠く見えますが、実際の嗜好(比率)は同じです。角度で測ることで、この「嗜好の方向性」を正確に捉えることができます。
計算式の意味を直感的に理解
コサイン類似度の計算式は以下の通りです:
💡 計算式を分解して理解
コサイン類似度 = (A・B) / (|A| × |B|)
- A・B:内積(各要素の積の合計)= 共通部分の強さ
- |A|, |B|:各ベクトルの長さ = それぞれの全体的な大きさ
- 割り算:正規化により、大きさの影響を除去
🧮 具体例で計算してみよう
・ユーザーA:[4, 2]
・ユーザーB:[3, 3]
# 1. 内積を計算
A_dot_B = (4 * 3) + (2 * 3) = 12 + 6 = 18
# 2. 各ベクトルの長さを計算
length_A = sqrt(4² + 2²) = sqrt(16 + 4) = sqrt(20) ≈ 4.47
length_B = sqrt(3² + 3²) = sqrt(9 + 9) = sqrt(18) ≈ 4.24
# 3. コサイン類似度を計算
cosine_similarity = 18 / (4.47 * 4.24) ≈ 18 / 18.95 ≈ 0.95結果:0.95という高い類似度が算出され、2人の嗜好が似ていることが数値で表現されました。
AIにおけるコサイン類似度の3大応用分野
応用分野1: 自然言語処理
文書の類似度計算や単語の意味類似度で広く活用されています:
📄 文書類似度の応用例
- 検索エンジン:クエリと文書の関連度計算
- 盗作検出システム:論文やレポートの類似度チェック
- ニュース分類:似た内容の記事をグループ化
- FAQ検索:ユーザーの質問と最適な回答のマッチング
🔤 単語埋め込み(Word Embeddings)での活用
Word2VecやGloVeなどの技術で、単語を高次元ベクトルに変換し、意味的類似度を計算:
・「王」 – 「男」 + 「女」 ≈ 「女王」
・「東京」と「大阪」の類似度 > 「東京」と「りんご」の類似度
応用分野2: レコメンドシステム
協調フィルタリングの中核技術として使用されています:
🛍️ 商品推薦での活用
アイテムベース協調フィルタリング:
- 商品Aを購入したユーザーの評価パターン
- 商品Bを購入したユーザーの評価パターン
- 2つのパターンの類似度 → 商品AとBの関連性
- 「商品Aを買った人にはBもおすすめ」
ユーザーベース協調フィルタリング:
- ユーザーAの商品評価パターン
- ユーザーBの商品評価パターン
- 2つのパターンの類似度 → ユーザー同士の類似性
- 「あなたと似た人が高評価した商品をおすすめ」
🎵 実際のサービス例
- Netflix:視聴履歴から類似作品を推薦
- Spotify:音楽の特徴ベクトルから似た楽曲を発見
- Amazon:購入履歴から関連商品を推薦
- YouTube:視聴パターンから次の動画を推薦
応用分野3: 画像・音声認識
特徴ベクトルの比較により、画像や音声の類似性を判定します:
🖼️ 画像認識での活用
- 顔認識:顔の特徴ベクトル同士の類似度比較
- 類似画像検索:Google画像検索の「この画像に似た画像」機能
- 商品検索:写真から似た商品を見つける
- 医療画像診断:過去の症例との類似性判定
🎤 音声・音楽での活用
- 音声認識:音響特徴ベクトルからの単語認識
- 話者認識:声紋の特徴ベクトル比較
- 音楽推薦:楽曲の音響特徴からの類似曲発見
- 楽曲検索:鼻歌から楽曲を特定するShazam等
【実践】Pythonでコサイン類似度を実装してみよう
NumPyを使った基本実装
まずは数式に忠実な実装でコサイン類似度を理解しましょう:
import numpy as np
def cosine_similarity_basic(vector_a, vector_b):
"""
基本的なコサイン類似度の実装
"""
# 内積を計算
dot_product = np.dot(vector_a, vector_b)
# 各ベクトルのノルム(長さ)を計算
norm_a = np.linalg.norm(vector_a)
norm_b = np.linalg.norm(vector_b)
# コサイン類似度を計算
cosine_sim = dot_product / (norm_a * norm_b)
return cosine_sim
# 実際に使ってみよう
user_a = np.array([4, 2, 1]) # [アクション, 恋愛, コメディ]
user_b = np.array([3, 3, 2])
user_c = np.array([1, 4, 3])
print(f"ユーザーAとB: {cosine_similarity_basic(user_a, user_b):.3f}")
print(f"ユーザーAとC: {cosine_similarity_basic(user_a, user_c):.3f}")
print(f"ユーザーBとC: {cosine_similarity_basic(user_b, user_c):.3f}")
# 実行結果:
# ユーザーAとB: 0.959
# ユーザーAとC: 0.775
# ユーザーBとC: 0.955scikit-learnでの効率的な計算
大量のデータを効率的に処理するにはscikit-learnが便利です:
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 複数のユーザーデータを行列として準備
user_matrix = np.array([
[4, 2, 1, 0, 3], # ユーザーA
[3, 3, 2, 1, 2], # ユーザーB
[1, 4, 3, 2, 1], # ユーザーC
[5, 1, 0, 0, 4], # ユーザーD
[2, 3, 4, 3, 2] # ユーザーE
])
# 全ユーザー間の類似度を一度に計算
similarity_matrix = cosine_similarity(user_matrix)
print("全ユーザー間類似度行列:")
print(similarity_matrix.round(3))
# 特定のユーザー間の類似度を取得
print(f"\nユーザーAとBの類似度: {similarity_matrix[0][1]:.3f}")
# 最も類似したユーザーを見つける
def find_most_similar_user(target_user_index, similarity_matrix):
user_similarities = similarity_matrix[target_user_index]
# 自分自身(類似度1.0)を除く
user_similarities[target_user_index] = -1
most_similar_index = np.argmax(user_similarities)
return most_similar_index, user_similarities[most_similar_index]
target_user = 0 # ユーザーA
similar_user, similarity_score = find_most_similar_user(target_user, similarity_matrix)
print(f"ユーザーA(0)に最も似ているのは: ユーザー{similar_user} (類似度: {similarity_score:.3f})")実際のデータでの動作確認
映画レビューデータを使った実践的な例を見てみましょう:
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer
# サンプルの映画レビューデータ
movie_reviews = {
'Movie_A': [
"素晴らしいアクション映画でした。爆発シーンが印象的。",
"迫力満点のアクション。主人公がかっこいい。",
"つまらないアクション映画。ストーリーが薄い。"
],
'Movie_B': [
"感動的な恋愛映画。涙が止まりませんでした。",
"美しい恋愛ストーリー。俳優の演技が素晴らしい。",
"ありきたりな恋愛もの。特に印象に残らない。"
],
'Movie_C': [
"面白いアクション映画。特殊効果が見事。",
"ハラハラするアクション。手に汗握る展開。",
"期待していたより普通のアクション映画。"
]
}
# 各映画のレビューを結合
movie_texts = {}
for movie, reviews in movie_reviews.items():
movie_texts[movie] = ' '.join(reviews)
# TF-IDFベクトル化
vectorizer = TfidfVectorizer(
max_features=100, # 特徴量数を制限
stop_words=None, # 日本語では別途処理が必要
ngram_range=(1, 2) # 1-gramと2-gramを使用
)
# テキストをベクトル化
texts = list(movie_texts.values())
movie_vectors = vectorizer.fit_transform(texts)
# コサイン類似度を計算
movie_similarity = cosine_similarity(movie_vectors)
# 結果を表示
movie_names = list(movie_texts.keys())
similarity_df = pd.DataFrame(
movie_similarity,
index=movie_names,
columns=movie_names
)
print("映画間の類似度:")
print(similarity_df.round(3))
# 最も類似した映画ペアを見つける
max_similarity = 0
most_similar_pair = None
for i in range(len(movie_names)):
for j in range(i+1, len(movie_names)):
similarity = movie_similarity[i][j]
if similarity > max_similarity:
max_similarity = similarity
most_similar_pair = (movie_names[i], movie_names[j])
print(f"\n最も類似した映画: {most_similar_pair[0]} と {most_similar_pair[1]}")
print(f"類似度: {max_similarity:.3f}")
# 特徴的な単語を確認
feature_names = vectorizer.get_feature_names_out()
print(f"\n抽出された特徴語(一部): {feature_names[:10]}")他の類似度指標との使い分け
コサイン類似度以外にも様々な類似度指標があります。適切な選択が重要です。
主要な類似度指標の比較
📊 類似度指標の特徴比較
- コサイン類似度
・測定対象:ベクトルの角度(方向性)
・値の範囲:-1 ~ 1
・特徴:大きさに依存しない - ユークリッド距離
・測定対象:点間の直線距離
・値の範囲:0 ~ ∞(小さいほど類似)
・特徴:大きさの違いに敏感 - マンハッタン距離
・測定対象:各次元の差の絶対値の合計
・値の範囲:0 ~ ∞(小さいほど類似)
・特徴:外れ値に対して頑健 - ジャカード係数
・測定対象:集合の重複度
・値の範囲:0 ~ 1
・特徴:バイナリデータに適している
コサイン類似度が適している場面
✅ 適用推奨場面
- 高次元データ:文書ベクトル、ユーザー行動ベクトル等
- スパース(疎)なデータ:多くの要素がゼロのデータ
- 正規化が困難なデータ:評価の絶対値よりも傾向が重要
- 方向性が重要なデータ:好みのパターン、テキストの内容等
コサイン類似度が適していない場面
❌ 注意が必要な場面
- 位置情報データ:GPS座標等、実際の距離が重要
- バイナリデータ:0/1のみのデータ(ジャカード係数の方が適切)
- 大きさが重要な数値データ:売上金額、人口等
- 負の値が意味を持つデータ:温度、株価変動等
# 使い分けの実例
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity, euclidean_distances
from scipy.spatial.distance import jaccard
# サンプルデータ
user_a = np.array([5, 4, 0, 0, 3]) # 控えめな評価
user_b = np.array([10, 8, 0, 0, 6]) # 高めの評価(同じ傾向)
user_c = np.array([3, 3, 5, 4, 2]) # 異なる傾向
print("=== 類似度指標の比較 ===")
# コサイン類似度
cos_ab = cosine_similarity([user_a], [user_b])[0][0]
cos_ac = cosine_similarity([user_a], [user_c])[0][0]
print(f"コサイン類似度 - A vs B: {cos_ab:.3f}, A vs C: {cos_ac:.3f}")
# ユークリッド距離(類似度に変換するため逆数を取る)
euc_ab = 1 / (1 + euclidean_distances([user_a], [user_b])[0][0])
euc_ac = 1 / (1 + euclidean_distances([user_a], [user_c])[0][0])
print(f"ユークリッド類似度 - A vs B: {euc_ab:.3f}, A vs C: {euc_ac:.3f}")
# バイナリ化してジャカード係数
binary_a = (user_a > 0).astype(int)
binary_b = (user_b > 0).astype(int)
binary_c = (user_c > 0).astype(int)
jac_ab = 1 - jaccard(binary_a, binary_b)
jac_ac = 1 - jaccard(binary_a, binary_c)
print(f"ジャカード係数 - A vs B: {jac_ab:.3f}, A vs C: {jac_ac:.3f}")
print("\n=== 解釈 ===")
print("- コサイン類似度: AとBの傾向は同じ(高い類似度)")
print("- ユークリッド距離: AとBは値の差が大きい(低い類似度)")
print("- ジャカード係数: AとBは同じアイテムを評価(高い類似度)")実際のAIプロダクトでの活用事例
Netflix・Spotifyのレコメンドシステム
Netflixでは、視聴履歴をベースにした協調フィルタリングでコサイン類似度を活用:
🎬 Netflixの推薦アルゴリズム
- ユーザーの視聴データを収集:視聴時間、評価、完走率等
- ユーザー行動をベクトル化:作品ごとの関心度を数値化
- 類似ユーザーを発見:コサイン類似度で嗜好の近いユーザーを特定
- 協調フィルタリング:類似ユーザーが好む作品を推薦
- コンテンツベース推薦と組み合わせ:作品の特徴からも類似作品を推薦
🎵 Spotifyの音楽推薦
- 音響特徴ベクトル:テンポ、音域、音色等を数値化
- リスニング行動:再生時間、スキップ率、リピート等
- プレイリスト分析:ユーザーが作成したプレイリストの傾向
- 類似楽曲発見:これらのベクトル間のコサイン類似度で関連曲を特定
Google検索での文書ランキング
検索エンジンでは、クエリと文書の関連度計算でコサイン類似度が使われます:
🔍 検索ランキングでの活用
- クエリの前処理:検索キーワードを正規化・分析
- 文書のインデックス化:各文書をTF-IDFベクトルに変換
- クエリベクトル化:検索クエリも同様にベクトル化
- 類似度計算:クエリベクトルと各文書ベクトルのコサイン類似度
- ランキング決定:類似度スコアと他の要因を組み合わせて順位付け
ChatGPTでの文書検索・RAGシステム
RAG(Retrieval-Augmented Generation)システムでも重要な役割を果たします:
🤖 RAGでのコサイン類似度活用
- 文書の埋め込み生成:事前に文書をベクトル化してデータベースに保存
- 質問の埋め込み生成:ユーザーの質問をリアルタイムでベクトル化
- 類似文書検索:質問ベクトルと各文書ベクトルのコサイン類似度を計算
- 関連文書抽出:最も類似度の高い文書を取得
- 回答生成:関連文書を参考にLLMが回答を生成
# RAGシステムの簡易実装例
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
class SimpleRAGSystem:
def __init__(self):
self.vectorizer = TfidfVectorizer(max_features=1000)
self.document_vectors = None
self.documents = []
def add_documents(self, documents):
"""文書をベクトル化してインデックスに追加"""
self.documents = documents
self.document_vectors = self.vectorizer.fit_transform(documents)
print(f"{len(documents)}件の文書をインデックス化しました")
def search(self, query, top_k=3):
"""質問に最も関連する文書を検索"""
# 質問をベクトル化
query_vector = self.vectorizer.transform([query])
# コサイン類似度を計算
similarities = cosine_similarity(query_vector, self.document_vectors)[0]
# 類似度順にソート
top_indices = similarities.argsort()[-top_k:][::-1]
results = []
for idx in top_indices:
results.append({
'document': self.documents[idx],
'similarity': similarities[idx],
'index': idx
})
return results
# 使用例
documents = [
"機械学習は人工知能の一分野です。データからパターンを学習します。",
"深層学習はニューラルネットワークを使った機械学習手法です。",
"自然言語処理はテキストデータを扱うAI技術です。",
"コンピュータビジョンは画像や動画を解析する技術です。",
"レコメンドシステムはユーザーの好みを予測して商品を推薦します。"
]
rag_system = SimpleRAGSystem()
rag_system.add_documents(documents)
# 質問に対する検索
query = "テキスト分析について教えて"
results = rag_system.search(query)
print(f"\n質問: {query}")
print("検索結果:")
for i, result in enumerate(results, 1):
print(f"{i}. (類似度: {result['similarity']:.3f}) {result['document']}")
まとめ:コサイン類似度でAIの「類似性判定」を理解しよう
コサイン類似度は、現代AIの基盤を支える重要な数学的手法です。
重要なポイント
- 角度による類似性測定:方向性(傾向)を重視し、大きさに依存しない
- 高次元データでの安定性:文書ベクトルや行動データなど大規模データに適用可能
- AI技術の中核:NLP、レコメンド、画像認識の基盤技術として広く活用
- 実装の容易さ:NumPyやscikit-learnで簡単に実装・活用可能
- 適切な使い分け:データの性質に応じて他の類似度指標との選択が重要
実践への第一歩
- 基本概念の理解:ベクトルと角度の関係を直感的に把握
- 簡単な実装を試す:NumPyでの基本実装から始める
- 実際のデータで実験:テキストや評価データで動作を確認
- ライブラリを活用:scikit-learnで効率的な処理を学習
- 応用分野への展開:レコメンド、検索、分類などへの適用
コサイン類似度を理解することで、NetflixやSpotifyがなぜ的確な推薦ができるのか、検索エンジンがなぜ関連性の高い結果を返せるのか、ChatGPTがなぜ適切な情報を参照できるのかといった、AIサービスの仕組みが見えてきます。
「AIの魔法」の正体は、実はコサイン類似度のような数学的手法の組み合わせです。まずは今日から、簡単なPythonコードでコサイン類似度を体験してみましょう!
AI・機械学習をさらに深める関連記事
コサイン類似度の理解を深めたら、さらなるAI・機械学習の技術習得を目指していきましょう:
AI技術の基盤理解
- 初心者エンジニア向け|Reactのバージョンアップ理由とReact 19の新機能をやさしく解説! – 技術の進化と理解の重要性(コサイン類似度同様、基盤技術の理解が大切)
- useEffectを使いすぎてない?React副作用の正しい使い分けとモダンな代替手段 – 適切な技術選択の考え方(類似度指標の使い分けと同様の思考)
開発環境・実装技術
- 循環参照で『Cannot access before initialization』エラーが出る問題をESLintとツールで解決 – Python・機械学習開発でも重要なエラー解決アプローチ
- Next.jsでTailwind CSSが効かない時のよくある解決法 – 設定とトラブルシューティングの基本(AI開発環境でも応用可能)
プロジェクト管理・コード品質
- ハードコーディングって何?良くないって言われるけど何で?|初心者が知るべき問題点と改善方法 – 機械学習プロジェクトでも重要なコード品質の基本
- リリース前に必ず確認!バイブコーディング&非エンジニア向けWebアプリ安全チェックリスト – AIシステムの本番運用時のセキュリティ・品質確保
