來源:標點符
這篇文章介紹了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的排名落後。對於評論排名上述的方法是否是我們所需要的呢?這樣的計算才能更好的體現評論價值?正確的排名演算法應該是怎樣的?
我們先做如下設定:
1、每個使用者的投票都是獨立事件。
2、使用者只有兩個選擇,要麼投好評,要麼投差評。
3、如果投票總人數為n,其中好評為k,那麼好評率p就等於k/n。
如果你熟悉統計學,可能已經看出來了,p服從一種統計分佈,叫做“兩項分佈”(binomial distribution)。
p越大,就代表這個專案的好評比例越高,越應該排在前面。但是,p的可信性,取決於有多少人投票,如果樣本太小,p就不可信。由於p服從”兩項分佈”,因此我們可以計算出p的置信區間。所謂“置信區間”,就是說,以某個概率而言,p會落在的那個區間。比如,某個產品的好評率是 80%,但是這個值不一定可信。根據統計學,我們只能說,有 95% 的把握可以斷定,好評率在 75% 到 85% 之間,即置信區間是[75%, 85%]。
通過上面的分析,我們就可以推斷出,如果要給一個評論進行排名,就需要考慮一下內容:
1、計算每個評論的”好評率”
2、計算每個”好評率”的置信區間(以 95% 的概率)。
3、根據置信區間的下限值,進行排名。這個值越大,排名就越高。
這樣做的原理是,置信區間的寬窄與樣本的數量有關。比如,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程式碼後:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
; html-script: false ]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