因为一直在做推荐系统和点击率预估排序相关工作,所以一直想用一种粗糙但直观的方式来做一个推荐系统的示例,如果能有一定的工程实现价值就更好。最近突然有了这样一个基于 Beta 分布的想法,所以记录下来。当然,这个想法可能不是我的专利,可能已经有人想到过了。
Beta 分布的直观理解
Beta 分布 是一组定义在 $(0, 1)$ 之间的连续概率分布,有两个参数 $\alpha, \beta > 0$
。随机变量 $X$
服从参数为 $\alpha$
, $\beta$
的 Beta 分布通常记作 $X \sim \text{Be}(\alpha, \beta)$
。
在理解 Beta 分布之前,我们先回顾一下二项分布。
二项分布说的是 $n$ 个 i.i.d 的二项伯努利试验中成功次数的离散概率分布。根据二项分布,我们可以用似然的办法,通过有限次的实验,推断伯努利实验成功的概率。比如有一枚多少有些不均匀的硬币,我们多次抛硬币,将硬币呈现正面记为成功,要求成功的概率,就可以用似然的办法结合二项分布来求解。现在的问题是,在只有很少次数的实验时,利用二项分布估计的概率可能会很不准。一个极端的例子,如果我们只做了一次实验,硬币落下后呈现正面。那么根据二项分布估计出来的概率将会是 $P = 1$
。这显然是不对的。
这时候,Beta 分布就该出场了。Beta 分布可以看做是二项分布概率的概率分布。怎么理解呢?我们来继续看抛硬币的例子。
我们知道,虽然每一枚硬币都多少有些不均匀,但是总体上,硬币落下呈现正面的概率是 $0.5$
左右。因此,不论如何,一枚多少有些不均匀的硬币,抛硬币得到正面的概率应该和 $0.5$
相去不远。具体到多次 i.i.d 的二项伯努利试验上,就是当 $N$
足够大时,$2N$
次二项伯努利试验中,得到正面的次数应该接近 $N$
。我们假设 $N = 1000$
,这意味着,在 $2000$
次二项伯努利试验中,大约会获得 $A = 1000$
次正面和 $B = 1000$
次反面。于是,我们初始化 Beta 分布 $\text{Be}(A, B) = \text{Be}(1000, 1000)$
。接着,我们用这枚多少有些不均匀的硬币开始若干次二项伯努利试验,比如说 50 次。在 50 次试验中,我们得到了 $a = 19$
次正面,$b = 31$
次反面。于是我们更新 Beta 分布的参数 $\alpha \gets A + a$
以及 $\beta \gets B + b$
,于是得到新的 Beta 分布 $\text{Be}(1019, 1031)$
。该 Beta 分布的均值是
$$ \frac{\alpha}{\alpha + \beta} = \frac{1019}{1019 + 1031} = \frac{1019}{2050} \approx 0.497. $$
于是我们说,这枚多少有些不均匀的硬币在二项伯努利试验中得到正面的概率是 $P = 0.497$
;与此同时,就这 50 次试验,根据二项分布推算出来的概率是 $P = 0.38$
。显然,根据 Beta 分布均值推算出来的概率相对根据二项分布推算出来的概率要显著接近 $P = 0.5$
的先验值。
总结一下,Beta 分布可以看做是二项分布概率的概率分布。当我们对二项分布概率已经有一个相对比较靠谱的先验知识的时候,我们可以据此设定 Beta 的参数,然后在后续 i.i.d 的二项伯努利试验过程中,依赖 Beta 分布共轭先验的特性,对 Beta 分布的参数进行更新,最后以 Beta 分布均值作为二项分布概率的估计。
基于 Beta 分布的用户画像
推荐系统的一侧是用户,描述用户的方法是用户画像。我们可以用 Beta 用户来做基于 Tag 的用户画像。在这里,对于某个用户来说:
- Beta 分布中的
$\alpha_i$
是用户在编号为$i$
的 Tag 下的点击次数的反映; - 相应地,
$\beta_i$
则是用户在编号为$i$
的 Tag 下展示未点击次数的反应。
于是,用户画像的策略可以简单叙述如下:
- 对于某个用户,使用先验知识(比如,全体用户的平均兴趣),对
$\{(\alpha_i, \beta_i)\}$
序列进行初始化。 - 根据用户的行为(展示和点击),更新该序列
- 用户点击了具有编号为
$i$
,$j$
,$k$
Tag 的物品进行了点击,则对$\alpha_i$
,$\alpha_j$
,$\alpha_k$
分别自增 1; - 用户展示未点击具有编号为
$i$
,$j$
,$k$
Tag 的物品进行了点击,则对$\beta_i$
,$\beta_j$
,$\beta_k$
分别自增 1。
- 用户点击了具有编号为
基于 Beta 分布的点击率预估
对于具有画像 $\{(\alpha_i, \beta_i)\}$
的用户进行推荐时,我们要对待推荐的物品进行点击率预估。假设某物品同时具有编号为 $i$
, $j$
, $k$
的 Tag,假设各个 Tag 对点击行为的贡献都相同——这是一个很强的假设,但对于示例方案来说无关紧要,则用户对该物品的点击概率可以预估为:
$$P_{\text{click}} = 1 - \frac{\beta_i}{\alpha_i + \beta_i} \times \frac{\beta_j}{\alpha_j + \beta_j} \times \frac{\beta_k}{\alpha_k + \beta_k}.$$
而后,我们可以根据各个物品的预估点击率对物品进行排序,然后推荐给用户。
总结
这是一个近乎「儿戏」的推荐方案,但在实践上并非完全无用。说它儿戏,是因为它只考虑了单个用户的历史行为,而没有考虑其他所有对推荐有帮助的因素——比如其他用户的行为(可做协同过滤),比如推荐结果多样性。但是,在没有这些其他因素的情况下,这种方案可以起到过渡方案的作用。对,我说的就是在新用户、新物品冷启动的时候,这种方案简单易实现,值得一试。