矩陣分解#
矩陣分解 (Matrix Factorization) 是協同過濾的進階方法,通過將用戶-物品矩陣分解為低維隱因子向量,解決稀疏性問題。
基本原理#
分解目標#
將 m × n 的用戶-物品評分矩陣 R 分解為兩個低維矩陣:
R(m×n) ≈ P(m×k) × Q(k×n)^T
其中:
- P:用戶隱因子矩陣,每個用戶對應 k 維向量
- Q:物品隱因子矩陣,每個物品對應 k 維向量
- k:隱因子數量(通常 10~200)預測評分#
r̂(u,i) = p_u · q_i = Σ(p_uk × q_ik)隱因子可以理解為潛在的「主題」或「特徵」,如電影的動作程度、愛情程度等。
SVD 及其變體#
基礎 SVD#
損失函式:
L = Σ(r_ui - p_u · q_i)² + λ(||p_u||² + ||q_i||²)- 第一項:預測誤差
- 第二項:正則化,防止過擬合
SVD++#
加入隱式反饋:
r̂(u,i) = μ + b_u + b_i + q_i · (p_u + |N(u)|^(-1/2) Σ y_j)
其中:
- μ:全局平均評分
- b_u:用戶偏差
- b_i:物品偏差
- N(u):用戶 u 有過行為的物品集合
- y_j:物品 j 的隱式特徵向量SVD++ 考慮了用戶「看過什麼」這一隱式資訊,即使沒有評分,瀏覽行為也能提供資訊。
TimeSVD++#
考慮時間因素:
r̂(u,i,t) = μ + b_u(t) + b_i(t) + q_i · p_u(t)用戶偏好和物品熱度都會隨時間變化。
優化演算法#
隨機梯度下降 (SGD)#
for epoch in range(num_epochs):
for u, i, r in training_data:
error = r - predict(u, i)
# 更新用戶向量
P[u] += lr * (error * Q[i] - reg * P[u])
# 更新物品向量
Q[i] += lr * (error * P[u] - reg * Q[i])交替最小二乘 (ALS)#
ALS 是 Facebook 推薦系統採用的主要方法,更適合分布式計算。
核心思想:交替固定一個矩陣,優化另一個矩陣。
1. 初始化 Q 為隨機矩陣
2. 固定 Q,求解 P = R × Q × (Q^T × Q + λI)^(-1)
3. 固定 P,求解 Q
4. 重複 2-3 直到收斂ALS 優點
- 每一步都有解析解,計算穩定
- 天然可並行:每個用戶/物品的更新互不依賴
- 適合處理大規模稀疏矩陣
SGD vs ALS#
| 維度 | SGD | ALS |
|---|---|---|
| 收斂速度 | 較慢 | 較快(稀疏資料) |
| 並行化 | 困難 | 容易 |
| 實現複雜度 | 簡單 | 中等 |
| 適用場景 | 顯式評分 | 隱式反饋 |
隱式反饋處理#
One-Class 問題#
實際推薦系統中,評分資料很少,更多的是隱式反饋(點擊、瀏覽、購買)。
| 反饋類型 | 特點 | 示例 |
|---|---|---|
| 顯式反饋 | 用戶明確表達喜好 | 評分、點讚 |
| 隱式反饋 | 只有正樣本,缺少負樣本 | 點擊、購買 |
Weighted-ALS#
針對隱式反饋的改進:
L = Σ c_ui × (r_ui - p_u · q_i)² + λ(||P||² + ||Q||²)
其中:
- r_ui = 1(有行為)或 0(無行為)
- c_ui = 1 + α × 行為次數(置信度)行為次數越多,置信度越高。預設 α = 40。
負樣本採樣#
由於沒有明確的負樣本,需要構造:
| 方法 | 說明 | 效果 |
|---|---|---|
| 隨機採樣 | 均勻隨機選擇無行為物品 | 一般 |
| 熱門採樣 | 按物品熱度採樣 | 較好 |
| 曝光採樣 | 從曝光未點擊中採樣 | 最好 |
熱門採樣的邏輯:熱門物品用戶更可能知道其存在,如果沒有行為,更可能是真正的負樣本。
BPR: 面向排序的矩陣分解#
動機#
傳統矩陣分解優化的是評分預測準確度,但推薦的最終目標是排序正確。
BPR 優化目標#
max Σ log σ(r̂_uij) - λ||Θ||²
其中:
- r̂_uij = r̂_ui - r̂_uj
- (u, i, j):用戶 u 對物品 i 有正反饋,對物品 j 無反饋
- σ:sigmoid 函式BPR 直接優化「正樣本排在負樣本前面」的概率。
BPR 訓練流程#
for epoch in range(num_epochs):
for u, i, j in sample_triplets():
x_uij = predict(u, i) - predict(u, j)
gradient = sigmoid(-x_uij)
# 更新參數
update_parameters(u, i, j, gradient)評估指標:AUC#
AUC = Σ I(r̂_ui > r̂_uj) / |positive| × |negative|AUC 衡量正樣本排在負樣本前面的概率。
向量檢索#
問題#
矩陣分解得到用戶和物品的隱因子向量後,如何高效找到最相似的物品?
解決方案:近似最近鄰 (ANN)#
| 工具 | 特點 | 適用場景 |
|---|---|---|
| Faiss | Facebook 開源,支援動態更新 | 通用推薦 |
| Annoy | Spotify 開源,輕量級 | 中小規模 |
| NMSLIB | 高性能,多種演算法 | 大規模搜尋 |
Faiss 示例
import faiss
# 構建索引
d = 128 # 向量維度
index = faiss.IndexFlatL2(d) # L2 距離
index.add(item_vectors) # 添加物品向量
# 查詢最相似的 k 個物品
k = 10
D, I = index.search(user_vector, k)聚類加速#
另一種方法是先對物品向量聚類:
1. 對物品向量進行 K-means 聚類
2. 計算用戶向量與每個聚類中心的相似度
3. 選擇相似度最高的聚類
4. 從選中的聚類中選擇具體物品優點:可以控制推薦多樣性。
工程實踐#
模型訓練#
| 工具 | 語言 | 特點 |
|---|---|---|
| Spark ALS | Scala | 分布式,適合大規模 |
| LightFM | Python | 支援混合特徵 |
| Implicit | Python | 專注隱式反饋 |
| QMF | C++ | Quora 開源,單機高性能 |
QMF 性能:單機(32 核、244G 記憶體)20 分鐘完成 10 億非零元素的矩陣分解。
模型更新策略#
| 策略 | 頻率 | 優點 | 缺點 |
|---|---|---|---|
| 全量更新 | 每天 | 準確 | 計算量大 |
| 增量更新 | 每小時 | 及時 | 可能累積誤差 |
| 混合策略 | - | 平衡 | 實現複雜 |
總結#
| 要點 | 說明 |
|---|---|
| 核心思想 | 將用戶和物品映射到低維隱因子空間 |
| SVD++ | 加入隱式反饋和偏置項 |
| ALS | 交替優化,適合分布式計算 |
| Weighted-ALS | 處理隱式反饋,使用置信度加權 |
| BPR | 面向排序優化,直接優化 AUC |
| 向量檢索 | 使用 ANN 加速相似向量查找 |