IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

数学之美:Reddit评论排名算法

标点符 2012-07-12 23:03:42 累计浏览 5,944 次
本机暂存

    上一篇文章介绍了Reddit的排名算法,今天继续上一篇文章,需要学习的是reddit的评论排名算法。与文章新闻类排名不同的事,评论类的算法可能发表时间没有什么关系。

    目前很多网站采用的评论排名主要有两种,即绝对好评数(好评减去差评)和好评率(好评/总评)。这两种评价方式 都存在很明显的缺陷,以下为事例:

  • A:好评550; 差评450
  • B:好评60;差评40
  • C:好评1;差评0
  • D:好评9,差评1
  •     首先是A与B比较,A的绝对好评数是550-450=100,B的绝对好评数是60-40=20,从绝对好评数比较,A的排名应该在B的前面;A的好评率为550/(450+550)=55%,B的好评率为60/(40+60)=60%,从好评率来说B的排名要比A的排名好。

        再来比较下C与D,从好评率出发,C的好评率为100%,而D的好评率为9/(1+9)=90%,单纯从数据上看D的排名要比C的排名落后。对于评论排名上述的方法是否是我们所需要的呢?这样的计算才能更好的体现评论价值?正确的排名算法应该是怎样的?

        我们先做如下设定:

  • 每个用户的投票都是独立事件。
  • 用户只有两个选择,要么投好评,要么投差评。
  • 如果投票总人数为n,其中好评为k,那么好评率p就等于k/n。
  •     如果你熟悉统计学,可能已经看出来了,p服从一种统计分布,叫做“两项分布”(binomial distribution)。

        p越大,就代表这个项目的好评比例越高,越应该排在前面。但是,p的可信性,取决于有多少人投票,如果样本太小,p就不可信。由于p服从”两项分布”,因此我们可以计算出p的置信区间。所谓“置信区间”,就是说,以某个概率而言,p会落在的那个区间。比如,某个产品的好评率是 80%,但是这个值不一定可信。根据统计学,我们只能说,有 95% 的把握可以断定,好评率在 75% 到 85% 之间,即置信区间是[75%, 85%]。

        通过上面的分析,我们就可以推断出,如果要给一个评论进行排名,就需要考虑一下内容:

  • 计算每个评论的”好评率”
  • 计算每个”好评率”的置信区间(以 95% 的概率)。
  • 根据置信区间的下限值,进行排名。这个值越大,排名就越高。
  •     这样做的原理是,置信区间的宽窄与样本的数量有关。比如,A有 8 张赞成票,2张反对票;B有 80 张赞成票,20张反对票。这两个项目的赞成票比例都是 80%,但是B的置信区间(假定[75%, 85%])会比A(假定[70%, 90%])窄得多,因此B的置信区间的下限值(75%)会比A(70%)大,所以B应该排在A前面。

        置信区间的实质,就是进行可信度的修正,弥补样本量过小的影响。如果样本多,就说明比较可信,不需要很大的修正,所以置信区间会比较窄,下限值会比较大;如果样本少,就说明不一定可信,必须进行较大的修正,所以置信区间会比较宽,下限值会比较小。

        二项分布的置信区间有多种计算公式,最常见的是“正态区间”(Normal approximation interval),教科书里几乎都是这种方法。但是,它只适用于样本较多的情况(np > 5 且 n (1 − p) > 5),对于小样本,它的准确性很差。

        1927年,美国数学家 Edwin Bidwell Wilson 提出了一个修正公式,被称为“威尔逊区间”,很好地解决了小样本的准确性问题。Reddit 目前使用的是评论算法就是基于威尔逊得分区间 (Wilson score interval)。具体代码片段可从开放的源代码中找到,将其转化成Python代码后:

    from math import sqrt
    
    def _confidence(ups, downs):
        n = ups + downs
    
        if n == 0:
            return 0
    
        z = 1.0 #1.0 = 85%, 1.6 = 95%
        phat = float(ups) / n
        return (phat+z*z/(2*n)-z*sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
    def confidence(ups, downs):
        if ups + downs == 0:
            return 0
        else:
            return _confidence(ups, downs)

        使用到的威尔逊得分区间具体公式如下:

        原图已失效

        其中

  • p 是好评率
  • n 是总投票数
  • Z (1-α/2) 表示对应某个置信水平的z统计量,这是一个常数,可以通过查表得到。一般情况下,在 95% 的置信水平下,z统计量的值为1.96。
  •     可以公式看到,当n的值足够大时,这个下限值会趋向原图已失效。如果n非常小(投票人很少),这个下限值会大大小于原图已失效

         。实际上,起到了降低”好评率”的作用,使得该评论的得分变小、排名下降。

        威尔逊得分区并不关心一个评论的投票数,而关心好评数和投票总数或采样大小的相对关系!

        原图已失效

        上图是根据威尔逊得分区计算出来的值:一个评论有1个好评,没有差评,它的支持率是100%,但是由于数据量过小,系统还是会把它放到底部。 但如果,它有10个好评,1个差评,系统可能会有足够的信息把他放到一个有着40个好评,20个差评的评论之前。因为我们基本确认当它有了40个好评的时候,它收到的差评会少于20个。最好的一点是,一旦这个算法出错了(算法有15%的失效概率),它会很快拿到更多的数据,因为它被排到了前面。

        威尔逊得分区间不仅仅用于评论排名,它还试用于以下情景:

  • 垃圾邮件检测:看到这个内容并将它标记成垃圾邮件的百分比有多少?
  • 创建精华列表:看到这个内容并将它加星标件的百分比有多少?
  • 创建最受欢应列表:看到这个内容并将它转发给朋友的百分比有多少?
  • 说了那么多,再来看看威尔逊得分区间的缺点,从上面的分析中也很容易发现问题,即排行榜前列总是那些票数最多的项目,新项目或者冷门的项目,很难有出头机会。

        参考文章:

        http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval

        http://blog.reddit.com/2009/10/reddits-new-comment-sorting-system.html

        http://www.evanmiller.org/how-not-to-sort-by-average-rating.html

    同分类推荐文章

    1. Four Levels Of Customer Understanding (2026-05-22 21:00:00)
    2. 除法的意义 (2026-04-12 20:52:17)
    3. 第五章:共识算法 (2026-03-18 08:00:00)

    查看更多 算法 文章 →

    建议继续学习

    1. 数学之美:StackOverflow问答排名算法 (累计阅读 11,340)
    2. 数据分析中常用的数据模型 (累计阅读 7,803)
    3. Hacker News 排名算法工作原理 (累计阅读 7,400)
    4. Kindle 电子书生成工具 (累计阅读 5,041)
    5. 净推荐值(NPS)系列之一——基本原理与操作模型 (累计阅读 4,662)
    6. 房租分配问题 (累计阅读 4,501)
    7. 实时排名,其实很简单 (累计阅读 4,422)
    8. 服务器日志网站分析的原理及优缺点 (累计阅读 4,140)
    9. 面试题:火车运煤问题 (累计阅读 4,061)
    10. 基于管道模式的容器设计 (累计阅读 3,343)