打分排序系统漫谈1 - 时间衰减

打分排序系统的应用很是广泛,好比电影的评分,知乎帖子的热度,和新闻文章的排序。让咱们从最简单直观的平均打分开始, 聊聊各类打分方法的利弊和使用场景。html

最简单的打分方法固然是一段时间的点赞量综述。显而易见的缺点就是越老的帖子容易拿到更多的赞而长期霸榜,HN用了一种简单的时间方法来考虑时间衰减。python

Hacker News Algo - 只有点赞

image.png-144.2kB
\[ \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

  1. 时间衰减过快,对于一些有长实效性的打分并不适用。可否在打分上加入指数?3d

  2. 如何考虑时间衰减和当前时段的关系。不一样时段浏览量不一样,若是一篇很好的文章在凌晨发布,由于当时浏览量低,文章可能永远没有置顶机会。可否对时间进行加权?code

  3. 没有考虑到点赞量和文章热度的非线性关系。简单说就是点赞量能够接近无限大,但文章热度是有限的。可否对打分进行非线性压缩?orm

  4. 不一样类型文章热度是否可比,例若有的文章质量高可是相对小众。可否作组内排序?或者用点赞率来衡量htm

  5. 同理也应该考虑到浏览量(PV)和点赞量的关系。点赞率高的应该考虑排在前面,但一样浏览量太小的点赞率也要考虑置信度的问题blog

Reddit Hot Formula - 包括点赞和拍砖

image.png-177.5kB
同时考虑点赞和拍砖,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

  1. http://www.evanmiller.org/rank-hotness-with-newtons-law-of-cooling.html
  2. http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html
  3. https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
相关文章
相关标签/搜索