ヒット率(Hit Rate)

入門

4.5.4

ヒット率(Hit Rate)

最終更新 2020-03-11 読了時間 3 分
まとめ
  • Hit Rate は上位候補に少なくとも 1 つ正解が含まれる割合を測る指標です。
  • ユーザーごとの候補リストから Hit Rate@k を算出し、網羅性を評価します。
  • Recall や Precision と併用する際の注意点や利用シーンを整理します。

1. 定義 #

クエリごとの正解集合を $G_q$、上位 k の候補集合を $S_{q,k}$ とすると、

$$ \mathrm{HR@k} = \frac{1}{Q} \sum_{q=1}^{Q} \mathbf{1}\bigl\{ G_q \cap S_{q,k} \ne \emptyset \bigr\} $$

少なくとも 1 件ヒットしていれば 1、なければ 0 として平均を取ります。


2. Python で計算 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

def hit_rate_at_k(y_true: np.ndarray, y_score: np.ndarray, k: int) -> float:
    """上位 k 件内に少なくとも 1 件の正例があるかどうかを返す。

    Args:
        y_true: 正例を 1 とするラベル配列。
        y_score: モデルが出力したスコア配列。
        k: 上位何件を見るか。

    Returns:
        ヒットした場合は 1.0、該当なしの場合は 0.0。
    """
    idx = np.argsort(-y_score)[:k]
    return 1.0 if y_true[idx].sum() > 0 else 0.0

hits = [hit_rate_at_k(y_true[q], y_score[q], k=10) for q in range(len(queries))]

hr_at_10 = np.mean(hits)

print("Hit Rate@10:", round(hr_at_10, 3))

複数クエリ(ユーザー)がある場合は平均を取ります。実装はRecall@kと似ていますが、ヒットの有無だけに注目する点が異なります。


3. 計算例 — HR@5 vs HR@10 #

ここでは6人のユーザーに対して、推薦システムが出力した候補リストを使い、 $k=5$ と $k=10$ でHit Rateがどう変わるかを具体的に確認します。

3.1 設定 #

推薦システムが各ユーザーに10件のアイテムを推薦し、ユーザーが実際に購入(正解)したアイテムが候補リスト中のどの位置にあるかを示します。

ユーザー推薦リスト(10件)正解アイテムの順位
A$[i_1, i_2, \ldots, i_{10}]$3位
B$[i_1, i_2, \ldots, i_{10}]$7位
C$[i_1, i_2, \ldots, i_{10}]$1位
D$[i_1, i_2, \ldots, i_{10}]$リスト外(ヒットなし)
E$[i_1, i_2, \ldots, i_{10}]$5位
F$[i_1, i_2, \ldots, i_{10}]$9位
  • ユーザーA:正解アイテムが3位 → 上位5件にも上位10件にも含まれる
  • ユーザーB:正解アイテムが7位 → 上位5件には含まれないが、上位10件には含まれる
  • ユーザーC:正解アイテムが1位 → 両方に含まれる
  • ユーザーD:正解アイテムがリスト外 → どちらにも含まれない
  • ユーザーE:正解アイテムが5位 → 上位5件にも上位10件にも含まれる
  • ユーザーF:正解アイテムが9位 → 上位5件には含まれないが、上位10件には含まれる

3.2 ユーザーごとのヒット判定 #

ユーザー正解の順位$k=5$でのヒット$k=10$でのヒット
A3位11
B7位01
C1位11
Dなし00
E5位11
F9位01
合計35

3.3 HR@5の計算 #

上位5件に正解が含まれたユーザーはA・C・Eの3人です。

$$ \mathrm{HR@5} = \frac{1}{6} \sum_{q=1}^{6} \mathbf{1}\bigl\{ G_q \cap S_{q,5} \ne \emptyset \bigr\} = \frac{3}{6} = 0.500 $$

つまり、ユーザーの 50% に対して上位5件以内で正解を提示できています。

3.4 HR@10の計算 #

上位10件に正解が含まれたユーザーはA・B・C・E・Fの5人です。

$$ \mathrm{HR@10} = \frac{1}{6} \sum_{q=1}^{6} \mathbf{1}\bigl\{ G_q \cap S_{q,10} \ne \emptyset \bigr\} = \frac{5}{6} \approx 0.833 $$

