Bayesian Personalized Ranking 是基于隐式反馈数据的非常通用的个性化模型,一般实现使用的是 matrix factorization 机制,利用随机梯度下降来求解。

假设用来表达训练集的三元组为 ,只需要找到“最优化”的用户的 f 维向量表征 ,positive item i 的 f 维向量表征 ,negative item j 的 f 维向量表征 , 则建模完毕。

它有以下几点优势:

  • 不关注于拟合的具体数值损失最小,而是关注于 item 的排序关系
  • 由于特殊的负采样策略,导致它的结果相对偏 High-Precision & Low-Recall
  • 因为是潜变量模型,预测只是向量的相乘,工程化性能优异

模型推导

考虑我们优化的目标( 是我们求解的任意参数,比如矩阵分解的潜向量, 代表了 user 对其他所有 item 的排序关系),它可以用贝叶斯公式表示为

假设所有的用户行为都是独立的,因此有

因此优化目标拆解成了两部分,先看第一部分,可以表示为

定义user 和 item 的内积为 user 对 item 的偏好 。 对于 这个概率,直观解释就是 是否大于 ,大于零则表示:对于用户 来说, 更偏好

但这里有个问题,这个如果直接减的话,是 non-continuous, non-differential, 所以我们需要变换一下,把 的结果用 sigmod 函数变换一下(概率化),可以写成这样

因此第一部分的优化目标就可以变成这个样子了:

对于第二部分的 ,我们将它简化为均值为0,协方差矩阵为 ,即

因此对数后验估计函数可以表示为:

上式的对于 的一阶导为:

在这里有

因此很容易得到:

也就是说,对于矩阵分解算法的参数 来说,user 的 f 维隐向量 ,以及 item 的 f 维隐向量 非常容易通过梯度上升法来求解。

实现细节

摘抄一部分C++代码

prob = sum(U(user_id, _) * (I(liked_id, _) - I(disliked_id, _)));
prob = 1 / (1 + exp(prob));
temp = U(user_id, i);
U(user_id, i) +=  alpha * (prob * (I(liked_id, i) - I(disliked_id, i)) - lamb*temp);
I(liked_id, i) += alpha * (prob * temp - rlamb * I(liked_id, i));
I(disliked_id, i) += alpha * (-prob * temp - lamb * I(disliked_id, i));

可以很清晰的看到所有的运算基于 以及 以及常数项 alpha, lambda。

negative item j 是通过抽样方式来确定的,实际在计算的过程中只考虑 positive item i,因为 negative item 很多,所以会在所有的 item 里随机抽一个, 即便是抽到了 positive item 从概率上来讲也不会对计算速度和精度有太大影响,但速度会加快很多。(想象一下电商推荐场景,不点击的长尾商品很多)

在 51Talk 老师推荐的实际应用场景又有不同,我们只针对有评分(positive)的老师进行训练,来更新用户和老师的向量,实际效果更佳优异。