什么是以5星评级排序的更好方法?

Viz*_*rai 64 sorting statistics user-experience rating bayesian

我正在尝试使用5星系统按客户评级对一堆产品进行排序.我设置的网站没有很多评级,并继续添加新产品,所以它通常会有一些评级较低的产品.

我尝试使用平均星级评级,但是当评级很少时,该算法会失败.

例如,具有3x5星评级的产品将比具有100x5星评级和2x2星评级的产品更好.

第二个产品是否应该显得更高,因为它在统计上更值得信赖,因为评级数量更多?

Mar*_*ris 71

在2015年之前,互联网电影数据库(IMDb)公开列出了用于对其250强电影列表进行排名的公式.报价:

计算最高额定250标题的公式给出了真正的贝叶斯估计:

weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
Run Code Online (Sandbox Code Playgroud)

哪里:

  • R =电影的平均值(平均值)
  • v =电影的投票数
  • m =要求列入前250名的最低票数(目前为25000)
  • C =整个报告的平均投票数(目前为7.0)

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

这并不难理解.公式是:

rating = (v / (v + m)) * R +
         (m / (v + m)) * C;
Run Code Online (Sandbox Code Playgroud)

可以在数学上简化为:

rating = (R * v + C * m) / (v + m);
Run Code Online (Sandbox Code Playgroud)

变量是:

  • R - 项目自己的评级.R是项目投票的平均值.(例如,如果一个项目没有投票,则其R为0.如果有人给它5个星,R变为5.如果有人给它1个星,R变为3,平均值为[1, 5].等等.)
  • C - 平均项目的评级.找到数据库中每个项目的R,包括当前项目,并取其平均值; 那就是C.(假设数据库中有4个项目,它们的等级是[2, 3, 5, 5].C是3.75,这些数字的平均值.)
  • v - 项目的投票数.(举另一个例子,如果5个人对某个项目投了票,则v为5.)
  • m - 可调参数.应用于评级的"平滑"量基于与m相关的投票数(v).调整m直到结果满足您.并且不要将IMDb对m的描述误解为"需要列出的最低票数" - 这个系统完全能够以低于m的票数对项目进行排名.

所有公式都是:在计算平均值之前,添加m个虚构的投票,每个投票的值为C.一开始,当没有足够的数据(即投票数远远小于m)时,这会导致空白用平均数据填充.然而,随着选票的累积,最终虚构的选票将被真实的投票淹没.

在这个系统中,投票不会导致评级大幅波动.相反,他们只是在某个方向上稍微扰乱它.

当存在零票时,仅存在虚构的投票,并且所有投票都是C.因此,每个项目以C的评级开始.

也可以看看:

  • 一个演示.单击"解决".
  • IMDb系统的另一种解释.
  • 类似贝叶斯星级评定系统的解释.

  • 公式实际上是相同的,你必须将原始公式错误地放入(v /(v + m))*R +(m /(v + m))*C与(v*R + m)相同*C)/(v + m).链接:http://goo.gl/IW9s1A (2认同)

Gre*_*reg 17

请参见本页面基于星级评定系统的一个很好的分析,以及这一次的upvote-/downvote-基础的系统的一个很好的分析.

对于上下投票,你想要估计一个概率,给定你的评级,"真实"分数(如果你有无限的评级)大于一些数量(比如,你的其他项目的类似数字)重新排序).

请参阅第二篇文章以获得答案,但结论是您希望使用Wilson的信心.本文给出了方程式和示例Ruby代码(很容易翻译成另一种语言).

  • 威尔逊置信区间仅适用于二项分布(例如,+ 1/-1样式评级); 目前还不清楚采取什么方法来获得像5星评级计划这样的东西. (4认同)

unu*_*tbu 17

Evan Miller采用贝叶斯方法对五星评级进行排名: 在此输入图像描述

哪里

  • nkk星级评分的数量,
  • skk恒星的"价值"(以分为单位),
  • N 是总票数
  • K 是最大星数(例如K = 5,在5星评级系统中)
  • z_alpha/21 - 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))
Run Code Online (Sandbox Code Playgroud)

例如,如果一个项目有60颗五颗星,80颗四颗星,75颗三颗星,20颗两颗星和25颗一颗星,那么它的整体星级评分约为3.4:

x = (60, 80, 75, 20, 25)
starsort(x)
# 3.3686975120774694
Run Code Online (Sandbox Code Playgroud)

