# ecs_ratio 和 ARP 指标说明

> 这两个指标是推荐实验报表的"健康度 guardrail"——专门用来回答老板关心的那句话：
> **"数值涨了，是真本事还是靠推头部换来的？"**

---

## 📌 TL;DR（30 秒电梯版）

两个健康度指标：

- **`ecs_ratio`** = **分发均匀度**：内容是集中在头部几条视频，还是分散推出去？越高越分散。我们现在 7% 左右，意思是"**菜单上 1.6 万条视频，实际等效只推了 1100 条**"。
- **`ARP`** = **平均推荐热度**：推给用户的视频平均有多火？越高说明越在推爆款，越低说明越在推长尾。

**两个一起看**，就能判断 AB 涨的数值是真本事还是靠推头部换的。

---

## 一、ecs_ratio — 分发均匀度

### 一句话定义
**回答"内容有没有集中"的问题**。把分发的形态（多均匀 / 多集中）量化成一个 0~100% 的数字。

### 大白话解释
- 我们菜单上有 16,000 种视频，但每天的曝光量 90% 都集中在前 1,000 条上
- `ecs_ratio` 告诉你：**实际等效推了多少种，占菜单的几成**
- 比如 7%，就是"**菜单 16,000 条，等效只推了 1,100 条**"——剩下 14,900 条要么曝光少得可忽略，要么根本没上架

### 数值范围

| ecs_ratio 值 | 含义 |
|---|---|
| → 100% | 每条视频曝光次数完全相同（完全均匀，不现实） |
| **7% 左右** | **你们短视频 Feed 的典型水平**（基线形态） |
| → 0% | 所有曝光都集中在一条视频（极端集中） |

### 业务含义
- 这个数字**越高越健康**（分发越分散，长尾视频有机会）
- **变化 > 2.9%** 才是显著信号（噪声门槛，实测 7 天得出）
- 如果从 7% 掉到 6%，意思是"**推荐系统比以前更偏向头部了，长尾内容被挤掉了**"——这就是老板担心的"内容在集中"

### 计算方法（3 步，不用公式）

**第 1 步：数每条视频当天被推了多少次**

```
A 视频: 50,000 次     ← 头部
B 视频: 30,000 次
C 视频: 15,000 次
...
Z 视频:     10 次     ← 长尾
```

**第 2 步：算"等效视频数"**

如果把这些曝光**平均分配**给所有视频，等于推了多少条？

> 举个简单的例子：3 条视频，曝光分别是 500 / 300 / 200。
> 如果**完全平均**，每条应该 333.3 次，相当于推了 3 条。
> 但实际是 500/300/200 不均匀，所以"等效视频数"**小于 3**——算出来大约 **2.4 条**。

**第 3 步：等效视频数 ÷ 真实视频数 = ecs_ratio**

```
2.4 / 3 = 80%   ← 这个例子的 ecs_ratio
```

在真实数据里：**1158（等效）/ 16,757（真实）= 6.9%**。

---

## 二、ARP — 平均推荐热度

### 一句话定义
**回答"推的都是爆款吗"的问题**。把"推荐内容的平均热门度"量化成一个数字。

### 大白话解释
- 用户刷到的每一条推荐，**这条视频在全平台当天被推过多少次**
- 如果推给用户的都是"全平台日曝光 50 万次的爆款"，ARP 就很高
- 如果推给用户的是"一天只被推 500 次的长尾视频"，ARP 就很低
- 我们现在 ARP 在 **12 万左右**，意思是"**用户平均每次刷到的视频，当天被全平台推过 12 万次**"——中等偏上热门

### 数值范围
- **这个数字没有绝对好坏**，只能和对比组比相对值
- 两组之间 ARP **差 > 0.5%** 就是显著信号（最稳的指标，噪声极小）
- **越高** = 推得越头部
- **越低** = 推得越长尾

### 业务含义
- ARP 单独看不够，要和 `ecs_ratio` 一起看
- 如果一个实验组的 ARP 比对照组高 5%，说明这组**倾向于多推热门内容**
- 如果同时 bn_rov 也涨了，要问："**涨的 bn_rov 是不是靠多推爆款换来的？**"

### 计算方法（2 步）

**第 1 步：查每条被推视频在全平台的当天总曝光**

```
A 视频（头部爆款）：全平台日曝光 500,000
B 视频（中等）：    全平台日曝光 100,000
C 视频（长尾）：    全平台日曝光   5,000
```

**第 2 步：按"我们推了多少次"加权求平均**

> 假设我们今天推了：A 给 500 个用户，B 给 300 个用户，C 给 200 个用户
>
> 加权平均 =
> `(500×500,000 + 300×100,000 + 200×5,000) / (500+300+200)`
> `= 281,000`
>
> 含义：**我们推的视频平均每条当天全平台被推了 28.1 万次**。

**为什么要加权**：因为用户不是"每条视频看 1 次"，而是"**头部的 A 视频他看了 500 次**"。加权后才能反映"用户实际看到的内容平均有多火"。

