什么是一个更好的方法来排序由一个5星级?

我正在尝试使用一个五星级系统根据客户评分对一系列产品进行分类。我正在建立这个网站没有很多评级,并继续增加新的产品,所以它通常会有一些产品与低数量的评级。

我尝试使用平均星级评分,但是当评分数量较少时,该算法失败了。

举个例子,一个产品有3x5星级评价会比一个产品有100x5星级评价和2x2星级评价表现得更好。

难道第二个产品不应该显示得更高,因为它在统计学上更值得信赖,因为它有更多的评级吗?

24190 次浏览

你可以用 中位数代替算术平均值来排序。在这种情况下,两个例子的中位数都是5,所以两个排序算法的权重是相同的。

您可以使用 模式来达到同样的效果,但中值可能是一个更好的主意。

如果你想给100个5星评级的产品分配额外的权重,你可能想采用某种加权模式,用相同的中位数分配更多的权重,但是用更多的整体投票。

在2015年之前,互联网电影数据库(IMDb)公开列出了用于排名他们的 250强电影名单的公式。引用如下:

排名前250的书籍的计算公式是 真贝叶斯估计真贝叶斯估计:

weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C

地点:

  • R = 电影的平均值(平均值)
  • 这部电影的票数
  • M = 进入前250名所需的最低票数(目前为25000票)
  • C = 整个报告的平均投票数(目前为7.0)

对于前250名,只考虑普通选民的投票。

It's not so hard to understand. The formula is:

rating = (v / (v + m)) * R +
(m / (v + m)) * C;

在数学上可以简化为:

rating = (R * v + C * m) / (v + m);

这些变量是:

  • 项目自己的等级。R 是项目投票的平均数。(例如,如果一个项目没有投票权,它的 R 是0。如果有人给它5颗星,R 就变成了5。如果别人给它1星,R 就变成3,这是 [1, 5]的平均值。等等。)
  • C-平均项目的评级。找到数据库中每个项目的 R,包括当前项目,然后取它们的平均值,即 C (假设数据库中有4个项目,它们的评分是 [2, 3, 5, 5]。C 是3.75,这些数字的平均值。)
  • 一个项目的投票数。(举另一个例子,如果有5个人对一个项目投了票,v 是5。)
  • M-可调参数。应用于评级的“平滑”数量是基于投票数(v)相对于 m。调整 m,直到结果令您满意。不要误解 IMDb 对 m 的描述为“需要列出的最低投票数”——这个系统完全可以对投票数少于 m 的项目进行排名。

所有的公式都是: 在计算平均值之前,加上 m 个虚数选票,每个选票的值都是 C。一开始,如果没有足够的数据(例如,投票数明显小于 m) ,就会用平均数据填充空格。然而,随着选票的积累,最终虚拟的选票将被真实的选票所淹没。

在这个系统中,投票不会导致收视率剧烈波动。相反,它们只是在某个方向上稍微扰动了一下。

当选票为零时,只有虚数选票存在,而且所有的选票都是 C。因此,每个项目都以 C 打分开始。

参见:

  • 一个 小样点击“解决”。
  • IMDb 系统的另一个 解释
  • 类似贝叶斯星等系统的 解释

显然,低评级使得这个问题在统计学上处于不利地位。

提高总体评级质量的一个关键因素是“评级员”,即记录每个特定“评级员”提供的评级(相对于其他评级员)。这允许在聚合过程中权衡他们的投票。

另一个解决方案,更多的是应付,是为最终用户提供一个计数(或其范围指示)的投票为基础的项目。

我强烈推荐 Toby Segaran (OReilly)的《编程集体智慧》一书,该书讨论了如何从群体行为中提取有意义的数据。这些示例是用 Python 编写的,但是转换起来很容易。

这取决于你想把它做得有多复杂,你可以根据一个人做了多少次评分,以及这些评分是什么,来对评分进行加权。如果一个人只做了一个评级,那么这可能是一个托儿的评级,可能会少一些。或者,如果这个人在 A 类中评价了很多东西,但在 B 类中评价很少,平均评分为1.3(满分5星) ,这听起来像是 A 类可能被这个用户的低平均分人为压低了,应该进行调整。

