オンライン評価
「オフライン評価で良い結果が出た。だが本番は別世界だ。」
田中VPoEが本番環境のメトリクスを指す。
「実際のユーザー行動で検証するオンライン評価。A/Bテストの結果をどう読み解き、どう意思決定するかが重要だ。」
オンライン評価指標
| 指標 | 定義 | 目標 |
|---|---|---|
| CTR | クリック数 / インプレッション数 | > 5% |
| CVR | 購入数 / クリック数 | > 2% |
| RPV | 収益 / ビジター数 | 前月比+10% |
| セッション滞在時間 | 推薦ページの平均滞在時間 | > 2分 |
| カート追加率 | カート追加数 / インプレッション数 | > 3% |
インターリービング
class InterleavingExperiment:
"""インターリービングによる高速オンライン評価"""
def interleave(self, list_a, list_b, k=10):
"""2つの推薦リストをインターリーブ"""
result = []
source = []
i, j = 0, 0
while len(result) < k and (i < len(list_a) or j < len(list_b)):
# 交互に追加(重複は除外)
if i < len(list_a) and list_a[i] not in result:
if len(result) <= len([s for s in source if s == 'B']):
result.append(list_a[i])
source.append('A')
i += 1
continue
if j < len(list_b) and list_b[j] not in result:
result.append(list_b[j])
source.append('B')
j += 1
else:
i += 1
return result, source
def evaluate_clicks(self, interleaved_list, source_list, clicked_items):
"""クリックされたアイテムの出所を集計"""
wins = {'A': 0, 'B': 0}
for item in clicked_items:
if item in interleaved_list:
idx = interleaved_list.index(item)
wins[source_list[idx]] += 1
total = wins['A'] + wins['B']
if total == 0:
return {'winner': 'tie', 'confidence': 0}
# 二項検定
from scipy.stats import binom_test
p_value = binom_test(wins['B'], total, 0.5)
winner = 'B' if wins['B'] > wins['A'] else 'A'
return {
'winner': winner,
'wins_a': wins['A'],
'wins_b': wins['B'],
'p_value': round(p_value, 4),
}
オンライン評価の落とし穴
| 問題 | 説明 | 対策 |
|---|---|---|
| ノベルティ効果 | 新しい推薦方式に最初だけ反応 | 2週間以上の長期テスト |
| 季節効果 | 季節イベントが結果を歪める | 同一期間で比較 |
| ネットワーク効果 | ユーザー間の影響 | クラスター単位の割り当て |
| Peeking問題 | テスト途中で結果を見て判断 | 事前にサンプルサイズを固定 |
まとめ
| 項目 | ポイント |
|---|---|
| 指標 | CTR, CVR, RPVなどビジネス直結の指標で評価 |
| インターリービング | A/Bテストより少ないサンプルで検出可能 |
| 落とし穴 | ノベルティ効果・季節効果に注意 |
| 意思決定 | 統計的有意性 + ビジネスインパクトの両面で判断 |
チェックリスト
- オンライン評価指標を列挙できる
- インターリービングの仕組みを説明できる
- A/Bテストとインターリービングの使い分けを判断できる
- オンライン評価の落とし穴と対策を理解した
次のステップへ
オンライン評価を学んだ。次は探索と活用のバランスを学ぼう。
推定読了時間: 30分