ユーザーの約 83.3% に対して上位10件以内で正解を提示できています。

3.5 kの値による比較 #

指標ヒット数Hit Rate
HR@53 / 60.500
HR@105 / 60.833
差分+2+0.333

$k$ を5から10に増やすことで、ユーザーB(7位)とユーザーF(9位)が新たにヒットに加わり、Hit Rateが0.333ポイント改善しました。

この結果から読み取れるポイント:

  • $k$ を大きくするとHR@kは単調に増加(または同値) します。候補が増えるほどヒットしやすくなるためです。
  • ユーザーDはどの $k$ でもヒットしないため、推薦リスト自体の改善(モデルやデータの見直し)が必要です。
  • HR@5が低くHR@10が高い場合、正解アイテムが6〜10位付近に集中していることを示唆します。上位に押し上げるために、ランキングモデルの精度向上が求められます。

3.6 Pythonでの再現 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import numpy as np

# 各ユーザーの正解アイテムの順位(1-indexed, 0 はヒットなしを表す)
hit_positions = [3, 7, 1, 0, 5, 9]

def compute_hr_at_k(hit_positions, k):
    """各ユーザーの正解順位からHR@kを計算する。"""
    hits = [1 if 0 < pos <= k else 0 for pos in hit_positions]
    return np.mean(hits)

hr5 = compute_hr_at_k(hit_positions, k=5)
hr10 = compute_hr_at_k(hit_positions, k=10)

print(f"HR@5 : {hr5:.3f}")   # 0.500
print(f"HR@10: {hr10:.3f}")  # 0.833

4. 利点 #

  • 直感的:ユーザーの何%にヒットしたかをそのまま説明できる。
  • Recall@k より寛容:複数正解があっても 1 件ヒットすればカバーしたと見なす。
  • 早期評価:最初の改善方向を探るためのラフな指標として使いやすい。

5. 実務での活用 #

  • 推薦システム:ユーザーがクリックしたアイテムを候補に含められた割合を把握。

  • E コマース:人気商品やパーソナライズされた商品が候補に入っているかを確認。

  • A/B テスト:オンライン試験に入る前に、オフラインで HR@k の改善を目安にモデルを絞り込む。


6. 他指標との併用 #

指標特徴一緒に見ると良い理由
Hit Rateユーザー単位のヒット有無簡潔だが網羅性は分からない
Recall@k正解数 / 正解総数正解が複数ある場合の網羅性を把握
Precision@k候補の純度ヒット率が高くてもノイズが多い可能性を確認
NDCG順位の質ヒットした正解が上位にあるかを確認

まとめ #

  • Hit Rate はユーザーごとに候補リスト内へ正解が入ったかを評価するシンプルな指標。

  • Recall@k や NDCG と組み合わせることで、網羅性や順位の質も把握できる。

  • 初期分析や KPI として扱いやすく、ビジネス側への説明にも向いている。


よくある質問 #

Hit RateとRecall@kはどう違う? #

Hit Rate@kは「ユーザーごとに上位k件に1件でも正解が含まれたか」をバイナリ(0/1)で評価します。Recall@kは「正解アイテム全体のうち何割を上位k件に含めたか」の割合です。正解が1件しかないタスク(例:購入予測)では両者は一致しますが、正解が複数あるタスクではRecall@kの方が詳細な評価ができます。

kの値はどうやって決める? #

ユーザーが実際に見る画面の表示件数に合わせるのが基本です。スマートフォンの1画面に5件表示するならk=5、ECサイトの1ページ表示が20件ならk=20といった具合です。複数のk(例: k=5, 10, 20)で評価し、kの変化に対するHit Rateの感度を確認することで閾値設定の根拠になります。

Hit Rateが高くてもNDCGが低い場合は? #

上位k件に正解が含まれているが、正解が上位に出ていない(例:k=10の10番目にのみ正解がある)ケースです。Hit Rateは「あるかないか」しか見ないため、このような状況を検出できません。ランキングの質を重視する場合はNDCGやMAPを併用してください。

sklearnやpandasでHit Rateを計算するには? #

標準ライブラリには組み込み関数がないため、自作することが多いです。numpyを使って各ユーザーの正解セットと上位k件の積集合のサイズが1以上かどうかを判定し、ユーザー全体で平均します。ranking_metricsms-recommendなどのレコメンドライブラリにも実装があります。