Skill 寫法圖鑑

algo-rank-wilson

asgard-ai-platform | 資料與分析 | 原文 | MIT

用 Wilson 信賴下界依正面比例排名並修正樣本數

中文翻譯

---
name: "algo-rank-wilson"
description: "計算 Wilson Score 信賴區間,依正面比例排名並修正樣本數的影響。當使用者需要依評分替產品排名、依認同率排序內容、或建立考慮樣本數的「最佳評分」榜單時使用,即使他們說的是「依星等排名」、「評論很少的最佳評分」或「經信賴度調整的評分」也一樣。"
metadata:
  category: "WP-44 排名演算法"
  tags: ["ranking", "wilson-score", "confidence-interval", "rating"]
---

# Wilson Score 排名

## 概述

Wilson Score 區間給出「真實正面評價比例」的信賴下界。和簡單平均不同,它會懲罰評分數少的項目,避免只有 1 則 5/5 評論的項目,排在有 1000 則評論、4.8/5 的項目前面。每個項目的計算是 O(1)。

## 何時使用

**觸發條件:**
- 評論數差異很大時,依使用者評分替項目排名
- 建立對評論多的項目公平的「最高評分」或「best of」榜單
- 用信賴度來排序二元回饋(讚/倒讚)

**何時不要用:**
- 連續型分數(改用貝氏平均)
- 比較樣本數差不多的項目時(簡單平均就夠了)

## 演算法

```
鐵律:樣本數不同時,絕對不要用簡單平均排名
1 則評論的 5.0 平均,並不比 1000 則評論的 4.8 好。
Wilson Score 的下界把樣本的不確定性算進去了:
評分少的項目會得到「較低」的下界,
正確反映我們對它真實品質的不確定。
```

### 階段 1:輸入驗證
每個項目要蒐集:正面評分數(p)、總評分數(n)。星等評分要轉成二元(例如 4-5 星 = 正面)。
**關卡:** 所有項目 n > 0、已選定信賴水準(通常是 95%,z=1.96)。

### 階段 2:核心演算法
1. 計算觀察到的比例:p̂ = positive / total
2. Wilson 下界:(p̂ + z²/2n - z × √(p̂(1-p̂)/n + z²/4n²)) / (1 + z²/n)
3. 依 Wilson 下界由高到低排名(對真實品質的保守估計)

### 階段 3:驗證
檢查:正面評論多的項目,要排在比例相同但評論少的項目前面。評論非常少的項目有被適度懲罰。
**關卡:** 人工檢視排名符合直覺。

### 階段 4:輸出
回傳排好名的項目,附上分數和信賴區間。

## 輸出格式

```json
{
  "rankings": [{"item": "Product_A", "wilson_lower": 0.89, "positive": 950, "total": 1000, "proportion": 0.95}],
  "metadata": {"confidence": 0.95, "z": 1.96, "items_ranked": 500}
}
```

## 範例

### 輸入輸出範例
**輸入:** 項目 A:1 正面 / 共 1(100%)。項目 B:950 正面 / 共 1000(95%)。
**預期:** B 排名較高。Wilson 下界:A ≈ 0.05、B ≈ 0.94。單一一則評論幾乎給不了任何信心。

### 邊界情況
| 輸入 | 預期 | 原因 |
|-------|----------|-----|
| 0 則評論 | 無法排名 | n=0,沒有定義。排除或給最低分 |
| 0 正面,共 100 | 分數非常低 | 真的是爛項目,信心很高 |
| 100 萬正面,共 100 萬 | 下界 ≈ 1.0 | 樣本龐大,對 100% 的信心很高 |

## 常見陷阱

- **二元轉換**:5 星評分的話,正面/負面的門檻很重要。4 星以上算正面?還是 3 星以上?不同門檻會產生不同排名。
- **不適用連續資料**:Wilson Score 是給比例(二元結果)用的。連續評分要用帶先驗的貝氏平均。
- **冷啟動**:沒有評論的新項目沒辦法排名。可以設最低評論數門檻,或用貝氏平滑。
- **信賴水準的選擇**:信賴度越高(99%),對小樣本的懲罰越重。95% 是標準,但要依你的使用情境調整。
- **依下界排序是保守的**:這個做法偏袒知名項目。如果是為了探索發現,可以考慮也提升上界高的項目(潛在的遺珠)。

## 腳本

| 腳本 | 說明 | 用法 |
|--------|-------------|-------|
| `scripts/wilson_score.py` | 計算 Wilson score 區間並替項目排名 | `python scripts/wilson_score.py --help` |

