基于用户投票的排名算法(五):威尔逊区间
作者: 阮一峰
日期: 2012年3月20日
迄今为止,这个系列都在讨论,如何给出"某个时段"的排名,比如"过去24小时最热门的文章"。
但是,很多场合需要的是"所有时段"的排名,比如"最受用户好评的产品"。
这时,时间因素就不需要考虑了。这个系列的最后两篇,就研究不考虑时间因素的情况下,如何给出排名。
一种常见的错误算法是:
得分 = 赞成票 - 反对票
假定有两个项目,项目A是60张赞成票,40张反对票,项目B是550张赞成票,450张反对票。请问,谁应该排在前面?按照上面的公式,B会排在前面,因为它的得分(550 - 450 = 100)高于A(60 - 40 = 20)。但是实际上,B的好评率只有55%(550 / 1000),而A为60%(60 / 100),所以正确的结果应该是A排在前面。
Urban Dictionary就是这种错误算法的实例。
另一种常见的错误算法是
得分 = 赞成票 / 总票数
如果"总票数"很大,这种算法其实是对的。问题出在如果"总票数"很少,这时就会出错。假定A有2张赞成票、0张反对票,B有100张赞成票、1张反对票。这种算法会使得A排在B前面。这显然错误。
Amazon就是这种错误算法的实例。
那么,正确的算法是什么呢?
我们先做如下设定:
(1)每个用户的投票都是独立事件。
(2)用户只有两个选择,要么投赞成票,要么投反对票。
(3)如果投票总人数为n,其中赞成票为k,那么赞成票的比例p就等于k/n。
如果你熟悉统计学,可能已经看出来了,这是一种统计分布,叫做"二项分布"(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提出了一个修正公式,被称为"威尔逊区间",很好地解决了小样本的准确性问题。
在上面的公式中,表示样本的"赞成票比例",n表示样本的大小,表示对应某个置信水平的z统计量,这是一个常数,可以通过查表或统计软件包得到。一般情况下,在95%的置信水平下,z统计量的值为1.96。
威尔逊置信区间的均值为
它的下限值为
可以看到,当n的值足够大时,这个下限值会趋向。如果n非常小(投票人很少),这个下限值会大大小于。实际上,起到了降低"赞成票比例"的作用,使得该项目的得分变小、排名下降。
Reddit的评论排名,目前就使用这个算法。
[参考文献]
* How Not To Sort By Average Rating
(完)
文档信息
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
- 发表日期: 2012年3月20日
- 更多内容: 档案 » 算法与数学
- 购买文集: 《如何变得有思想》
- 社交媒体: twitter, weibo
- Feed订阅:
相关文章
- 2015.09.01: 理解矩阵乘法
大多数人在高中,或者大学低年级,都上过一门课《线性代数》。这门课其实是教矩阵。
- 2015.07.27: 蒙特卡罗方法入门
本文通过五个例子,介绍蒙特卡罗方法(Monte Carlo Method)。
- 2015.06.10: 泊松分布和指数分布:10分钟教程
大学时,我一直觉得统计学很难,还差点挂科。
- 2013.12.16: 朴素贝叶斯分类器的应用
生活中很多场合需要用到分类,比如新闻分类、病人分类等等。
留言(39条)
suranxu 说:
其实我觉得一个简单函数就可以解决此问题: score = 赞成比例 * min(投票数, 100)
1. 当投票数100时,score取决于赞成比例。
2. 若一个
2012年3月20日 14:47 | ∞ | 引用
suranxu 说:
2. 若一个小于100投票数的物品要排到大于100投票数且好评率为n%的物品前面,就必须有至少n个好评。或积累100个投票后,靠好评率胜出。
2012年3月20日 14:53 | ∞ | 引用
zisasign 说:
引用suranxu的发言:2. 若一个小于100投票数的物品要排到大于100投票数且好评率为n%的物品前面,就必须有至少n个好评。或积累100个投票后,靠好评率胜出。
如果我没理解错,赞成比例应该是这样计算:赞成比例 = 好评数/投票数。
则,当投票数小于100,score = (好评数/投票数)*投票数 = 好评数
当投票数大于等于100, score = (好评数/投票数)*100
因为投票数大于等于100,所以此时score应该是等于好评数乘以一个小于等于1的系数,该系数与投票数成反比。
也就是说,相同的好评数,投票数越多,得分越低。
挺好的。
2012年3月20日 15:44 | ∞ | 引用
Wesker 说:
楼主您好:
我拜读了这篇文章,收获很多.但是我对该文章对二项式分析一个地方有点质疑:
文章说"如果投票总人数为n,其中赞成票为k,那么赞成票的比例p就等于k/n。如果你熟悉统计学,可能已经看出来了,p服从一种统计分布,叫做"两项分布"(binomial distribution)。"
我觉得得票比例p不符合二项分布. 应该是 总票数为n,在得票比例为p情况下,获得赞成票的次数k的概率 符合二项分布 P(X=k) = C(n,k) * p^k * (1-p)^(n-k)
k= 0,1,2,3....n 其中C(n,k) = n!/ (k!*(n-k)!)
如果 比例p不符合二项分布,那么后面的结论就都不对了.
还望楼主帮忙分析下我的理解对不对. 谢谢!
2012年3月20日 16:51 | ∞ | 引用
dsw 说:
引用Wesker的发言:楼主您好:
我拜读了这篇文章,收获很多.但是我对该文章对二项式分析一个地方有点质疑:
文章说"如果投票总人数为n,其中赞成票为k,那么赞成票的比例p就等于k/n。如果你熟悉统计学,可能已经看出来了,p服从一种统计分布,叫做"两项分布"(binomial distribution)。"
我觉得得票比例p不符合二项分布. 应该是 总票数为n,在得票比例为p情况下,获得赞成票的次数k的概率 符合二项分布 P(X=k) = C(n,k) * p^k * (1-p)^(n-k)
k= 0,1,2,3....n其中C(n,k) = n!/ (k!*(n-k)!)
如果 比例p不符合二项分布,那么后面的结论就都不对了.
还望楼主帮忙分析下我的理解对不对. 谢谢!
嗯,应该是k服从二项分布。在计算p的置信区间时,可假设p是渐近正态的,从而算出置信区间。
2012年3月20日 18:17 | ∞ | 引用
阮一峰 说:
@Wesker:
你说得对,应该是K服从二项分布。
我对统计还是不熟,这里已经改过来了。谢谢指出。
这个地方不影响下面的结论,那些公式本来就是针对p的(二项分布的比例)。
2012年3月20日 20:50 | ∞ | 引用
knight 说:
亚马逊里面的那个例子,用户可不是只有两个选择,而是从一星到五星的评级。虽然从结果来讲也是不合适的,但是也不适用两项分布、威尔逊区间的吧。
2012年3月21日 14:34 | ∞ | 引用
Janet 说:
哥哥好哦~追你博蛮久了,偶是名大四女生,热爱写作、分享idea.之前全在门户网站的空间写blog,但到这后,自己开独立blog的想法非常强烈,我希望也能开一个像这里一样的自由独立的博~~~泪求哥哥指点一二啊。。。
前面看过如何开的日志说明,但那些对我还是难了点。。还有,请问要money吗?要向谁申请吗?申请困难吗?
2012年3月30日 10:01 | ∞ | 引用
阮一峰 说:
引用Janet的发言:自己开独立blog的想法非常强烈,我希望也能开一个像这里一样的自由独立的博~~~
如果你不懂技术,还是不要开独立Blog了,非常麻烦,还要花钱。
要是能翻墙,我非常推荐Blogger和Tumblr的服务。
2012年3月30日 18:50 | ∞ | 引用
Ralph_adu 说:
书到用时方恨少啊!
以前学概率和统计的时候感觉很枯燥,不知道学了有什么用,现在发现很多领域都要用到这些知识。如果以前在学的时候早点接触到这些需要用到这方面知识的领域时就可以更加针对性的学了,有动力,也不会感到枯燥了。得补补了~
2012年3月31日 10:18 | ∞ | 引用
yish 说:
让我对置信上下界的理解加深了,也就是说,我们在考虑用统计值来估计真实情况的时候,都应该考虑置信界限,否则在采样不够的时候,会有差别较大的判断。
2012年3月31日 20:48 | ∞ | 引用
andyshi 说:
引用爱早起的发言:好算法,我以前一直以为热门文章的算法很简单,就是挑浏览量最大的,我的wordpress博客就是这样的
最简单的就是按照浏览量的。就一个权。
除了浏览量,还需要考虑回复,文章引用,回复的引用,打分等等!
2012年4月12日 13:16 | ∞ | 引用
quady 说:
引用zisasign的发言:如果我没理解错,赞成比例应该是这样计算:赞成比例 = 好评数/投票数。
则,当投票数小于100,score = (好评数/投票数)*投票数 = 好评数
当投票数大于等于100, score = (好评数/投票数)*100
因为投票数大于等于100,所以此时score应该是等于好评数乘以一个小于等于1的系数,该系数与投票数成反比。
也就是说,相同的好评数,投票数越多,得分越低。
挺好的。
A好评数10,总投票数10,那得分是10
B好评数500,总投票数5000,得分也是10
这样到底合不合理呢
2012年4月13日 14:17 | ∞ | 引用
丕子 说:
引用suranxu的发言:2. 若一个小于100投票数的物品要排到大于100投票数且好评率为n%的物品前面,就必须有至少n个好评。或积累100个投票后,靠好评率胜出。
关键是你的那个100如何确定的?
2013年1月21日 13:35 | ∞ | 引用
kevin 说:
百度搜索排名算法找过来的,认真拜读了博主的“基于用户投票的排名算法”多篇文章,收获颇多。如果不基于用户投票,而且一个商品的评价数、评分,应该如何排名呢?
2013年1月22日 14:03 | ∞ | 引用
闲耘 说:
> 表示对应某个置信水平的z统计量,这是一个常数,可以通过查表或统计软件包得到。一般情况下,在95%的置信水平下,z统计量的值为1.96。
请问这个常数表是什么表,哪里可以得到?
我用这个算法做 了一些实践,发现有些区间边界不理想,想调整这个常数试试。
2013年10月 4日 22:34 | ∞ | 引用
suranxu 说:
引用quady的发言:A好评数10,总投票数10,那得分是10
B好评数500,总投票数5000,得分也是10
这样到底合不合理呢
如果只看这一瞬间快照的话,好像很不合理,明显A商品吃亏了。
但其实我觉得把时间跨度放长一些,这并不是一个系统性问题。一方面,如果A商品确实是一个被广泛认可的好商品(而不是一个极其小众的“好商品”),它会快速积累到更多投票(想象一个新出的电影,或者一个性价比卓越的新卖家,它的投票不不会因为默认排名不靠前就积累不到新的投票),很快就会超过B商品。另一方面,如果A商品真的就此止步于此,没有人再给它投票,如此小众的商品真的应该排在B的前面吗。比如“日常用品”频道首页到底应该排除一个劣质的马桶垫,还是排出一款非常好用便宜实惠的“宇航员太空便便吸收器”?真的要选择其一吗?
2013年10月20日 19:44 | ∞ | 引用
suranxu 说:
引用丕子的发言:关键是你的那个100如何确定的?
我...拍脑袋想的。Orz请各位学院派大大们原谅我的暴虐吧。>_
其实写100主要是它数学形式上看起来比较好看,同时100这个数基本又能满足可信性。这其实这就是一个票数少于阈值时降权的山炮模型,参数值可以调,个数也可以再加。
我想表达的是,其实一些复杂模型数学上可能很漂亮,但实际效果相对简单规则模型往往提升了了,甚至会下降,而巨大的性能消耗在真实的线上环境上很多并不适用。(其实博主的例子比较特殊,因为投票毕竟不是一个频繁行为,如果换个场景,把好评换成点击,投票换成PV呢,点击每秒都在发生,PV每秒可能成千上万了,都这么算根本吃不消呵)
2013年10月20日 20:02 | ∞ | 引用
俚语维基 说:
大家好,我在我的网站上采用了阮先生介绍的这个威尔逊区间算法,
来决定1个词条下不同定义的排位顺序。
我的网站是用python下的Django开发的,
因此实现起来也有现成的代码可用。
欢迎来参观指导。
http://liyuwiki.com/technologies.html
2014年7月 2日 10:27 | ∞ | 引用
yys 说:
请问这个常数表在哪里查的啊?能给个链接么?
引用闲耘的发言:
> 表示对应某个置信水平的z统计量,这是一个常数,可以通过查表或统计软件包得到。一般情况下,在95%的置信水平下,z统计量的值为1.96。
请问这个常数表是什么表,哪里可以得到?
我用这个算法做 了一些实践,发现有些区间边界不理想,想调整这个常数试试。
2015年7月20日 14:10 | ∞ | 引用
基于用户投票的排名算法(五):威尔逊区间相关推荐
- 投票源码程序_基于用户投票的排名算法
基于用户投票的排名算法(一):Delicious和Hacker News 互联网的出现,意味着"信息大爆炸". 用户担心的,不再是信息太少,而是信息太多.如何从大量信息之中,快速有 ...
- 转:基于用户投票的排名算法系列
互联网的出现,意味着"信息大爆炸". 用户担心的,不再是信息太少,而是信息太多.如何从大量信息之中,快速有效地找出最重要的内容,成了互联网的一大核心问题. 各种各样的排名算法,是目 ...
- 基于用户投票的排名算法
目录 基于用户投票的排名算法(一):Delicious和Hacker News 基于用户投票的排名算法(二):Reddit 基于用户投票的排名算法(三):Stack Overflow 基于用户投票的排 ...
- 基于用户投票的排名算法(一):Delicious和Hacker
作者: 阮一峰 日期: 2012年2月24日 互联网的出现,意味着"信息大爆炸". 用户担心的,不再是信息太少,而是信息太多.如何从大量信息之中,快速有效地找出最重要的内容,成了互 ...
- 基于用户投票的排名算法Reddit
基于用户投票的排名算法(二):Reddit 作者: 阮一峰 日期: 2012年3月 7日 (不好意思,这个系列中断了近两周,我会尽快在这几天,把后面几篇写完.) 上一次,我介绍了Hacker News ...
- 基于用户投票的排名算法(一):Delicious和Hacker News
互联网的出现,意味着"信息大爆炸". 用户担心的,不再是信息太少,而是信息太多.如何从大量信息之中,快速有效地找出最重要的内容,成了互联网的一大核心问题. 各种各样的排名算法,是目 ...
- 基于用户投票的排名算法(二):Reddit
基于用户投票的排名算法(二):Reddit 作者: 阮一峰 日期: 2012年3月 7日 (不好意思,这个系列中断了近两周,我会尽快在这几天,把后面几篇写完.) 上一次,我介绍了Hacker News ...
- 基于用户投票的排名算法(六):贝叶斯平均
作者: 阮一峰 日期: 2012年3月28日 (这个系列实在拖得太久,今天是最后一篇.) 上一篇介绍了"威尔逊区间",它解决了投票人数过少.导致结果不可信的问题. 举例来说,如果只 ...
- 基于用户投票的排名算法(四):牛顿冷却定律
作者: 阮一峰 日期: 2012年3月16日 这个系列的前三篇,介绍了Hacker News,Reddit和Stack Overflow的排名算法. 今天,讨论一个更一般的数学模型. 这个系列的每篇文 ...
最新文章
- slider(滑动条)控件模版,样式--用图片定义控件模版
- python项目归纳总结-python总结七
- python读取文件多行内容-python 逐行读取文件的几种方法
- Docker中应用的性能调优指南(一)- 先谈谈容器化性能调优
- 华为云牵手同舟共济伙伴 持续发力构建云核心生态圈
- MongoDB中文社区年终盛典
- Python可视化——绘制折线图
- android视频播放的代码
- linux num_fds文件描述符数量限制 too many openfiles 错误
- 学计算机要数学吗,学习计算机真的需要数学能力超强吗?
- 栈(LIFO:后进先出)
- HDU 1847 Good Luck in CET-4 Everybody!(巴什博弈论)
- 模拟城市服务器连接中断 正试着,【模拟城市5】确认DRM在线 中断不会被踢
- 80后年薪多少,才能摆脱中年危机?
- 我30岁自学编程,当上高级工程师,几度精疲力尽想放弃
- [转]数据挖掘十大经典算法
- python--socket(套接字/插口)
- mysql 外键报错_MySQL添加外键、删除外键方式,MySQL删除外键报错快速解决方案...
- 轻松解决win10不能联网问题
- 王垠 我和Google的故事
热门文章
- leetcode算法题--礼物的最大价值
- linux 修改dmi信息,如何从linux清除DMI系统事件日志?
- python 做个创越火线挂_一日一技:用Python做个能挂墙上的大钟表
- php 文件迭代对象,通过PHP中的stdClass对象进行迭代
- 大型网站技术架构(四)网站的高性能架构
- 开源图像编辑器 GIMP 开发者透露 2019 年计划
- 压力测试工具gatling安装和介绍
- vim配置@year12
- [转]Supporting OData Query Options in ASP.NET Web API 2
- 如何访问自定义键值的二维数组