Bayesian 평균과 시간 감쇠로 만드는 추천 시스템

English (N/A)

추천 시스템을 처음 만들 때 가장 먼저 부딪히는 문제가 있다. 리뷰가 하나뿐인 상품이 평점 5.0을 받아서 리뷰가 수백 개인 검증된 상품보다 상위에 뜨는 현상이다. 데이터가 적을수록 노이즈가 커지고, 그 노이즈가 그대로 순위에 반영된다.

두 번째 문제는 시간이다. 사용자의 취향은 변한다. 3년 전에 SF 소설을 열심히 읽던 사람이 지금은 자기계발서에 빠져 있을 수 있다. 과거 데이터를 현재와 동등하게 취급하면, 이미 흥미가 식어버린 영역을 계속 추천하게 된다.

이 두 문제를 해결하는 방법이 Bayesian 평균시간 감쇠 의 조합이다.

왜 단순 평균이 실패하는가

리뷰가 1개이고 평점이 5점인 상품 A와, 리뷰가 200개이고 평점이 4.3점인 상품 B를 비교해보자. 단순 평균으로는 A가 이긴다. 하지만 합리적인 사람이라면 B를 더 신뢰할 것이다. 리뷰 1개는 운이거나 지인의 리뷰일 가능성이 높다.

문제의 본질은 샘플 크기를 신뢰도로 환산하지 않는다 는 것이다. 숫자의 크기만 보고 그 숫자가 얼마나 믿을 만한지는 무시한다.

통계학에서는 이를 "작은 샘플의 분산이 크다"고 표현한다. 동전을 3번 던져서 3번 앞면이 나왔다고 해서 이 동전이 100% 앞면만 나오는 동전이라고 볼 수 없는 것과 같은 이치다.

Bayesian 평균의 아이디어

Bayesian 평균은 "리뷰가 없을 때 이 상품의 평점은 얼마라고 봐야 하는가"라는 사전 믿음(prior)에서 출발한다.

아무 정보도 없다면 전체 상품의 평균 평점을 기대값으로 삼는 것이 합리적이다. 리뷰가 쌓일수록 이 사전 기대에서 벗어나 실제 관측값 쪽으로 무게중심이 이동한다.

수식으로 쓰면 이렇다.

bayesian_score = (C × m + n × r) / (C + n)
  • m: 전체 상품 평균 평점 (prior mean)
  • C: 신뢰 가중치 (confidence weight) — 튜닝 파라미터
  • n: 해당 상품의 리뷰 수
  • r: 해당 상품의 실제 평균 평점

C가 클수록 사전 기대에 오래 머문다. C가 작을수록 실제 리뷰에 빨리 반응한다. 보통 전체 상품의 평균 리뷰 수를 C의 초기값으로 쓴다.

그래프로 보는 점수 수렴

전체 평균 m = 4.0, 신뢰 가중치 C = 10 일 때, 실제 평점이 다른 두 상품의 Bayesian 점수가 리뷰 수에 따라 어떻게 변하는지 그려보자.

위쪽 선은 실제 평점 r = 5.0 인 상품, 아래쪽 선은 실제 평점 r = 3.0 인 상품이다.

세 가지를 읽을 수 있다.

  • 출발점이 같다. n = 0 일 때 둘 다 사전 기대값 4.0에서 시작한다. 리뷰가 없으면 모두 평균 취급이다.
  • 수렴 속도가 빠르지 않다. 리뷰가 10개여도 점수는 사전 기대와 실제값의 중간쯤이다. C = 10 이라는 의미가 바로 이것이다 — "리뷰 10개는 사전 기대만큼의 무게."
  • 결국 실제값에 도달한다. 리뷰 200개에 도달하면 거의 실제 평점에 수렴한다. 충분한 데이터가 모이면 사전의 영향은 사라진다.

리뷰 1~2개짜리 상품이 5점이라도 점수는 4.1을 넘기 어렵다는 점이 핵심이다. 노이즈가 자연스럽게 눌린다.

시간 감쇠: 오래된 데이터를 희석시키기

Bayesian 평균은 리뷰 수의 신뢰 문제를 해결하지만, 시간의 문제는 건드리지 않는다. 2년 전 리뷰와 오늘 리뷰가 동등하게 취급된다.

시간 감쇠는 오래된 상호작용에 낮은 가중치를 주는 방식이다. 가장 많이 쓰이는 형태는 지수 감쇠(exponential decay)다.

weight(t) = exp(-λ × Δt)
  • Δt: 해당 상호작용이 일어난 시점부터 현재까지의 시간
  • λ: 감쇠 속도 — 도메인에 따라 조절하는 핵심 파라미터

λ 자체를 직접 다루기보다는 반감기(half-life) 로 사고하는 것이 직관적이다. 반감기 T일이면 T일이 지난 리뷰의 가중치는 정확히 0.5가 된다. 변환은 λ = ln(2) / T 로 간단하다.

그래프로 보는 시간 감쇠

반감기를 30일, 90일, 365일로 설정했을 때 가중치가 시간에 따라 어떻게 떨어지는지 보자.

위에서부터 차례로 반감기 365일, 90일, 30일이다.

  • 반감기 30일 (가장 가파른 곡선): 3개월만 지나도 가중치가 거의 0이다. 트렌드성 상품이나 뉴스에 적합하다.
  • 반감기 90일: 한 분기 단위로 영향력이 절반씩 줄어든다. 일반 커머스에서 무난한 선택이다.
  • 반감기 365일: 1년이 지나도 절반의 영향력이 남는다. 책, 영화, 클래식 상품처럼 수명이 긴 콘텐츠에 적합하다.

