在推荐系统的重排阶段,我们常面临结果同质化问题——精排结果相似物料扎堆,导致用户体验单调。行列式点过程(Determinantal Point Processes, DPP)通过数学建模相关性与多样性的平衡,成为解决该问题的经典方案。
一、DPP的核心思想
DPP将推荐列表视为一个点过程,其核心是计算子集出现的概率。给定候选集 ( Z )(精排输出的Top-N物料),DPP定义子集 ( Y \subseteq Z ) 出现的概率为:
P ( Y ) ∝ det ( L Y ) P(Y) \propto \det(L_Y) P(Y)∝det(LY)
其中 ( L ) 是核矩阵(Kernel Matrix),( L_Y ) 是 ( L ) 的 ( Y ) 对应的子矩阵。行列式 (\det(L_Y)) 的几何意义是向量集合构成的超平行多面体体积:
- 体积越大 → 向量差异性越大 → 推荐多样性越强
- 对角线元素 L i i L_{ii} Lii 表示物料 i i i 的质量(如CTR得分)
- 非对角线元素 L i j L_{ij} Lij 表示物料 i i i 与 j j j 的相似度
关键公式(核矩阵构造):
L = Diag ( r ) ⋅ S ⋅ Diag ( r ) L = \text{Diag}(\mathbf{r}) \cdot S \cdot \text{Diag}(\mathbf{r}) L=Diag(r)⋅S⋅Diag(r)
- r \mathbf{r} r:物料质量分向量(如精排得分)
- S S S:物料相似度矩阵, S i j = cos ( emb i , emb j ) S_{ij} = \text{cos}(\text{emb}_i, \text{emb}_j) Sij=cos(embi,embj)
二、核矩阵 ( L ) 的工程实现
1. 基础构造法
# 输入:精排结果物料集合 Z,包含每个物料的embedding和得分
def build_kernel_matrix(Z):
r = [item.score for item in Z] # 质量分向量
S = cosine_similarity([item.embedding for item in Z]) # 相似度矩阵
L = np.diag(r) @ S @ np.diag(r) # Diag(r) * S * Diag(r)
return L
缺陷:( S ) 的余弦相似度可能为负,导致 ( L ) 非正定。
2. 改进方案(文档式6-29)
高斯核保证正定性
S i j = exp ( − dist ( i , j ) 2 2 σ 2 ) S_{ij} = \exp\left(-\frac{\text{dist}(i,j)^2}{2\sigma^2}\right) Sij=exp(−2σ2dist(i,j)2)
3. 个性化加权(华为pDPP)
L i j = r i ⋅ r j ⋅ S i j ⋅ ϕ u L_{ij} = r_i \cdot r_j \cdot S_{ij} \cdot \color{red}{\phi_u} Lij=ri⋅rj⋅Sij⋅ϕu
ϕ u \phi_u ϕu 为用户个性化权重
三、贪婪求解:Fast Greedy MAP
直接枚举所有子集计算 (\det(L_Y)) 是指数级复杂度。Fast Greedy MAP算法(复杂度 (O(N^2 K)))是工业界首选:
def fast_greedy_map(L, K):
Y = [] # 已选集合
for _ in range(K):
max_gain = -np.inf
best_item = None
for j in range(len(L)):
if j in Y: continue
gain = compute_marginal_gain(L, Y, j) # 计算边际增益
if gain > max_gain:
max_gain = gain
best_item = j
Y.append(best_item)
update_cached_vectors(L, Y) # 更新中间变量(避免重复计算)
return Y
关键优化:利用Cholesky分解的增量更新(见文档公式6-47, 6-48):
c j = 1 L j j − ∥ v j ∥ 2 ( L Y , j − V T v j ) d j = L j j − ∥ v j ∥ 2 \begin{align*} \mathbf{c}_j &= \frac{1}{\sqrt{L_{jj} - \|\mathbf{v}_j\|^2}} \left( L_{Y,j} - V^T \mathbf{v}_j \right) \\ d_j &= \sqrt{L_{jj} - \|\mathbf{v}_j\|^2} \end{align*} cjdj=Ljj−∥vj∥21(LY,j−VTvj)=Ljj−∥vj∥2
其中 ( V ) 是Cholesky分解的三角矩阵,(\mathbf{v}_j) 是中间向量。
DPP 算法流程
四、实际应用技巧
- 特征工程:
- 质量分 ( r i r_i ri ):精排CTR得分 × 时长增益系数
- Embedding:双塔模型输出的物料向量
- 负样本策略:
- 曝光未点击物料作为Hard Negative
- 随机采样物料作为Easy Negative(比例100:1)
- 在线服务:
- Faiss加速相似矩阵计算
- 核矩阵 ( L ) 的增量更新(新物料动态插入)
五、效果对比(Hulu案例)
算法 | 多样性↑ | 点击率↑ | 时长↑ |
---|---|---|---|
精排基线 | 0.82 | 0.125 | 45s |
DPP重排 | 0.93 | 0.127 | 51s |
多样性指标:物料类别熵(Entropy),值越大越多样
六、总结
DPP的数学美感与工程实用性使其成为重排阶段的核心算法:
- 优势:严格建模相关性与多样性的trade-off
- 挑战:核矩阵构造的合理性、大规模计算的优化
- 趋势:与强化学习(如RNN重排)、多任务学习的结合