不要再把事情复杂化了,让我们把事情简单化。

假设我们只使用两个值,ReviewCount 和 AverageRating,对于一个特定的项目,我认为 ReviewCount 本质上是“可靠性”值是有意义的。但是,我们不仅仅是想要降低审查计数较低的项目的分数: 一个单一的一星评级可能和一个单一的五星评级一样不可靠。所以我们要做的可能是中间的平均值: 3。

所以,基本上,我在考虑一个方程,比如 X * AverageRating + Y * 3 = the-atings-we-want。为了使这个值正确出来,我们需要 X + Y 等于1。另外,我们需要 X 来增加值,因为 ReviewCount 增加了... 如果评论数为0,x 应该是0(给我们一个“3”的方程式) ,如果评论数为无限,X 应该是1(这使得方程式 = AverageRating)。

那么 X 和 Y 方程是什么呢?对于 X 方程,当自变量趋于无穷大时,要求因变量渐近地逼近1。一组好的方程式是这样的: Y = 1/(因子 ^ RatingCount) 和(利用 X 必须等于1-Y 的事实) X = 1-(1/(因子 ^ RatingCount)

然后我们可以调整“因素”,以适应范围,我们正在寻找。

我用这个简单的 C # 程序尝试了几个因素:

        // We can adjust this factor to adjust our curve.
double factor = 1.5;


// Here's some sample data
double RatingAverage1 = 5;
double RatingCount1 = 1;


double RatingAverage2 = 4.5;
double RatingCount2 = 5;


double RatingAverage3 = 3.5;
double RatingCount3 = 50000; // 50000 is not infinite, but it's probably plenty to closely simulate it.


// Do the calculations
double modfactor = Math.Pow(factor, RatingCount1);
double modRating1 = (3 / modfactor)
+ (RatingAverage1 * (1 - 1 / modfactor));


double modfactor2 = Math.Pow(factor, RatingCount2);
double modRating2 = (3 / modfactor2)
+ (RatingAverage2 * (1 - 1 / modfactor2));


double modfactor3 = Math.Pow(factor, RatingCount3);
double modRating3 = (3 / modfactor3)
+ (RatingAverage3 * (1 - 1 / modfactor3));


Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage1, RatingCount1, modRating1));
Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage2, RatingCount2, modRating2));
Console.WriteLine(String.Format("RatingAverage: {0}, RatingCount: {1}, Adjusted Rating: {2:0.00}",
RatingAverage3, RatingCount3, modRating3));


// Hold up for the user to read the data.
Console.ReadLine();

所以你不用麻烦把它复制进去,它会给出这样的输出:

RatingAverage: 5, RatingCount: 1, Adjusted Rating: 3.67
RatingAverage: 4.5, RatingCount: 5, Adjusted Rating: 4.30
RatingAverage: 3.5, RatingCount: 50000, Adjusted Rating: 3.50

差不多吧?显然,您可以根据需要调整“因子”值,以获得您想要的权重类型。

有关基于星级的评分系统的良好分析,请参阅 这一页,有关基于上下投票的系统的良好分析,请参阅 这个

对于向上和向下投票,你想要估计的概率,给定你的评分,“实际”得分(如果你有无限的评分)大于一些数量(比如,类似的数字,对于其他项目,你正在排序)。

请参阅第二篇文章中的答案,但结论是您希望使用威尔逊置信度。本文给出了等式和 Ruby 代码示例(很容易翻译成另一种语言)。

如果您只是需要一个快速和廉价的解决方案,将大部分工作不使用大量的计算,这里有一个选择(假设1-5评级尺度)

SELECT Products.id, Products.title, avg(Ratings.score), etc
FROM
Products INNER JOIN Ratings ON Products.id=Ratings.product_id
GROUP BY
Products.id, Products.title
ORDER BY (SUM(Ratings.score)+25.0)/(COUNT(Ratings.id)+20.0) DESC, COUNT(Ratings.id) DESC

加上25,除以总分 + 20,你基本上是在总分中加上了10个最差分数和10个最好分数,然后相应地排序。