뉴스 추천에서 반감기 365일을 쓰면 작년 기사가 오늘 기사만큼 노출된다. 책 추천에서 반감기 30일을 쓰면 작년 베스트셀러가 통째로 사라진다. 도메인 감각이 가장 중요한 파라미터다.

Bayesian + 시간 감쇠 결합

두 개념을 결합하는 방법은 단순하다. Bayesian 공식의 n (리뷰 수) 자리에 시간 가중치의 합 을, r (평균 평점) 자리에 시간 가중 평균 을 넣는다.

n_effective = Σ w_i                        (가중치의 합)
r_decay     = Σ (w_i × rating_i) / n_eff   (시간 가중 평균)

bayesian_score = (C × m + n_eff × r_decay) / (C + n_eff)

이 결합이 만들어내는 가장 중요한 효과는 오래된 인기 상품의 자연스러운 재평가 다.

예시를 보자. 어떤 상품이 2년 전 출시 직후 100개의 5점 리뷰를 받고 그 후로 새 리뷰가 없다면, 이 상품의 점수는 시간이 지남에 따라 어떻게 변할까? (m=4.0, C=10, 반감기 180일 가정)

처음에는 4.91점으로 거의 만점에 가깝다. 하지만 새 리뷰 없이 시간만 지나면:

  • 6개월 후: 4.83 — 거의 변화 없음
  • 1년 후: 4.71 — 살짝 떨어짐
  • 2년 후: 4.38 — 눈에 띄게 하락
  • 4년 후: 4.04 — 사실상 사전 평균으로 회귀

n_effective 가 시간에 따라 감쇠하면서, 점수가 자연스럽게 사전 평균 m = 4.0 쪽으로 끌려간다. 누군가 강제로 "오래된 상품 페널티" 같은 규칙을 짤 필요가 없다. 수학적으로 알아서 일어난다.

새 리뷰가 계속 들어오면 n_effective 가 유지되고 점수도 유지된다. 신선한 상호작용이 있는 상품만 상위에 남는다.

사용자 개인화 레이어

지금까지의 점수는 상품 단위의 점수다. 추천 시스템에서는 여기에 사용자 취향을 반영해야 한다.

가장 단순한 방법은 사용자의 최근 상호작용 이력에서 선호 카테고리나 태그를 추출해서, 그 친밀도를 점수에 곱하는 것이다.

personalized_score = base_score × (1 + α × user_affinity)
  • base_score: 위에서 계산한 Bayesian + 시간 감쇠 점수
  • user_affinity: 0~1로 정규화된 사용자의 해당 카테고리 친밀도
  • α: 개인화 강도 (보통 0.2~1.0 사이)

α 가 너무 크면 필터 버블이 생긴다. 자기가 본 카테고리만 계속 추천된다. 너무 작으면 개인화 효과가 미미하다.

user_affinity 자체도 시간 감쇠로 계산한다. 3개월 전 클릭보다 어제 클릭이 취향을 더 잘 반영하기 때문이다. 단, λ_user 는 상품 감쇠와 별도로 튜닝해야 한다 — 사용자 취향이 바뀌는 속도와 상품 인기가 식는 속도는 다르다.

실무 튜닝 포인트

C (신뢰 가중치)

C 를 너무 크게 잡으면 인기 많은 상품이 뜰 때까지 너무 오래 걸린다. 너무 작으면 리뷰 초기의 노이즈가 순위에 그대로 튀어나온다.

초기값은 전체 상품 평균 리뷰 수로 시작하고, A/B 테스트로 조정한다. 신규 상품 노출 전략과 연계해서 생각해야 한다.

λ (시간 감쇠 속도)

반감기로 사고하는 것이 가장 빠르다. 도메인별로 자주 쓰이는 범위는 다음과 같다.

  • 뉴스: 1~3일
  • 트렌드 상품, 핫딜: 2~4주
  • 일반 커머스: 1~3개월
  • 책, 영화, 음악: 6개월~2년

상품 점수용 λ 와 사용자 친밀도용 λ_user 는 독립적으로 튜닝한다. 보통 사용자 취향이 더 빠르게 변하므로 λ_user 가 더 크다 (반감기가 더 짧다).

콜드 스타트 처리

신규 상품은 리뷰가 없어서 n_effective 가 0이다. 이 경우 전체 평균 m 으로 시작하는 게 기본이다. 그러나 카테고리별 m 을 따로 계산해서 쓰면 더 정교해진다 — 식품 카테고리 평균과 가전 카테고리 평균이 다를 수 있기 때문이다.

신규 사용자는 user_affinity 가 모두 0이다. 이때는 인기 기반 추천(base_score 그대로)으로 시작해서, 첫 상호작용이 쌓이는 대로 개인화 비중을 늘려간다.

이 접근법의 한계

Bayesian 평균과 시간 감쇠는 협업 필터링(Collaborative Filtering) 이나 딥러닝 기반 추천 에 비해 단순하다. 사용자 간의 유사성을 직접 모델링하지 않고, 콘텐츠의 잠재 특성을 학습하지도 않는다.

그러나 해석 가능성이 높고, 데이터가 적을 때도 안정적으로 동작하며, 운영 비용이 낮다는 장점이 있다. 트래픽이 많지 않은 초기 서비스나, 설명 가능한 추천이 필요한 도메인에서는 충분히 강력한 선택지다.

복잡한 모델도 결국 이 개념들 위에 쌓인다. Bayesian 사전 분포와 시간 가중 집계를 이해하면, 더 복잡한 추천 모델의 설계 의도를 읽는 눈도 생긴다.


참고