---

## 三、两个一起看 = 实验健康度四象限

这是**汇报时的核心图**，老板一看就懂：

| | **ARP ↓**（推更长尾） | **ARP ↑**（推更头部） |
|---|---|---|
| **ecs_ratio ↑**<br>（更分散） | ✅ **最健康**<br>分散推冷门<br>= 真·个性化提升 | ⚠️ **可接受**<br>分散但推头部<br>= 头部内部多样化 |
| **ecs_ratio ↓**<br>（更集中） | ❓ **少见**<br>集中推冷门<br>= 小众爆发 | ❌ **最差**<br>集中推头部<br>= popularity bias 作弊 |

**解读规则**：
- 落在左上 = 模型真的变聪明了（扩量放心）
- 落在右上 = 模型倾向头部但还保持多样性（可以接受）
- 落在右下 = 警报！数值涨可能是靠推头部作弊换来的
- 落在左下 = 少见情况，需要单独分析

---

## 四、真实数据应用：建模目标 01 桶

以跑了 19 天的建模目标 01 桶 vs 对照组 89（7 天均值）：

| 指标 | 变化 | 象限判定 |
|---|---|---|
| `ecs_ratio` | **+1.4%**（更分散） | ⬆️ 纵轴正向 |
| `ARP` | **-0.64%**（推更少头部） | ⬅️ 横轴负向 |
| **落在哪个象限** | **左上：最健康** ✅ | |

同时数值指标：
- `bn_rov` +8.04%（7/7 天全胜）
- `cn_rov` +11.92%（7/7 天全胜）
- `total_rov` +7.51%（7/7 天全胜）

### 翻译成大白话

> "建模目标实验 01 桶数据全面健康。bn_rov 涨了 8%，**但不是靠推头部换来的**——
>
> 分发均匀度 **ecs_ratio 反而升了 1.4%**（说明内容更分散，没有向头部集中），
> 平均推荐热度 **ARP 还降了 0.64%**（说明推的视频比以前平均**更冷门**）。
>
> 这意味着：模型在**推得更分散、更长尾的前提下，还拿到了 +8% 的收益**。这才是真·个性化提升，不是 popularity bias 作弊。"

---

## 五、汇报话术模板

### 👔 汇报给老板的标准格式

```
【实验名称】XX 实验
【结论】数据全面健康 / 有弱风险 / 还需观察
【数值】bn_rov +X%, cn_rov +Y%, total_rov +Z%（N/7 天全胜）
【健康度】ecs_ratio 变化 +/-X%（门槛 2.9%），ARP +/-Y%
          => 翻译成"是否靠推头部换数值"
【建议】继续扩量 / 暂缓扩量 / 再观察 X 天
```

### 🎤 一句话终极版

> "这两个指标就是老板您说的'**内容有没有集中、有没有靠推头部换数值**'的量化版本。ecs_ratio 测分散度，ARP 测头部偏向。建模目标的 bn_rov 涨 8%，同时 ecs_ratio 略升、ARP 反降——**涨得很干净，不是作弊**。"

---

## 六、餐厅比喻（适合 business sense 的人）

> 您可以这么想——
>
> **`ecs_ratio` 就像一家餐厅的菜单使用率**：菜单有 100 道菜，但客人天天只点前 5 道，这家店'**实际在运营 5 道菜**'。这个比例越高，店铺越活，所有菜都有人点。
>
> **`ARP` 就像这家餐厅推荐给你的菜的平均热度**：服务员推荐你点'**招牌烤鸭**'（爆款）还是'**上海独家本帮小菜**'（长尾）。数字越高，说明推的越是'大家都点的爆款'。
>
> 两个一起看，就能判断我们的'餐厅'（推荐系统）到底是在**精准上菜**还是**懒人式只推爆款**。

---

## 七、技术细节（给同事/自己留的）

### ecs_ratio 的数学公式

**ECS (Effective Catalog Size)**:

$$ECS = 2 \cdot \sum_{i=1}^{N} p_i \cdot i - 1$$

其中：
- `N` = 桶内去重的 vid 数
- `p_i` = 第 `i` 名 vid 的曝光占比（按曝光量**降序**排好）
- `i` = 排名（第 1 名、第 2 名 ...）

**ecs_ratio**:

$$\text{ecs\_ratio} = \frac{ECS}{\text{distinct\_vid\_cnt}}$$

**值域**：`(0, 1]`，越大越分散。

**验算**：
- 3 条视频曝光 500/300/200：ECS = 2·(0.5·1 + 0.3·2 + 0.2·3) - 1 = 2.4
- 完全均匀（各 1/3）：ECS = 2·(1/3·1 + 1/3·2 + 1/3·3) - 1 = 3（= N 上限）
- 完全集中（一个占 100%）：ECS = 2·1 - 1 = 1（下限）

### ARP 的数学公式

