打分排序系統的應用很是廣泛,好比電影的評分,知乎帖子的熱度,和新聞文章的排序。讓咱們從最簡單直觀的平均打分開始, 聊聊各類打分方法的利弊和使用場景。html
最簡單的打分方法固然是一段時間的點贊量綜述。顯而易見的缺點就是越老的帖子容易拿到更多的贊而長期霸榜,HN用了一種簡單的時間方法來考慮時間衰減。python
\[ \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的大小來調整。但仍然有幾個未解問題:spa
時間衰減過快,對於一些有長實效性的打分並不適用。可否在打分上加入指數?3d
如何考慮時間衰減和當前時段的關係。不一樣時段瀏覽量不一樣,若是一篇很好的文章在凌晨發佈,由於當時瀏覽量低,文章可能永遠沒有置頂機會。可否對時間進行加權?code
沒有考慮到點贊量和文章熱度的非線性關係。簡單說就是點贊量能夠接近無限大,但文章熱度是有限的。可否對打分進行非線性壓縮?orm
不一樣類型文章熱度是否可比,例若有的文章質量高可是相對小衆。可否作組內排序?或者用點贊率來衡量htm
同理也應該考慮到瀏覽量(PV)和點贊量的關係。點贊率高的應該考慮排在前面,但一樣瀏覽量太小的點贊率也要考慮置信度的問題blog
同時考慮點贊和拍磚,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 + 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