基於用戶評價的評分模型


一、場景

  豆瓣圖書、時光電影等索引類站點的不考慮時間因素的產品評分,其核心是通過用戶的評價計算出可量化的分數來衡量產品的受歡迎程度。使用威爾遜區間法進行評分,並使用貝葉斯平均法修正評分。

二、威爾遜區間法

  威爾遜區間法是基於二項分布的一種計算方法,其結果與好評率和評價次數相關。其假設只有“喜歡”和“不喜歡”兩個可選項,使其符合二項分布,並根據置信水平得到結果。

  計算公式如下:

  其中Smax是最大評分,pmin是威爾遜區間下限值,p是好評率(通常為平均值/總分值),n是評價總數,K是統計量常數(表示某個置信水平下z的統計量,在90%的置信水平下,值為1.64,在95%的置信水平下,值為1.96,在99%的置信水平下,值為2.58)。
  以豆瓣的評分機制為例,其評價選項為一星至五星,評分十分制。若存在產品ABCD,其評價如下表所示,那么其在95%置信水平下的評分為:

產品

一星

二星

三星

四星

五星

平均值

評分

A

32

32

32

32

32

5.00

4.23

B

50

25

10

25

50

5.00

4.23

C

320

320

320

320

320

5.00

4.76

D

500

250

100

250

500

5.00

4.76

  可以看出,相對於常用的平均值法,威爾遜區間法更准確的反映除了評價差異。

三、貝葉斯平均法

  嚴格來說,貝葉斯平均法並不是一個評分模型,而是平衡模型。其核心是為冷門題目提供一個補償值使其不至於因為少量評價而產生不可靠的評分,而在評價數量多后減小補償值的比例,最終使得隨着評價數量的增加而評分逐漸逼近實際值。
  計算公式如下:

  其中C是補償評價數,M是補償評分,n是評價數量,s是已計算評分。通常C、M應為常量,使最終評分只與評價數量和已計算評分相關。
  以豆瓣的評分機制為例,其評價選項為一星至五星,評分十分制。若存在產品EFGH,其評價如下表所示,那么其在95%置信水平,C=64、M=4.0368的補償條件下的修正評分為:

產品

一星

二星

三星

四星

五星

平均值

評分

修正

E

0

0

1

0

0

5.00

0.55

3.98

F

10

0

5

0

10

5.00

3.18

3.79

G

10

10

10

10

10

5.00

3.66

3.87

H

100

50

20

50

100

5.00

4.46

4.39

  顯然,對評價數量少的產品評分進行了大幅修正。

四、總結

  需要明確威爾遜區間法用於對單個產品評分,貝葉斯平均法用於對多個產品平衡評分。對於威爾遜區間法,需要確保好評率的正確性及選擇合適的置信水平。對於貝葉斯平均法,需要使補償評價數和補償評分為常量,以使得單個產品的評分僅與自身的評價相關。

五、更多

  更為細致的評分,需要考慮評分的用戶的權重性(資深用戶和普通用戶)、傾向性評分(用戶的評分習慣),二者都可以在上述方法上擴充修改。

參考

  阮一峰,《基於用戶投票的排名算法(五):威爾遜區間》
  阮一峰,《基於用戶投票的排名算法(六):貝葉斯平均》

實現代碼-Python

import sys

def Avg(data,scoreMap):
    totalScore = float(sum(map(lambda t:t[0]*t[1], map(None,data,scoreMap))))
    totalN = sum(data)
    return totalScore / totalN

def Wilson(p, n, maxScore):
    p = float(p)
    K = 1.96 # 95% confidence level
    _K2_div_n = (K ** 2) / n
    pmin = (p + _K2_div_n / 2.0 - K*((p*(1-p)/n + _K2_div_n/n/4.0)**0.5)) / (1 + _K2_div_n)
    return pmin * maxScore

def WilsonAvgP(n):
    totalP = 0.0; totalN = 0
    p = 0.01
    while True:
        totalP += Wilson(p, n, 1); totalN += 1
        p += 0.01
        if p >= 1: break
    return totalP / totalN

def Bayesian(C, M, n, s):
    return (C*M + n*s) / (n + C)

DATA = {
    "A" : (32,32,32,32,32),
    "B" : (50,25,10,25,50),
    "C" : (320,320,320,320,320),
    "D" : (500,250,100,250,500),
    "E" : (0,0,1,0,0),
    "F" : (10,0,5,0,10),
    "G" : (10,10,10,10,10),
    "H" : (100,50,20,50,100),
    }
SCORE_MAP = (0,2.5,5,7.5,10)
MAX_SCORE = 10

result = {} # key : avgScore, wilsonScore, wilsonRank
C = 64; M = WilsonAvgP(C) * MAX_SCORE
for k,v in DATA.items():
    n = sum(v)
    avgScore = Avg(v,SCORE_MAP)
    wilsonScore = Wilson(avgScore / MAX_SCORE, n, MAX_SCORE)
    wilsonRank = Bayesian(C, M, n, wilsonScore)
    result[k] = (avgScore, wilsonScore, wilsonRank)
for k in sorted(result.keys()):
    v = result[k]
    print k,":","%.2f" % v[0]," ","%.2f" % v[1]," ","%.2f" % v[2]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM