工程實踐#
推薦系統的落地需要解決許多工程問題,本章介紹資料採集、實時推薦、實驗平台和服務化等實踐經驗。
資料採集#
採集要素#
| 要素 | 說明 | 示例 |
|---|
| 用戶標識 | 唯一識別用戶 | user_id、device_id、cookie |
| 行為類型 | 用戶做了什麼 | 曝光、點擊、購買、收藏 |
| 行為物件 | 作用於什麼物品 | item_id |
| 時間戳 | 什麼時候發生 | timestamp |
| 上下文 | 發生的環境 | 頁面、位置、設備 |
埋點規範#
{
"event_type": "click",
"user_id": "u123456",
"item_id": "i789",
"timestamp": 1706313600000,
"page_id": "home",
"position": 3,
"recommend_id": "rec_xxx",
"device": {
"os": "iOS",
"version": "17.0"
}
}
recommend_id 非常重要,用於關聯曝光和後續行為,追蹤推薦效果。
資料質量保障#
| 問題 | 影響 | 解決方案 |
|---|
| 資料丟失 | 訓練資料不完整 | 多端上報、本地快取重傳 |
| 資料延遲 | 特徵更新不及時 | 流批一體架構 |
| 資料錯誤 | 模型效果下降 | 資料校驗、異常監控 |
| 重複資料 | 統計偏差 | 去重機制 |
去重策略#
內容去重:Simhash#
處理相似內容,避免推薦重複新聞:
1. 對文本分詞,計算每個詞的權重
2. 每個詞雜湊成二進位向量,0 變成 -1
3. 加權求和,正數變 1,負數變 0
4. 得到 Simhash 指紋
特點:
- 相似內容的 Simhash 相近
- 計算漢明距離判斷相似度
- 計算效率高
用戶去重:Bloom Filter#
防止重複推薦已看過的內容:
1. 準備長度為 m 的二進位向量
2. 使用 k 個獨立雜湊函式
3. 每個已推薦物品雜湊到 k 個位置,設為 1
4. 查詢時,k 個位置都為 1 則認為已推薦過
Bloom Filter 有一定的誤判率(可能把未推薦的判斷為已推薦),但可以接受。
實時推薦#
三個層次#
| 層次 | 說明 | 難度 |
|---|
| 給得及時 | 服務響應快 | 基本要求 |
| 用得及時 | 特徵實時更新 | 中等 |
| 改得及時 | 模型實時更新 | 困難 |
實時架構#
用戶行為 → Kafka → 流計算 → 特徵更新 → 在線服務
↓
模型更新
↓
推薦結果更新
增量更新 Item-CF#
當用戶產生新行為時:
增量更新邏輯
輸入:用戶 u 對物品 i 產生行為
步驟:
1. 取出用戶歷史行為物品列表 [j1, j2, ...]
2. 對每個 j:
- 增加 (i, j) 的共現次數
- 增加 i 的評分用戶數
3. 重新計算所有相關物品對的相似度
4. 更新推薦結果
效率優化#
| 方法 | 說明 |
|---|
| 剪枝 | 相似度穩定後不再更新(Hoeffding 不等式) |
| 滑窗 | 只保留最近 K 條行為 |
| 採樣 | 對高頻行為降採樣 |
| 合併 | 批量處理多條行為再更新 |
| 快取 | 熱門資料放入快取 |
實驗平台#
為什麼需要實驗平台#
資料驅動的核心是做對比實驗,科學地評估改進效果。
A/B 測試三要素#
| 要素 | 說明 |
|---|
| 流量 | 用戶訪問,實驗樣本來源 |
| 參數 | 不同策略或模型的配置 |
| 結果 | 日誌記錄,分析實驗效果 |
分層實驗架構#
Google 的分層實驗框架:
全部流量
↓
┌───────┴───────┐
域 1 域 2
↓ ↓
層 1 → 桶 1-5 獨立實驗
↓
層 2 → 桶 1-5
↓
層 3 → 桶 1-5
核心概念:
| 概念 | 說明 |
|---|
| 域 (Domain) | 流量的劃分 |
| 層 (Layer) | 參數子集的測試 |
| 桶 (Bucket) | 實驗組和對照組 |
流量分配#
def get_bucket(user_id, layer_id, n_buckets=1000):
"""
計算用戶落入哪個桶
- 同一用戶在同一層始終落入同一桶(體驗一致)
- 不同層的分配相互獨立(無偏置)
"""
hash_key = f"{user_id}_{layer_id}"
hash_value = md5(hash_key.encode()).hexdigest()
return int(hash_value, 16) % n_buckets
實驗規模估算#
Google 公式:
N >= 10.5 × (s/θ)²
其中:
- s:指標標準差
- θ:希望檢測的敏感度(如 2% 的 CTR 變化)
這個規模保證 90% 的統計功效。
服務化#
在線服務要求#
| 要求 | 指標 |
|---|
| 延遲 | P99 < 100ms |
| 可用性 | 99.99% |
| QPS | 根據業務量級 |
微服務架構#
API Gateway
↓
┌───┴───┐
召回服務 排序服務
↓ ↓
Redis 模型服務
模型部署#
| 方式 | 適用場景 |
|---|
| 嵌入式 | 小模型,直接加載到服務行程 |
| RPC 服務 | 大模型,獨立部署 |
| TensorFlow Serving | TF 模型標準化部署 |
| Triton | NVIDIA GPU 推理服務 |
開源工具#
演算法層#
| 任務 | 工具 |
|---|
| 文本處理 | FastText、Gensim、LightLDA |
| 協同過濾 | Surprise、Implicit |
| 矩陣分解 | QMF、Spark ALS |
| 深度學習 | TensorFlow、PyTorch |
| 向量檢索 | Faiss、Annoy、NMSLIB |
平台層#
| 任務 | 工具 |
|---|
| 消息佇列 | Kafka |
| 流計算 | Flink、Storm |
| 批處理 | Spark |
| 存儲 | Redis、Cassandra、HBase |
| 搜尋引擎 | ElasticSearch |
完整推薦系統#
| 項目 | 語言 | 特點 |
|---|
| LensKit | Java | 學術界常用 |
| Surprise | Python | 簡單易用,適合學習 |
| RecBole | Python | 深度學習推薦框架 |
建議選擇各個模組的開源項目,自己組合集成,而不是使用大而全的框架。這樣更容易診斷問題和優化。
團隊組建#
最小配置#
| 角色 | 數量 | 職責 |
|---|
| 演算法工程師 | 1-2 | 資料分析、模型訓練、效果評估 |
| 後端工程師 | 2 | 推薦服務、API 開發 |
| 運維工程師 | 1-2 | 資料採集、日誌管理 |
工程師核心素質#
| 素質 | 說明 |
|---|
| 工程能力 | 快速交付高效少 Bug 的程式碼 |
| 理論基礎 | 能看懂論文,理解演算法原理 |
| 可視化思維 | 將資料規律直觀呈現 |
| 要點 | 說明 |
|---|
| 資料採集 | 規範埋點,保障資料質量 |
| 去重策略 | Simhash 內容去重,Bloom Filter 用戶去重 |
| 實時推薦 | 三個層次:服務實時、特徵實時、模型實時 |
| 實驗平台 | 分層實驗,無偏流量分配 |
| 服務化 | 低延遲、高可用、可降級 |
| 開源工具 | 按模組選擇,自己組合 |