打分排序系統漫談1 - 時間衰減
打分排序系統的應用非常普遍,比如電影的評分,知乎帖子的熱度,和新聞文章的排序。讓我們從最簡單直觀的平均打分開始, 聊聊各種打分方法的利弊和使用場景。
最簡單的打分方法當然是一段時間的點贊量綜述。顯而易見的缺點就是越老的帖子容易拿到更多的贊而長期霸榜,HN用了一種簡單的時間方法來考慮時間衰減。
Hacker News Algo - 只有點贊
\[ \begin{align} score & = \frac{(v-1)}{(t+2)^G} * pen \\ where & v-1 剔除只有一個使用者點讚的情況 \\ & t+2 保證除數永遠大於1 \\ & G:衡量打分隨時間的衰減程度 \\ &pen: 爭議,過短,沒有跳轉的文章打分會打折\\ \end{align} \]
def hacker_news_ranking(votes, item_age, gravity = 1.8, penalties): score = (votes-1)/(item_age +2)**gravity * penalties return score
Hacker News 的打分方式,主要考慮到了時間衰減。保證老的新聞不會因為累計更多的點贊而始終在排在前面。並且點贊數和帖子新舊程度的權衡可以通過G的大小來調整。但仍然有幾個未解問題:
-
時間衰減過快,對於一些有長實效性的打分並不適用。 能否在打分上加入指數?
-
如何考慮時間衰減和當前時段的關係。不同時段瀏覽量不同,如果一篇很好的文章在凌晨釋出,因為當時瀏覽量低,文章可能永遠沒有置頂機會。 能否對時間進行加權?
-
沒有考慮到點贊量和文章熱度的非線性關係。簡單說就是點贊量可以接近無限大,但文章熱度是有限的。 能否對打分進行非線性壓縮?
-
不同型別文章熱度是否可比,例如有的文章質量高但是相對小眾。 能否做組內排序?或者用點贊率來衡量
-
同理也應該考慮到瀏覽量(PV)和點贊量的關係。 點贊率高的應該考慮排在前面,但同樣瀏覽量過小的點贊率也要考慮置信度的問題
Reddit Hot Formula - 包括點贊和拍磚

同時考慮點贊和拍磚,Reddit 的 Hot Formula採用了和Hacker News相似的打分方式,來推薦優質高熱度的文章。並針對上述問題(1)和(3)給出了不同的處理。公式如下:
\[ \begin{align} score & = up - down \\ score_{adj} & = \log_{10}{(max(score,1))}\\ sign &= \begin{cases} 1 & if score > 0 \\ 0 & if score = 0 \\ -1& if score <0 \\ \end{cases}\\ score &= score_{adj} * sign + \frac{seconds}{45000} \\ where \, seconds & =發帖時間 - 2015年12月8日 \end{align} \]
和Hacker News相比, Reddt Hot Formula有幾個不同點:
-
用取Log的方式解決了上述提出的第三個問題就是文章熱度和點贊量之間的非線性關係,文章熱度不會隨著點贊量的增加無限線性增長。而壓縮的強度可以通過改變log的底數來調整,底數越大點贊量對文章的影響
-
處理時間遞減上,Hot Formula採用了線性遞減處理。新的帖子因為距歷史時點更遠會拿到更高的時間加分項 \(\frac{seconds}{45000}\) 。和上述指數衰減相比,線性不會過度懲罰老文章。
思考:時間衰減
比較Hacker News,和Reddit Hot Formula, 主要的兩點區別在於對點贊量(拍磚)取log進行壓縮,以及不同的時間衰減項。 log運算單調所以如果只用排序不用分數的話並不會對最終排序產生影響,所以讓我們再來深入討論一下時間衰減項的選取。
簡單來說時間衰減的意義就是為了讓新老文章的熱度具有可比性,否則老的帖子會因為在更長的時間累計了更多的帖子而始終置頂。一種直觀的解決辦法就是給老的帖子增加時間懲罰項。幾種常見的時間衰減項包括:
- 線性衰減
\[ score_t = score_0 - T/G \] -
冪指數衰減
\[ score_t = score_0 / (T + 2)^G \]
冪指數衰減的衰減速度會隨著時間加速,加速時間懲罰項對打分的影響。如果覺得冪指數的表達形式不夠直觀,我們可以對等式左右取個對數,會發現對數打分的變化是對數時間的線性函式,可以用這個方式來判斷冪指數打分是否適用,如下:
\[ log(score_t) = log(score_0) - G * log(T+2) \]
-
指數衰減
\[ score_t = score_0 * exp( - \lambda * T ) \]
指數衰減可以由牛頓冷卻定律的一階微分方程得到,
\(\lambda\)
是衰減速率,速率恆定,經過t時間衰減的量和N當前的值正相關
\[ \frac{dN(t)}{dt} = - \lambda N(t) \\ \frac{dN(t)}{N(t)} = -\lambda dt \\ log(\frac{N(t)}{N_0}) = - \lambda t \\ \]
也可以從指數分佈的角度來理解, \(N_0\) 是集合初始的元素數量,其中每個元素都在衰減,在t時刻依舊存在的元素數量期望是 \(N(t)\) 。元素的生命長度符合指數分佈:
\[ f(t) \sim \lambda e^{-\lambda t} \\ P(x>t) = 1 - F(x<t) = e^{-\lambda t } \\ N(t) = N_0 * P(x>t) \]
下一節我們接著就上述提出的幾個問題中還沒有解決的如何綜合考慮瀏覽量和點贊量來打分的問題進行討論。
To be continue
Reference