推薦手法の分類と特徴
「推薦には大きく3つのアプローチがある。それぞれの長所と短所を正しく理解しておかないと、技術選定で失敗する。」
田中VPoEがホワイトボードに3つの円を描きながら説明を始める。
「まずは各手法の仕組みを深く理解しよう。」
協調フィルタリング(Collaborative Filtering)
協調フィルタリングは「似たユーザーは似たアイテムを好む」という仮説に基づく手法である。アイテムの属性情報を必要とせず、ユーザーの行動データだけで推薦を行える。
ユーザーベース協調フィルタリング
ユーザー間の類似度を計算し、類似ユーザーが高評価したアイテムを推薦する。
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# ユーザー×アイテムの評価行列(0は未評価)
ratings = np.array([
[5, 3, 0, 1, 4], # ユーザーA
[4, 0, 0, 1, 3], # ユーザーB
[1, 1, 0, 5, 0], # ユーザーC
[0, 3, 4, 4, 0], # ユーザーD
[5, 4, 3, 0, 4], # ユーザーE
])
# ユーザー間のコサイン類似度
user_sim = cosine_similarity(ratings)
print("ユーザーAとBの類似度:", round(user_sim[0][1], 3))
# 出力: ユーザーAとBの類似度: 0.975
# ユーザーAとCの類似度
print("ユーザーAとCの類似度:", round(user_sim[0][2], 3))
# 出力: ユーザーAとCの類似度: 0.567
ユーザーAとBは好みが近く、AとCは好みが異なることが数値で確認できる。
アイテムベース協調フィルタリング
アイテム間の類似度を計算し、ユーザーが過去に高評価したアイテムに類似するアイテムを推薦する。
# アイテム間のコサイン類似度
item_sim = cosine_similarity(ratings.T)
item_names = ["商品A", "商品B", "商品C", "商品D", "商品E"]
# 商品Aに類似する商品を表示
sim_scores = list(enumerate(item_sim[0]))
sim_scores.sort(key=lambda x: x[1], reverse=True)
print("商品Aに類似する商品:")
for idx, score in sim_scores[1:]: # 自身を除外
print(f" {item_names[idx]}: {score:.3f}")
Amazonの「この商品を買った人はこちらも買っています」はアイテムベース協調フィルタリングの代表例である。
協調フィルタリングの課題
| 課題 | 説明 |
|---|---|
| Cold Start問題 | 新規ユーザー・新規アイテムには行動データがなく推薦不可 |
| スパース性 | ユーザー×アイテム行列のほとんどが未評価(99%以上が空) |
| スケーラビリティ | ユーザー数・アイテム数が増えると類似度計算コストが増大 |
| 人気バイアス | 人気アイテムが推薦されやすく、ロングテールが埋もれる |
コンテンツベースフィルタリング(Content-Based Filtering)
コンテンツベースフィルタリングは、アイテムの属性(メタデータ)を用いてユーザーの好みに合うアイテムを推薦する手法である。
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# H&Mデータセットを想定した商品データ
products = pd.DataFrame({
"product_id": [1, 2, 3, 4, 5],
"name": ["コットンTシャツ", "リネンシャツ", "デニムパンツ", "コットンワンピース", "ウールコート"],
"description": [
"オーガニックコットン クルーネック カジュアル 夏",
"リネン100% ボタンダウン きれいめ 夏",
"ストレッチデニム スリムフィット カジュアル 通年",
"オーガニックコットン Aライン フェミニン 春夏",
"ウール混 チェスターコート フォーマル 冬",
],
"category": ["トップス", "トップス", "ボトムス", "ワンピース", "アウター"],
})
# TF-IDFでテキスト特徴量を作成
tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(products["description"])
# アイテム間の類似度
content_sim = cosine_similarity(tfidf_matrix)
# コットンTシャツに類似する商品
sim_scores = list(enumerate(content_sim[0]))
sim_scores.sort(key=lambda x: x[1], reverse=True)
print("コットンTシャツに類似する商品:")
for idx, score in sim_scores[1:]:
print(f" {products.iloc[idx]['name']}: {score:.3f}")
コンテンツベースの特徴
| 長所 | 短所 |
|---|---|
| Cold Start問題に強い(アイテム属性があれば推薦可能) | 過剰特化(ユーザーの既知の好みに偏る) |
| 推薦理由の説明が容易 | 特徴量エンジニアリングの負荷が高い |
| 他ユーザーのデータ不要 | セレンディピティ(意外な発見)が低い |
ハイブリッド推薦
ハイブリッド推薦は協調フィルタリングとコンテンツベースを組み合わせ、両者の弱点を補完する手法である。
主な組み合わせ方
ハイブリッド推薦の構成パターン:
1. 加重ハイブリッド(Weighted)
- 複数手法のスコアを重み付け平均
- score = w1 * cf_score + w2 * cb_score
- シンプルで実装しやすい
2. スイッチング(Switching)
- 状況に応じて手法を切り替え
- 新規ユーザー → コンテンツベース
- 十分な履歴あり → 協調フィルタリング
3. カスケード(Cascade)
- 1つ目の手法で候補を絞り、2つ目で精緻化
- 協調フィルタリングで候補100件 → コンテンツベースでリランキング
4. 特徴量結合(Feature Combination)
- 協調フィルタリングの出力をコンテンツベースの特徴量に追加
- LightFM等のライブラリが対応
NetShop社への適用
NetShop社のECサイトでは以下の組み合わせが有効と考えられる。
| シナリオ | 推薦手法 | 理由 |
|---|---|---|
| 既存ユーザーのトップページ | 協調フィルタリング | 豊富な購買履歴を活用 |
| 新規ユーザー | コンテンツベース(人気+カテゴリ) | 行動データが不足 |
| 商品詳細ページ | アイテムベースCF + コンテンツ | 「似た商品」を表示 |
| カート内推薦 | アソシエーションルール + CF | クロスセル |
評価の観点
推薦手法を選定する際に考慮すべき評価軸を整理する。
| 評価軸 | 協調フィルタリング | コンテンツベース | ハイブリッド |
|---|---|---|---|
| 精度(Accuracy) | 高い | 中程度 | 最も高い |
| 多様性(Diversity) | 中程度 | 低い | 高い |
| 新規性(Novelty) | 中程度 | 低い | 高い |
| Cold Start耐性 | 低い | 高い | 高い |
| 説明可能性 | 低い | 高い | 中程度 |
| 実装コスト | 低い | 中程度 | 高い |
まとめ
| 項目 | ポイント |
|---|---|
| 協調フィルタリング | 行動データベース。精度は高いがCold Startに弱い |
| コンテンツベース | 属性データベース。説明しやすいが過剰特化しやすい |
| ハイブリッド | 組み合わせで弱点を補完。実装コストは高い |
| 選定基準 | データの質・量、Cold Startの頻度、説明性の要件で判断 |
チェックリスト
- ユーザーベースとアイテムベースの協調フィルタリングの違いを説明できる
- コンテンツベースフィルタリングの長所と短所を理解した
- ハイブリッド推薦の4つの組み合わせパターンを説明できる
- NetShop社のシナリオ別に適切な推薦手法を選定できる
次のステップへ
各推薦手法の特徴を理解したところで、次はレコメンデーションがビジネスに与える具体的なインパクトについて深掘りしよう。
推定読了時間: 30分