뉴스나 피드에 게시글 정렬 방법 중 **추천순** 혹은 **인기순**이라는 정렬 기준을 본적이 있을 것이다. 인기도를 기반으로 추천하는 고전적인 방법으로 비개인화 추천이지만 간단히 사용할 수 있기에 소개해보려 한다. 이번 글에서는 이 중 대표적인 Hacker News FormulaReddit Formula에 대해 알아보고자 한다.

Hacker News Formula

출처: https://sungkee-book.tistory.com/10
  • 분자의 pageviews는 조회수를 의미하며 작성자의 조회수를 제거하기 위해 1을 빼준다.
  • 분모의 age는 뉴스 업로드 날짜로부터 현재까지 지난 기간(Hours)를 의미한다. 2를 더해주는 이유는 나와있지 않지만 아래의 2가지 이유정도가 있지 않을까 추측한다.
    • 분모가 0이 되지 않기위해
    • 2가 아닌 1을 더하게되면 age가 0일 때 분모가 항상 1일 되기 때문에 gravity로 score를 조절할 수 없다
  • gravityage가 커질수록 분모를 얼마나 더 크게 증가시킬 것인지 설정하는 상수이다. Hacker News에서는 gravity 값을 1.8로 설정한다. 1보다 큰 값을 사용하므로써 시간이 지남에 따라 오래된 뉴스는 조회수가 높더라도 낮은 점수를 갖게 된다.
# Hacker News Formula
def hacker_news_formula(votes, item_hour_age, gravity=1.8):
    return (votes - 1) / (item_hour_age+2)**gravity

Reddit Formula

출처: https://sungkee-book.tistory.com/10

term1

  • _log_를 씌움으로써 초반 좋아요에 높은 점수를 주고 10 이상부터는 점수 상승 폭을 줄이는 역할을 한다.
  • 음수가 되는 것을 막기 위해 ups - downs가 1보다 작으면 1로 고정한다.

term2

  • 시간이 지날수록 더 낮은 스코어를 반영하는 역할을 한다.
  • seconds의 경우 Reddit이 오픈 한 후부터 게시글이 작성될 때까지의 절대적인 시간을 의미한다. 최신글일수록 seconds의 값이 커지게 된다. 때문에 오래된 포스팅일 수록 아주 많은 추천이 있어야 높은 score를 가질 수 있다.
  • sign의 경우 ups-downs가 0보다 크면 1, 0일 때는 0, 0보다 작을 때는 -1로 고정된다.
  • 분자의 45000의 의미는 12.5 시간을 최신글이라는 기준으로 잡았기 때문에 45000초라는 상수를 사용한다.
import math

def reddit_formula(ups, downs, date):
    s = ups - downs
    order = math.log10(max(abs(s), 1))
    if s > 0:
        sign = 1
    elif s < 0:
        sign = -1
    else:
        sign = 0
    seconds = date - 1134028003
    
    return round(order + sign * seconds / 45000, 7)

References

  • https://sungkee-book.tistory.com/10
  • https://medium.com/jp-tech/how-are-popular-ranking-algorithms-such-as-reddit-and-hacker-news-working-724e639ed9f7