$$ARP = \frac{\sum_{i=1}^{N} (\text{桶内曝光次数}_i \times \text{全平台曝光次数}_i)}{\sum_{i=1}^{N} \text{桶内曝光次数}_i}$$

这是一个**按桶内曝光量加权的平均**——推得越多的 vid，对 ARP 的贡献越大。

**关键设计**：用"桶内曝光加权"而不是"简单平均"，是因为用户不是均匀看每条 vid，而是**每次推荐事件**贡献 1 个权重。加权后 ARP 真正反映"**随机挑一次推荐，这条 vid 平均有多火**"。

---

## 八、SQL 实现位置

在 `base_v3_new.sql` 里：

| CTE | 作用 | 大致行号 |
|---|---|---|
| `t_vid_exp` | 桶内每条 vid 的曝光次数（ECS/ARP 共用的中间表） | ~259 |
| `t_bucket_ecs` | 用窗口函数算 ECS | ~280 |
| `t_vid_global_pop` | 全平台每条 vid 的当天总曝光（ARP 的 popularity reference） | ~308 |
| `t_bucket_arp` | 按桶内曝光加权算 ARP | ~327 |
| `t_metrics` | 把 ecs_ratio 算出来：`AVG(ecs) / AVG(distinct_vid_cnt)` | ~436 |

### 关键 SQL 片段

```sql
-- ECS 计算
,t_bucket_ecs AS (
    SELECT  dt, apptype, abcode, suffix
            ,2 * SUM(p * rn) - 1 AS ecs
    FROM    (
        SELECT  dt, apptype, abcode, suffix
                ,vid_exp_cnt / SUM(vid_exp_cnt) OVER (
                    PARTITION BY dt, apptype, abcode, suffix
                ) AS p
                ,ROW_NUMBER() OVER (
                    PARTITION BY dt, apptype, abcode, suffix
                    ORDER BY vid_exp_cnt DESC
                ) AS rn
        FROM    t_vid_exp
    ) t
    GROUP BY dt, apptype, abcode, suffix
)

-- ARP 计算
,t_bucket_arp AS (
    SELECT  v.dt, v.apptype, v.abcode, v.suffix
            ,SUM(v.vid_exp_cnt * g.vid_global_pop) / SUM(v.vid_exp_cnt) AS arp
    FROM    t_vid_exp v
    LEFT JOIN t_vid_global_pop g
    ON      v.dt = g.dt AND v.apptype = g.apptype AND v.vid = g.vid
    GROUP BY v.dt, v.apptype, v.abcode, v.suffix
)

-- ecs_ratio 计算（t_metrics 里）
,ROUND(AVG(e.ecs) / NULLIF(AVG(b.distinct_vid_cnt), 0), 6) AS ecs_ratio
```

---

## 九、噪声基底（重要！）

**基于 7 天对照组内部（89 vs 2c）实测的噪声门槛**：

| 指标 | 噪声门槛 | 含义 |
|---|---|---|
| `ecs_ratio` | **2.88%** | 实验组 ratio 变化 < 2.9% 都算噪声 |
| `bn_rov` | **1.06%** | 数值差 < 1% 不算赢 |
| `cn_rov` | **4.10%** | cn 噪声最大（分享行为方差大） |
| `total_rov` | **1.79%** | |
| `ARP` | **0.43%** | **最稳定**，> 0.5% 就是信号 |

**记住**：任何低于门槛的变化都不是信号，是噪声。不要把噪声当结论上报。

---

## 十、常见误解

### ❌ 误解 1："ARP 高就是坏"
**正确理解**：ARP 高只是说"推得更头部"，本身没有好坏。关键看 `ecs_ratio` 是不是同时跌——只有**两者同时往坏的方向走**（ARP ↑ + ecs_ratio ↓）才是 popularity bias。

### ❌ 误解 2："ecs_ratio 7% 很差，应该更高"
**正确理解**：7% 是**短视频 Feed 的正常形态**。Netflix 的同类指标也在类似量级（10-15%）。**绝对值不重要，变化才重要**。

### ❌ 误解 3："这两个指标和 bn_rov/cn_rov 是一回事"
**正确理解**：bn_rov/cn_rov 是**数值指标**（赚了多少），ecs_ratio/ARP 是**健康度指标**（赚得健不健康）。前者回答"有没有涨"，后者回答"涨得对不对"。两者是正交维度，不能互相替代。

### ❌ 误解 4："看单日 ecs_ratio 差 1% 就能下结论"
**正确理解**：单日差异 < 2.9% 都是噪声（见上面的噪声基底表）。**要看 7 天趋势和"赢的天数"**，不是看单点。

---

## 参考

- Netflix 的 ECS 指标原始论文：《The Netflix Recommender System: Algorithms, Business Value, and Innovation》(ACM TMIS 2015)
- 业界综述：《Fairness and Diversity in Recommender Systems: A Survey》(arXiv 2307.04644)
- 本项目实现：`tasks/00_尾号实验/base_v3_new.sql`