執行 `python scripts/wilson_score.py --verify` 可以跑內建的健全性測試。

## 參考資料

- 貝氏平均的替代方案,見 `references/bayesian-average.md`
- Reddit 的排名演算法(以 Wilson 為基礎),見 `references/reddit-ranking.md`

英文原文

---
name: "algo-rank-wilson"
description: "Calculate Wilson Score confidence intervals for ranking items by positive proportion with sample size correction. Use this skill when the user needs to rank products by ratings, sort content by approval rate, or build a 'best rated' list that accounts for sample size — even if they say 'rank by star rating', 'best rated with few reviews', or 'confidence-adjusted rating'."
metadata:
  category: "WP-44 排名演算法"
  tags: ["ranking", "wilson-score", "confidence-interval", "rating"]
---

# Wilson Score Ranking

## Overview

Wilson Score interval provides a lower confidence bound on the true proportion of positive ratings. Unlike simple averages, it penalizes items with few ratings, preventing a 5/5 review item (1 review) from outranking a 4.8/5 item (1000 reviews). Computes in O(1) per item.

## When to Use

**Trigger conditions:**
- Ranking items by user ratings when review counts vary widely
- Building "top rated" or "best of" lists that are fair to well-reviewed items
- Sorting binary feedback (upvote/downvote) with confidence

**When NOT to use:**
- For continuous scores (use Bayesian average instead)
- When comparing items with similar sample sizes (simple average suffices)

## Algorithm

```
IRON LAW: Never Rank by Simple Average When Sample Sizes Differ
A 5.0 average from 1 review is NOT better than 4.8 from 1000 reviews.
Wilson Score lower bound accounts for sample uncertainty:
Items with few ratings get a LOWER bound, properly reflecting our
uncertainty about their true quality.
```

### Phase 1: Input Validation
Collect per item: number of positive ratings (p), total ratings (n). For star ratings, convert to binary (e.g., 4-5 stars = positive).
**Gate:** n > 0 for all items, confidence level chosen (typically 95%, z=1.96).

### Phase 2: Core Algorithm
1. Compute observed proportion: p̂ = positive / total
2. Wilson lower bound: (p̂ + z²/2n - z × √(p̂(1-p̂)/n + z²/4n²)) / (1 + z²/n)
3. Rank by Wilson lower bound descending (conservative estimate of true quality)

### Phase 3: Verification
Check: items with many positive reviews rank above items with few reviews and same proportion. Items with very few reviews are appropriately penalized.
**Gate:** Ranking intuitively correct on manual inspection.

### Phase 4: Output
Return ranked items with scores and confidence intervals.

## Output Format

```json
{
  "rankings": [{"item": "Product_A", "wilson_lower": 0.89, "positive": 950, "total": 1000, "proportion": 0.95}],
  "metadata": {"confidence": 0.95, "z": 1.96, "items_ranked": 500}
}
```

## Examples

### Sample I/O
**Input:** Item A: 1 positive / 1 total (100%). Item B: 950 positive / 1000 total (95%).
**Expected:** B ranks higher. Wilson lower: A ≈ 0.05, B ≈ 0.94. The single review gives almost no confidence.

### Edge Cases
| Input | Expected | Why |
|-------|----------|-----|
| 0 reviews | Cannot rank | n=0, undefined. Exclude or assign minimum |
| 0 positive, 100 total | Very low score | Genuinely bad item, high confidence |
| 1M positive, 1M total | Lower bound ≈ 1.0 | Massive sample, high confidence in 100% |

## Gotchas

- **Binary conversion**: For 5-star ratings, the positive/negative threshold matters. 4+ stars as positive? 3+ stars? Different thresholds produce different rankings.
- **Not for continuous data**: Wilson Score is for proportions (binary outcomes). For continuous ratings, use Bayesian average with a prior.
- **Cold start**: New items with zero reviews can't be ranked. Use a minimum review threshold or Bayesian smoothing.
- **Confidence level choice**: Higher confidence (99%) penalizes small samples more aggressively. 95% is standard but tune for your use case.
- **Sorting by lower bound is conservative**: This approach favors well-known items. For discovery/exploration, consider also boosting items with high upper bounds (potential hidden gems).

## Scripts

| Script | Description | Usage |
|--------|-------------|-------|
| `scripts/wilson_score.py` | Compute Wilson score interval and rank items | `python scripts/wilson_score.py --help` |

Run `python scripts/wilson_score.py --verify` to execute built-in sanity tests.

## References

- For Bayesian average alternative, see `references/bayesian-average.md`
- For Reddit's ranking algorithm (Wilson-based), see `references/reddit-ranking.md`