这确实有些问题。例如,它不公平地奖励评分较低的产品(如 这张图所示,平均评分为1和只有一个评分的产品评分为1.2,而平均评分为1和1k + 评分的产品评分接近1.05)。你也可以说,它不公平地惩罚了几乎没有评级的高质量产品。

这个图表显示了超过1-1000个评级的5个评级会发生什么: Http://www.wolframalpha.com/input/?i=plot3d%5b%2825%2bxy%29/%2820%2bx%29%2c%7bx%2c1%2c1000%7d%2c%7by%2c0%2c6%7d%5d

你可以看到在最底层的评级下降,但总的来说,这是一个公平的排名,我认为。你也可以这样看:

Http://www.wolframalpha.com/input/?i=plot3d%5b6-%28%2825%2bxy%29/%2820%2bx%29%29%2c%7bx%2c1%2c1000%7d%2c%7by%2c0%2c6%7d%5d

如果你在这个图表的大部分地方丢一个弹珠,它会自动滚向分数和评分都更高的产品。

一种选择是类似于微软的 TrueSkills 系统,其中的分数由 mean - 3*stddev给出,常量可以进行调整。

埃文 · 米勒(Evan Miller)展示了一种贝叶斯方法来评定五星评级: enter image description here

哪里

  • nkk星级的编号,
  • skk恒星的“价值”,
  • N是投票总数
  • K是恒星数量的最大值(例如 K = 5,在一个五星评级系统中)
  • z_alpha/2是正态分布的 1 - alpha/2分位数。如果您想要95% 的信心(基于贝叶斯后验概率) ,即实际排序标准至少与计算排序标准一样大,请选择 z_alpha/2 = 1.65。

在 Python 中,排序条件可以用

def starsort(ns):
"""
http://www.evanmiller.org/ranking-items-with-star-ratings.html
"""
N = sum(ns)
K = len(ns)
s = list(range(K,0,-1))
s2 = [sk**2 for sk in s]
z = 1.65
def f(s, ns):
N = sum(ns)
K = len(ns)
return sum(sk*(nk+1) for sk, nk in zip(s,ns)) / (N+K)
fsns = f(s, ns)
return fsns - z*math.sqrt((f(s2, ns)- fsns**2)/(N+K+1))

例如,如果一个项目有60个五星、80个四星、75个三星、20个二星和25个一星,那么它的总体星级大约是3.4:

x = (60, 80, 75, 20, 25)
starsort(x)
# 3.3686975120774694

你可以用

sorted([(60, 80, 75, 20, 25), (10,0,0,0,0), (5,0,0,0,0)], key=starsort, reverse=True)
# [(10, 0, 0, 0, 0), (60, 80, 75, 20, 25), (5, 0, 0, 0, 0)]

这表明,更多的评级可以对整体星值的影响。


你会发现这个公式给出的总体评分有点低 低于亚马逊(Amazon)、 Ebay 或沃尔玛(Wal-mart)等网站报告的总体评级 特别是当选票很少(例如少于300票)的时候 更高的不确定性,伴随着更少的选票。随着选票数量的增加 (成千上万)所有这些评级公式应倾向于 (加权)平均等级。


因为公式只取决于频率分布的五星评级 对于项目本身,很容易从多个来源(或, 根据新选票更新总评分) ,只需添加频率 一起分配。


与 IMDb 公式不同,这个公式不依赖于平均分数 所有项目,也没有一个人为的最低票数截止值。

此外,这个公式利用了整个频率分布——不仅仅是 明星的平均数量和投票的数量。这是有道理的 因为一个项目的10个5星和10个1星应该被视为 不确定性比(因此评分不如)有 20个三星级别:

In [78]: starsort((10,0,0,0,10))
Out[78]: 2.386028063783418


In [79]: starsort((0,0,20,0,0))
Out[79]: 2.795342687927806

IMDb 公式没有考虑到这一点。

经过一段时间的观察,我选择了贝叶斯系统。 如果有人正在使用 Ruby,这里有一个宝石:

Https://github.com/wbotelhos/rating