목차13개 항목
출처와 참고
카카오 추천팀의 「내 손안의 AI 비서, 추천 알고리듬」(카카오 AI 리포트, 2017.06)과 「멜론에서 음악 추천을 어떻게 할까?」(2020.04), 번개장터의 「추천 시스템 개발 및 도입후기」 Part 1·2·3(2019)을 바탕으로 재구성한 노트다. 아이템 기반 CF의 사전 계산, 하이브리드 설계, 정확도 밖의 지표는 Jannach·Friedrich의 IJCAI 2013 튜토리얼 「Recommender Systems」로, 쇼 단위 추천과 다양성·새로움 실험은 Hulu의 「Hulu’s Recommendation System」(2011)로 보강했다. 베이스라인 모형, 이웃 기반 CF, 편향을 더한 행렬 분해, 점수 예측 지표는 데이터 사이언스 스쿨의 「추천 시스템」, 거래 로그로 만드는 베스트·연관 추천은 레코벨의 「파이썬과 SQL로 배우는 추천시스템 Workshop」으로 보강했다. 관심 작가 목록으로 만든 Item2Vec 예시는 최규민의 「브런치 작가 추천과 Word2Vec」(2016.04)으로 보강했다.
두 가지 기본 접근
| 방식 | 비유 | 무엇을 보나 |
|---|---|---|
| 콘텐츠 기반 필터링(Content-based Filtering, CBF) | 방금 마신 칵테일과 재료가 비슷한 술을 권한다 | 아이템 자체의 특성(텍스트, 이미지, 소리, 메타데이터) |
| 협업 필터링(Collaborative Filtering, CF) | 이 칵테일을 고른 손님들이 같이 고른 술을 권한다 | 사용자 행동(클릭, 재생, 구매, 좋아요) |
같은 추천이 두 방식 모두에서 나올 수 있지만 근거가 다르다. CBF는 「내용이 비슷해서」, CF는 「같은 사람들이 소비해서」다.
협업 필터링
명시적 점수와 암묵적 피드백
| 종류 | 예 | 문제 |
|---|---|---|
| 명시적 점수(explicit rating) | 별점, 후기 평점, 좋아요·싫어요 | 만족하면 매기고 불만이면 안 매기는 식으로 빈다. 사람마다 점수 기준이 달라 편향이 생긴다 |
| 암묵적 피드백(implicit feedback) | 클릭, 조회, 재생, 구매 | 「안 봤다」가 싫다는 뜻인지 몰라서 모른다는 뜻인지 구분이 안 된다. 대신 모으기 쉽고 양이 많다 |
대부분의 실서비스는 암묵적 피드백(클릭 로그 등)을 쓴다.
명시적 점수를 다루면 추천은 사용자 ID와 아이템 ID라는 두 범주 입력으로 점수 하나를 맞히는 회귀 문제가 된다. 점수를 사용자 × 아이템 피벗 테이블로 펼친 것이 평점 행렬 R이고, 대부분의 칸이 비어 있는 희소 행렬이다. MovieLens 100K(사용자 943명, 영화 1,682편, 평점 10만 개)가 이 문제의 표준 연습 데이터다.
베이스라인 모형
가장 단순한 예측은 전체 평균에 사용자와 아이템의 치우침만 더하는 것이다.
r̂(u, i) = μ + b(u) + b(i)
μ: 전체 평점 평균, b(u): 이 사용자가 평균보다 후하게·짜게 주는 정도, b(i): 이 아이템이 평균보다 높게·낮게 받는 정도
학습: Σ (r(u,i) − r̂(u,i))² + λ(b(u)² + b(i)²) 를 최소화 (SGD 또는 ALS)전체 평균, 사용자별 평균, 아이템별 평균만으로 예측해 보는 것도 좋은 출발점이다. 이후 모델은 이 기준보다 나아야 의미가 있다.
이웃 기반 CF
이웃 기반(neighborhood) CF는 메모리 기반(memory-based) CF라고도 한다. 학습 없이 평점 행렬에서 비슷한 사용자(행 벡터) 또는 비슷한 아이템(열 벡터) 을 찾아 그들의 점수를 가중 평균한다.
| 방식 | 비슷함의 기준 | 예측 |
|---|---|---|
| 사용자 기반(user-based) | 평점 행렬의 행 벡터 유사도 | 나와 비슷한 사용자 k명이 그 아이템에 준 점수의 가중 평균 |
| 아이템 기반(item-based) | 열 벡터 유사도 | 내가 점수를 준 아이템 중 그 아이템과 비슷한 k개에 준 점수의 가중 평균 |
| 유사도 | 계산 |
|---|---|
| 평균 제곱 차이(MSD) | 두 사용자가 공통으로 평가한 아이템의 점수 차 제곱 평균의 역수 1 / (msd + 1) |
| 코사인 | 두 벡터의 사잇각 |
| 피어슨 | 각자 평균을 뺀 뒤의 상관. 사람마다 다른 점수 기준을 걷어 낸다 |
| 피어슨-베이스라인 | 평균 대신 베이스라인 예측값을 뺀 상관. 공통 평점 수가 적으면 shrinkage (n − 1) / (n − 1 + 100)을 곱해 유사도를 줄인다 |
가중 평균도 세 가지로 나뉜다. 점수를 그대로 평균하거나(KNNBasic), 각 이웃의 평균을 빼고 평균한 뒤 내 평균을 더하거나(KNNWithMeans), 베이스라인을 빼고 평균한 뒤 베이스라인을 더한다(KNNBaseline). 뒤로 갈수록 사람마다 다른 점수 습관을 더 잘 걷어 낸다. 공통 평점이 너무 적은 쌍은 min_support로 제외한다. 파이썬 scikit-surprise 패키지가 이 알고리즘들을 같은 인터페이스로 제공한다.
아이템 기반이 운영에서 더 잘 버틴다. 사용자 수 m이 아이템 수 n보다 훨씬 많으면 사용자 유사도는 공간이 O(m²)이고 계산이 더 크다. 아이템 사이 관계는 사용자 관계보다 천천히 변하므로, Amazon(2003)처럼 아이템 쌍 유사도를 오프라인에서 미리 계산해 두고 요청 때는 내가 본 아이템의 이웃만 합친다. 이론상 n²쌍이지만 함께 평가된 적 없는 쌍이 대부분이라 실제로는 훨씬 적고, 최소 공통 평가 수와 이웃 수 상한으로 더 줄인다. 아이템 사이에는 사용자 평균을 뺀 조정 코사인이 잘 맞는다. 「Family Guy를 봤으니 American Dad」처럼 근거를 보여 주기도 쉽다.
암묵적 피드백용 아이템 CF는 Hulu 사례가 단순한 모양을 보여 준다.
선호 예측 p(u, i) = Σ_{j ∈ N(u)} r(u, j) · s(i, j) N(u): u가 본 쇼
유사도 s(i, j) = |N(i) ∩ N(j)| / sqrt(|N(i)| · |N(j)|) N(i): i를 본 사용자이 식은 모두가 보는 인기 쇼가 거의 모든 쇼와 유사해지는 문제(「해리 포터 문제」)가 있어 인기 쇼의 가중치를 낮춘다. 피어슨 사용자 CF를 다듬는 고전 기법으로는 공통 평가 수가 적은 이웃의 가중치를 줄이는 significance weighting, 유사도가 1에 가까운 이웃을 키우는 case amplification, 분산이 큰(의견이 갈리는) 아이템에 가중을 주는 방법이 있다.
행렬 분해
가장 오래되고 여전히 강력한 CF 모델이다. 2006년 넷플릭스 프라이즈에서 널리 알려졌다.
사용자 × 아이템 행렬 (소비했으면 1, 아니면 빈칸)
≈ 사용자 행렬 (사용자 × k) · 아이템 행렬 (k × 아이템)
학습: 두 행렬의 곱이 원래 행렬과 비슷해지도록
결과: 비어 있던 칸에도 숫자가 생긴다 → 그것이 예측 선호도잠재 요인(latent factor)은 장르 같은 숨은 취향 축이다. 액션을 싫어하고(−1) 코미디(2)·드라마(3)를 좋아하는 사용자 벡터 p(u) = (−1, 2, 3)와 액션 2·코미디 1·드라마 1인 영화 벡터 q(i) = (2, 1, 1)의 내적 −2 + 2 + 3 = 3이 예측 점수다. 선형대수의 특이값 분해(SVD)는 빈칸이 없는 행렬에만 바로 쓸 수 있으므로, 실제로는 관측된 칸에 대해서만 베이스라인을 더한 식을 최소화한다.
r̂(u, i) = μ + b(u) + b(i) + q(i)ᵀ p(u)
최소화: Σ_(관측된 u,i) (r(u,i) − r̂(u,i))² + λ(b(u)² + b(i)² + ‖q(i)‖² + ‖p(u)‖²)넷플릭스 프라이즈에서 「SVD」라고 불린 것이 이 모델이다. 값이 음수가 되지 않게 제약한 비음수 행렬 분해(NMF)도 쓴다.
- ALS(Alternating Least Squares): 사용자 행렬과 아이템 행렬을 번갈아 고정하며 푸는 방식이다. 병렬화가 쉬워 Spark MLlib에 기본으로 들어 있다. 분산·증분 처리, SIMD·GPU 연산, 네거티브 샘플링으로 일 수백만 사용자 규모도 몇 분 안에 학습한다.
- 변형으로 BPR-MF(순위를 직접 학습), LMF(로지스틱) 같은 모델이 있다. 추천 분야에서는 복잡한 딥러닝보다 얕은 모델이 여전히 꽤 우위인 경우가 많다.
- 행렬 분해로 얻은 아이템 잠재 벡터끼리 코사인 유사도를 재면 item-to-item 연관 추천(상품 상세 하단의 연관 상품 등)이 된다. ALS가 사용자 기준 모델이라도 이렇게 아이템 기준으로 바꿔 쓸 수 있다.
- 행렬을 분해하지 않고 사용자 이력을 문장으로, 아이템 ID를 단어로 보고 word2vec을 학습해도 아이템 벡터가 나온다(Item2Vec). 예를 들어 브런치 사용자 약 3.2만 명의 관심 작가 목록(33만 건)을 한 사람당 한 문장으로 두고 작가 ID를 단어로 학습하면, 작가 약 3,500명의 벡터로 「이 작가와 비슷한 작가」 추천 API를 만들 수 있다. 벡터 연산으로 두 작가 사이를 잇는 작가나 두 작가를 더한 성향의 작가도 찾는다. 학습 설정과 한계는 딥러닝 추천의 Item2Vec에 있다.
오토인코더
입력을 적은 차원으로 압축했다가 다시 복원하도록 학습하는 신경망이다. 행렬 분해보다 유연해서 태그 같은 부가 정보를 함께 넣을 수 있다. 쓸모없는 정보는 버리고 복원에 필요한 핵심만 남기도록 학습된다.
디노이징 오토인코더(Denoising Autoencoder) 는 일부러 문제를 어렵게 만든다. 플레이리스트를 0·1 벡터로 보고 곡의 절반을 가린 채 나머지로 가려진 곡을 맞히게 학습하면, 그 임베딩으로 플레이리스트 이어 붙이기(playlist continuation) 를 한다.
곡과 태그를 같은 공간에 임베딩하면 「느낌」으로도 찾고 벡터 연산도 된다. 예를 들어 「맥주」와 가까운 태그로 「여름밤」이 나오고, 시드 곡 + 「힙한」 태그로 비슷한 아티스트 목록과 요약 태그를 함께 돌려준다.
CF의 한계
| 문제 | 뜻 |
|---|---|
| 콜드 스타트(cold start) | 이력이 없는 신규 사용자·신규 아이템은 추천할 근거가 없다 |
| 희소성(data sparsity) | 아이템이 많을수록 대부분의 칸이 비어 관계를 못 찾는다 |
| 인기 편향(popularity bias) | 많이 소비된 것이 계속 추천돼 롱테일이 묻힌다 |
| 내용 무관 | 같이 소비됐을 뿐 내용은 상관없는 아이템이 섞인다 |
| 확장성 | 사용자·아이템이 늘수록 메모리와 학습 시간이 커진다 |
콘텐츠 기반 필터링
아이템의 내용을 벡터로 바꾸고 가까운 것을 찾는다. 과거에는 사람이 설계한 특성을 썼고, 지금은 딥러닝 임베딩이 기본이다.
| 대상 | 쓰는 기법 | 예 |
|---|---|---|
| 텍스트 | 단어·문서 임베딩, 토픽 모델(LDA), 클러스터링. 지금은 문장 임베딩·LLM 임베딩이 표준 | 뉴스·글 유사글 |
| 이미지 | CNN·비전 모델의 이미지 벡터 | 그림체가 비슷한 웹툰, 영상 썸네일, 쇼핑 상품 이미지 |
| 음악 | 스펙트로그램·MFCC 특성에 CNN·오토인코더 | 분위기 분류, 코드·템포가 비슷한 곡 |
오디오는 파형을 그대로 넣는 엔드투엔드 방식과, 파형을 짧게 잘라 푸리에 변환한 뒤 사람 청각에 맞춰 주파수 축을 로그로 줄인 멜 스펙트로그램을 넣는 방식이 있다. 엔드투엔드는 전처리가 없지만 데이터가 훨씬 많이 든다. 이미지에서 잘 되는 합성곱 모델이 멜 스펙트로그램에서도 잘 된다.
CBF는 행동 데이터가 없어도 되므로 신규 아이템에 강하고 인기 편향이 적다. 대신 사용자의 실제 반응을 모르므로 결과가 엉뚱하게 느껴질 때가 있다. 그 의외성이 다양성에는 장점이 된다. CF와 CBF는 서로의 약점을 메운다.
둘을 섞는 앙상블
| 방법 | 내용 | 주의 |
|---|---|---|
| 가중합 | 모델별 점수에 가중치를 곱해 더한다. 가중치는 TPE·Hyperopt·Hyperband 같은 하이퍼파라미터 탐색으로 정한다 | 모델마다 점수의 의미와 범위가 달라 그대로 더하면 안 된다 |
| 순위 결합(rank aggregation) | 점수 대신 순위를 합친다. Reciprocal Rank Fusion, CombMNZ | 점수가 없거나 비교 불가능할 때 쓴다 |
| 폴백(fallback) | 새 모델이 결과를 못 내는 아이템은 기존 방식(예: 카테고리별 클릭 랭킹) 결과를 보여 준다 | 가장 싸게 희소성을 피하는 방법이다 |
A/B 테스트에서는 CF와 CBF가 각각 기존 로직보다 낫고, 둘을 합친 앙상블이 어느 하나보다 나은 경우가 많다.
하이브리드는 구조로도 나눈다. 단일형은 한 알고리즘에 여러 근거를 넣고(콘텐츠 유사도로 가상 평점을 만들어 희소성을 메우는 특징 증강), 병렬형은 여러 추천기의 결과를 가중·투표·스위칭(평점이 적은 사용자는 지식 기반이나 콘텐츠 기반, 많으면 CF)으로 고르며, 파이프라인형은 앞 단계의 결과를 다음 단계의 입력으로 쓴다. 규칙·제약으로 고르는 지식 기반 추천(조건을 다 만족하는 상품이 없으면 「브랜드 조건을 풀까요, 예산을 늘릴까요」처럼 최소한의 완화를 제안한다)은 콜드 스타트가 없지만 지식을 만들고 고치는 비용이 든다.
평가
| 구분 | 지표 | 쓰는 곳 |
|---|---|---|
| 오프라인: 점수 예측 | RMSE, MAE, FCP(실제와 예측의 대소 관계가 일치하는 쌍의 비율) | 명시적 평점을 맞히는 문제. 평점을 9:1 등으로 나누거나 K-겹 교차 검증 |
| 오프라인: 순위 | AUC, MAP, Recall@K·Hit@K, nDCG | 과거 로그를 학습·검증용으로 나눠 측정 |
| 온라인 | CTR(노출당 클릭), 체류 시간, 전환율, 거래액 | 실제 사용자에게 보여 주는 A/B 테스트 |
오프라인 점수는 사용자가 실제로 본 것에 대한 반응만 담고 있어 새 모델의 진짜 효과를 다 보여 주지 못한다. 전후 비교도 트렌드·시간대 영향이 섞여 불공정하다. 그래서 같은 시간에 사용자를 나눠 비교하는 A/B 테스트가 최종 판단 기준이다. 실험 방법은 실시간 추천과 실험에 있다.
오프라인 점수가 좋아도 배포하면 엉뚱한 추천(다른 카테고리 상품 등)이 보일 수 있다. 그럴 때는 카테고리 경계 조건 같은 규칙을 덧댄다.
정확도 지표만으로는 부족하다. 다양성, 커버리지, 새로움, 의외성, 인기 편중(롱테일을 얼마나 추천하나)을 함께 본다. MAE 0.7이 사용자에게 무엇을 뜻하는지 말하기 어렵고, 정밀도·재현율은 「무엇이 관련 있었나」의 정답을 모르는 상태에서 잰다는 한계가 있다. Hulu는 인기순·평점순 베이스라인보다 CTR이 훨씬 높았지만, 새로움·다양성을 더해 CTR을 10% 넘게 더 올렸다. 오프라인 RMSE·정밀도로는 드러나지 않는 차이다.
추천 기법보다 자리를 먼저 본다
개인화 모델 전에 거래 로그(조회·구매)만으로 SQL 집계로 만들 수 있는 추천이 먼저다.
| 추천 | 만드는 법 |
|---|---|
| 베스트 | 조회 기반, 구매 기반, 사이트 전체, 카테고리별 집계 |
| 연관 | 같은 사용자가 본 상품, 같은 세션에서 본 상품, 바로 앞뒤로 이어 본 상품의 동시 출현 집계 |
| 개인화 | 내가 본 상품들의 연관 추천을 합치거나, 비슷한 사용자(KNN)의 이력에서 고른다 |
「어떤 알고리즘을 쓸까」보다 「추천을 어느 자리에 쓸까」를 먼저 정한다. 연관 상품처럼 「지금 보는 것과 가장 비슷한 것」이 답인 자리는 서버 비용 대비 딥러닝의 이득이 작아 ALS 같은 얕은 모델로 충분하다. 도구도 이미 데이터 파이프라인에 있는 것(Spark 등)과 팀이 익숙한 언어를 고르면 결과를 빨리 낸다. Spark RDD를 cache()한 뒤 unpersist()를 잊으면 메모리를 점유하므로 반드시 풀어 준다.
추천 단위도 자리에 맞춘다. 에피소드·클립이 수십 개씩 딸린 동영상 서비스는 영상이 아니라 쇼 단위로 추천해야 같은 쇼의 에피소드가 목록을 채우지 않는다. 방영 중인 쇼의 비중이 여름·주말에 줄듯 계절성도 반영한다. Hulu의 추천 허브는 최상위 추천, 선호 장르 세 개, 북마크, 이미 평가한 쇼 여섯 줄로 구성했고, 마지막 줄은 명시적 평점을 모으는 장치였다.
정리
- CF는 행동, CBF는 내용을 본다. 실서비스는 둘을 섞는다.
- 실서비스 데이터는 대부분 암묵적 피드백이다.
- 행렬 분해(ALS)는 오래됐지만 여전히 강력한 출발점이다. 아이템 벡터의 코사인 유사도로 연관 추천도 된다.
- 콜드 스타트와 희소성은 CBF 특성, 인기 아이템, 기존 로직 폴백으로 메운다.
- 오프라인 지표로 걸러 내고, 최종 판단은 A/B 테스트로 한다.
관련 노트: 추천 시스템, 딥러닝 추천 시스템, 문자열·문서 유사도, 머신 러닝 기초, 분류 모델 성능 평가 지표
원본 기록10
- 원문 (새 창) brunch.co.kr/@kakao-it/72
- 원문 (새 창) brunch.co.kr/@kakao-it/342
- 원문 (새 창) www.theteams.kr/teams/7937/post/70672
- 원문 (새 창) www.theteams.kr/teams/7937/post/70673
- 원문 (새 창) www.theteams.kr/teams/7937/post/70674
- 원문 (새 창) datascienceschool.net/view-notebook/fcd3550f11ac4537acec8d18136f2066/
- GitHub 원문 (새 창) github.com/recobell/fc-rec-workshop
- 원문 (새 창) brunch.co.kr/@goodvc78/7
- 원문 (새 창) ijcai13.org/files/tutorial_slides/td3.pdf
- 원문 (새 창) tech.hulu.com/blog/2011/09/19/recommendation-system.html