Метрики системы предсказания кликов рекламы¶
~3 минуты чтения
Предварительно: Определение задачи, Компоненты
Улучшение AUC модели Google Ads на 0.001 приносит ~$28M/year. При этом "хорошая" модель с AUC 0.75 может иметь miscalibrated predicted CTR (предсказывает 5% CTR, реальный 2%), что приводит к неправильному ранжированию рекламы и потере выручки. Калибровка (predicted CTR ~ actual CTR) -- не менее важна чем дискриминация (AUC). На интервью ожидают знание обоих аспектов + online metrics (revenue, user experience).
Иерархия метрик¶
| Уровень | Метрики | Цели |
|---|---|---|
| Business | Revenue per query, eCPM, advertiser ROI | Revenue growth |
| Auction | Calibration, bid landscape health | pred_CTR/actual_CTR in [0.98, 1.02] |
| Model | AUC, logloss, calibration, NE | AUC > 0.78, NE < 0.95 |
| System | Latency, throughput | p99 < 10ms, 1M+ QPS |
Business Metrics¶
Revenue Metrics¶
| Метрика | Формула | Почему важно |
|---|---|---|
| Revenue per query (RPQ) | total_revenue / total_queries | Primary business KPI |
| eCPM | (revenue / impressions) x 1000 | Revenue efficiency |
| Advertiser ROAS | advertiser_revenue / ad_spend | Advertiser retention |
| Ad load | ads_shown / total_slots | User experience balance |
| Click-through rate (actual) | clicks / impressions | Engagement quality |
Revenue Attribution¶
def compute_model_revenue_impact(
control_rpq: float, # Revenue per query (control model)
treatment_rpq: float, # Revenue per query (new model)
daily_queries: int = 8_500_000_000, # Google: 8.5B/day
) -> dict:
delta_rpq = treatment_rpq - control_rpq
daily_impact = delta_rpq * daily_queries
annual_impact = daily_impact * 365
return {
"delta_rpq": delta_rpq,
"daily_revenue_impact": daily_impact,
"annual_revenue_impact": annual_impact,
# AUC +0.001 ~ RPQ +0.1% ~ $28M/year for Google
}
Model Metrics¶
Discrimination Metrics¶
| Метрика | Формула | Цель | Интерпретация |
|---|---|---|---|
| AUC-ROC | Area under ROC curve | > 0.78 | Ranking quality |
| Logloss | \(-\frac{1}{N}\sum[y\log p + (1-y)\log(1-p)]\) | Minimize | Prediction quality |
| Normalized Entropy (NE) | logloss / entropy(avg_CTR) | < 0.95 | Relative to baseline |
| Group AUC | AUC per user or ad group | > 0.70 | Per-group ranking |
Calibration Metrics (Critical)¶
def compute_calibration(y_true, y_pred, n_bins=10):
"""
Калибровка: predicted CTR должен = actual CTR
"""
bins = np.linspace(0, 1, n_bins + 1)
results = []
for i in range(n_bins):
mask = (y_pred >= bins[i]) & (y_pred < bins[i+1])
if mask.sum() == 0:
continue
bin_pred = y_pred[mask].mean()
bin_actual = y_true[mask].mean()
results.append({
"bin": f"[{bins[i]:.1f}, {bins[i+1]:.1f})",
"predicted_ctr": bin_pred,
"actual_ctr": bin_actual,
"ratio": bin_pred / bin_actual if bin_actual > 0 else float('inf'),
"count": mask.sum(),
})
# Global calibration
global_ratio = y_pred.mean() / y_true.mean()
return {
"bins": results,
"global_calibration": global_ratio, # Target: 0.98-1.02
"expected_calibration_error": np.mean([
abs(r["predicted_ctr"] - r["actual_ctr"]) * r["count"]
for r in results
]) / len(y_true),
}
Auction-Specific Metrics¶
| Метрика | Описание | Цель |
|---|---|---|
| Calibration ratio | mean(pred_CTR) / mean(actual_CTR) | 0.98 - 1.02 |
| Reserve price efficiency | % auctions meeting reserve | > 90% |
| Pacing accuracy | actual_spend / budget_target | 0.95 - 1.05 |
| Position bias | CTR difference by ad position | Account for in model |
Online Metrics (A/B Test)¶
Primary¶
| Метрика | Минимальный detectable effect | Длительность теста |
|---|---|---|
| Revenue per query | +0.1% | 2 weeks |
| Clicks per query | +0.2% | 1 week |
| Advertiser satisfaction | +0.5% | 4 weeks |
Guardrail Metrics¶
| Метрика | Ограничение | Почему |
|---|---|---|
| Ad load (ads per page) | No increase > 2% | User experience |
| User session duration | No decrease > 1% | Organic engagement |
| Advertiser cost per click | No increase > 5% | Advertiser retention |
| Query abandonment rate | No increase > 0.5% | User satisfaction |
System Metrics¶
| Метрика | Цель |
|---|---|
| Inference latency p50 | < 3ms |
| Inference latency p99 | < 10ms |
| Throughput | 1M+ predictions/sec |
| Feature freshness | < 1 min for user features |
| Model freshness | < 24 hours |
Заблуждение: AUC -- единственная важная метрика для CTR prediction
AUC показывает ranking quality, но не calibration. Модель с AUC 0.80 и calibration ratio 2.0 (завышает CTR вдвое) приводит к: (1) рекламодатели переплачивают -> уходят, (2) auction dynamics нарушены -- low-quality ads побеждают. В production calibration ratio (0.98-1.02) не менее важен чем AUC. Isotonic regression или Platt scaling -- стандартные post-hoc calibration методы.
Заблуждение: offline метрики (AUC, logloss) достаточны для оценки
Модель с лучшим offline AUC может ухудшить revenue в production из-за: (1) feedback loops (показали другие ads -> другие клики -> другое распределение), (2) position bias (CTR зависит от позиции, не от ad quality), (3) exploration/exploitation tradeoff (новые ads без данных получают низкий predicted CTR). Online A/B test с revenue-метриками = единственный способ оценить реальный impact.
Секция для интервью¶
Вопрос: "Какие метрики для CTR prediction модели?"
Слабый ответ: "AUC и accuracy."
Сильный ответ: "Три группы. Offline: AUC (> 0.78, ranking quality), logloss (prediction quality), normalized entropy (< 0.95, relative improvement), calibration ratio (0.98-1.02, predicted CTR ~ actual CTR). Online: revenue per query (primary), eCPM, advertiser ROAS. Guardrails: ad load не растёт, user session не падает, advertiser CPC не скачет. Критически: calibration не менее важна чем discrimination. Модель с AUC 0.80 но miscalibrated (pred_CTR 2x выше actual) сломает auction dynamics -- рекламодатели переплачивают и уходят. Google использует Normalized Entropy вместо raw logloss: NE = logloss / entropy(avg_CTR), чтобы сравнивать модели с разным base CTR."