你可以用5种星级排序列表

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)]
Run Code Online (Sandbox Code Playgroud)

这显示了更多评级可能对整体恒星价值产生的影响.


您会发现这个公式的整体评分往往略低于亚马逊,Ebay或沃尔玛等网站报告的整体评分,特别是在投票数较少(比如少于300)时.这反映了较少的选票带来的更高的不确定性.随着投票数增加(成千上万)所有这些评级公式应该倾向于(加权)平均评级.


由于该公式仅取决于项目本身的五星评级的频率分布,因此通过简单地将频率分布加在一起,很容易组合来自多个来源的评论(或者, 根据新投票更新总体评级).


与IMDb公式不同,此公式不依赖于所有项目的平均分数,也不依赖于人工最小投票截止值.

此外,这个公式利用了全频率分布 - 不仅仅是平均星数和投票数.它应该是有道理的,因为具有10个5星和10个1星的项目应该被视为具有更多的不确定性(因此没有被评为高度)具有20个3星评级的项目:

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

In [79]: starsort((0,0,20,0,0))
Out[79]: 2.795342687927806
Run Code Online (Sandbox Code Playgroud)

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

  • 我还将此答案移植到 SQL,假设列“rated5”、“rated4”、“rated3”、“rated2”和“rated1”,这些列是给出该评级的人数。`选择((5*(额定5+1)+4*(额定4+1)+3*(额定3+1)+2*(额定2+1)+1*(额定1+1))/(5+额定5+额定4+额定3+额定2+额定1))-1.65*SQRT((((25*(额定5+1)+16*(额定4+1)+9*(额定3+1)+4*(额定2+1)+1) *(额定1+1))/(5+额定5+额定4+额定3+额定2+额定1)) - 功率(((5*(额定5+1)+4*(额定4+1)+3*(额定3+1) +2*(额定2+1)+1*(额定1+1))/(5+额定5+额定4+额定3+额定2+额定1)), 2))/(6+额定5+额定4+额定3+额定2+额定1) ) 作为 x 来自 mytable` (3认同)
  • 非常感谢!我将此答案移植到 JavaScript。https://gist.github.com/dfabulich/fc6b13a8bffc5518c4731347de642749 (2认同)

Wel*_*bog 7

您可以按中位数而不是算术平均值排序.在这种情况下,两个示例的中值均为5,因此在排序算法中两者都具有相同的权重.

您可以使用相同效果的模式,但中位数可能是一个更好的主意.

如果您想为具有100个5星评级的产品分配额外的权重,您可能希望采用某种加权模式,为具有相同中位数的评级分配更多权重,但总体投票更多.


Bes*_*ska 7

那么,根据你想要制作它的复杂程度,你可以根据这个人制作了多少评分以及这些评分是多少来对收视率进行加权.如果这个人只做了一个评级,那么它可能是一个评级,并且可能算得更少.或者如果这个人在类别a中评定了很多东西,但在类别b中评分很少,并且平均评分为1.5星的5星级,则听起来像a类别可能会被该用户的低平均分数人为压低,并且应该调整.

但足以让它变得复杂.让我们简单一点.

假设我们只使用两个值,即ReviewCount和AverageRating,对于特定项目,我认为将ReviewCount视为"可靠性"值是有意义的.但我们并不只是希望将得分降低至较低的ReviewCount项目:单个一星评级可能与单个5星评级不可靠.所以我们想要做的可能是中间平均值:3.

所以,基本上,我正在考虑一个像X*AverageRating + Y*3 =我们想要的评级这样的等式.为了使这个值正确,我们需要X + Y等于1.此外,当ReviewCount增加时,我们需要X增加值...审查计数为0,x应为0(给我们一个等式" 3"),并且无限复查计数X应为1(这使得等式= AverageRating).

那么什么是X和Y方程?对于X方程,当自变量接近无穷大时,希望因变量渐近逼近1.一组好的方程式如下:Y = 1 /(factor ^ RatingCount)和(利用X必须等于1-Y的事实)X = 1 - (1 /(factor ^ 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();
Run Code Online (Sandbox Code Playgroud)

所以你不打扰复制它,它给出了这个输出:

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
Run Code Online (Sandbox Code Playgroud)

那样的东西?显然,您可以根据需要调整"因子"值,以获得所需的权重.