qcoding

[AI논문리뷰-추천알고리즘] GRU4Rec - 세션 기반 추천을 RNN으로 풀어낸 출발점 본문

AI논문리뷰-추천알고리즘

[AI논문리뷰-추천알고리즘] GRU4Rec - 세션 기반 추천을 RNN으로 풀어낸 출발점

Qcoding 2026. 5. 6. 21:09
반응형
논문  Session-based Recommendations with Recurrent Neural Networks 저자  Balázs Hidasi et al. 학회/연도  ICLR 2016 Conference Track / arXiv 2015-2016 arXiv  1511.06939

한 문단 요약

이 논문은 로그인 사용자 이력 없이 현재 세션의 짧은 클릭 흐름만 보고 다음 아이템을 추천하는 문제를 RNN, 특히 GRU로 풀었다. 핵심은 세션을 하나의 시퀀스로 보고, 마지막 클릭 하나만 보는 Item-KNN 대신 지금까지의 클릭 순서를 hidden state에 누적하는 것이다. 여기에 session-parallel mini-batch, mini-batch 기반 negative sampling, BPR/TOP1 랭킹 손실을 붙여 실제 추천 환경의 큰 item space를 다뤘고, RSC15와 VIDEO 데이터에서 Item-KNN보다 Recall@20 기준 약 20-30% 개선을 보였다.

이 논문은 무엇을 해결하려고 했나?

이 논문이 겨냥한 문제는 "사용자 ID나 장기 프로필이 없는 상황에서, 현재 세션의 클릭 순서만으로 다음에 볼 아이템을 추천할 수 있는가?"다.

2015년 전후의 추천 시스템은 사용자-아이템 행렬을 분해하는 matrix factorization이나 item-to-item similarity에 많이 기대고 있었다. 하지만 작은 쇼핑몰, 뉴스/미디어 사이트, 비회원 방문, 개인정보 이슈가 큰 서비스에서는 안정적인 사용자 프로필을 만들기 어렵다. 이런 환경에서는 사용자가 방금 본 상품, 방금 본 영상, 방금 읽은 글 같은 세션 내부 신호가 거의 전부다.

기존의 item-to-item 추천은 실무적으로 강력하지만 보통 마지막 클릭 하나에 크게 의존한다. 예를 들어 사용자가 "러닝화 -> 스포츠 양말 -> 러닝 벨트"를 봤다면 다음 추천은 세 클릭의 흐름을 봐야 하지만, 단순 Item-KNN은 마지막 아이템과 같이 본 상품만 밀어줄 가능성이 크다. 이 논문은 이 흐름 전체를 GRU의 hidden state로 압축해 다음 아이템 랭킹을 만드는 방식을 제안한다. 이후 "GRU4Rec"이라는 이름으로 세션 기반 추천의 대표 출발점처럼 다뤄진 이유가 여기에 있다.

배경지식과 핵심 키워드

Session-based Recommendation
세션 기반 추천은 장기 사용자 프로필 대신 현재 방문 세션 안의 이벤트만 사용한다. 논문은 RSC15에서 약 6개월치 7,966,257개 세션, 31,637,239 클릭, 37,483개 아이템을 학습에 사용했고, 테스트는 다음 날 15,324개 세션으로 분리했다. 이 설정에서는 같은 사용자를 추적하는 추천보다 "지금 이 흐름에서 다음 클릭이 무엇인가"가 더 중요한 예측 문제가 된다.
GRU
GRU는 RNN의 hidden state를 update gate와 reset gate로 제어하는 recurrent unit이다. 논문에서는 아이템 클릭을 시간 순서대로 입력하고, hidden state가 세션의 현재 문맥을 담도록 학습한다. 기본 업데이트는 h_t=(1-z_t)h_{t-1}+z_t h_hat_t 형태라, 최근 클릭을 반영하면서도 이전 클릭 정보를 완전히 버리지 않는 구조다.
1-of-N Item Encoding
각 클릭 아이템을 전체 아이템 수 N 길이의 one-hot 벡터로 넣는 방식이다. 아이템이 37,483개라면 입력 벡터도 37,483차원이지만 실제로 1인 좌표는 하나뿐이다. 저자들은 embedding layer도 실험했지만, 이 논문 설정에서는 1-of-N encoding이 더 잘 나와서 최종 선택했다.
Session-parallel Mini-batch
NLP처럼 긴 시퀀스를 잘라 window mini-batch로 만들면 세션의 시작과 끝, hidden state reset이 깨진다. 이 논문은 X개 세션을 나란히 놓고 각 세션의 첫 이벤트를 첫 mini-batch, 두 번째 이벤트를 다음 mini-batch로 구성한다. 어떤 세션이 끝나면 그 슬롯에 다음 세션을 넣고 해당 hidden state만 0으로 초기화한다.
Mini-batch Negative Sampling
추천은 수만-수십만 아이템 전체 점수를 매번 계산하면 비용이 커진다. 논문은 현재 mini-batch 안의 다른 정답 아이템들을 negative sample로 재사용한다. 인기 아이템일수록 mini-batch에 더 자주 등장하므로, 별도 샘플러 없이도 popularity-proportional sampling과 비슷한 효과를 얻고 행렬 연산도 단순해진다.
BPR Loss
BPR은 positive item의 점수가 negative item보다 높아지도록 학습하는 pairwise ranking loss다. 논문에서는 한 세션 시점 s에서 정답 item i와 샘플 item j들의 점수 차 r_si-r_sj에 sigmoid와 log를 적용한다. 다음 클릭 하나를 맞히는 추천 문제는 분류처럼 보이지만, 실제 제품 화면은 top-N 랭킹이 중요하므로 pairwise loss가 잘 맞는다.
TOP1 Loss
TOP1은 저자들이 이 작업을 위해 제안한 손실이다. 정답 아이템보다 높은 점수를 받은 negative sample의 비율, 즉 상대 rank를 sigmoid로 근사한다. 동시에 negative item 점수를 0 근처로 당기는 정규화 항을 넣어 점수가 계속 커지는 불안정성을 줄인다. 최종 1000-unit GRU에서 TOP1은 VIDEO Recall@20 0.6624, MRR@20 0.3891로 가장 좋은 조합 중 하나였다.
Recall@20 / MRR@20
Recall@20은 실제 다음 아이템이 추천 상위 20개 안에 들어간 비율이다. MRR@20은 그 아이템이 몇 번째에 나왔는지를 reciprocal rank로 반영하되, 20위 밖이면 0으로 둔다. 논문이 Recall@20을 1차 지표로 둔 이유는 실제 추천 UI에서 사용자가 보게 되는 후보 수가 제한적이기 때문이다.

핵심 인사이트

이 논문의 설계는 모두 하나로 이어진다. 세션을 시퀀스로 보려면 GRU가 필요하고, 길이가 제각각인 세션을 학습하려면 session-parallel mini-batch가 필요하며, 수만 개 아이템을 랭킹하려면 mini-batch negative sampling과 pairwise ranking loss가 필요하다.

기존 방법의 한계

Matrix factorization은 사용자와 아이템의 latent vector를 학습한 뒤 dot product로 선호도를 예측한다. 이 방식은 장기 사용자 ID가 있을 때 강하지만, 세션 기반 추천에서는 새 방문자가 들어올 때 미리 학습된 사용자 벡터가 없다. 논문은 BPR-MF를 세션 내 아이템 벡터 평균으로 우회해 비교하지만, RSC15 Recall@20 0.2574, VIDEO Recall@20 0.0692로 Item-KNN보다도 약했다.

Item-KNN은 훨씬 강한 baseline이다. 같은 세션에서 자주 함께 등장한 아이템끼리 유사도를 계산하고, 현재 아이템과 비슷한 아이템을 추천한다. RSC15 Recall@20 0.5065, VIDEO Recall@20 0.5508로 단순 popularity나 BPR-MF보다 확실히 좋았다. 하지만 근본적으로 마지막 클릭 근처의 co-occurrence에 강하게 묶인다. 세션 초반부터 이어진 순서 정보, 여러 클릭 사이의 전환 맥락, 사용자의 현재 목적 변화는 충분히 반영하기 어렵다.

Markov chain이나 MDP 접근도 자연스러운 후보지만, 상태 공간이 빠르게 커진다. "A 다음 B"만 보면 1차 전이로 충분하지만, "A -> B -> C -> ?"처럼 과거 선택을 길게 볼수록 가능한 상태 수가 폭발한다. 이 논문이 RNN을 끌고 온 이유는 바로 이 지점이다. RNN hidden state는 긴 클릭 이력을 고정 길이 벡터로 압축하므로, 이론적으로는 순서를 살리면서도 상태 공간 폭발을 피할 수 있다.

제안 방법의 핵심 아이디어

제안 방법은 각 세션을 아이템 클릭의 시퀀스로 본다. 시점 t의 입력은 현재 클릭한 아이템 x_t이고, 출력은 다음 이벤트의 아이템이 될 가능성 점수다. 모델은 모든 후보 아이템에 대해 점수를 낼 수 있지만, 학습 때는 정답 아이템과 mini-batch 내부 negative item 위주로 비교한다.

아키텍처는 단순하다. 입력 1-of-N item vector가 들어오고, 필요하면 embedding layer를 거친다. 그 다음 하나 이상의 GRU layer가 세션 상태를 갱신한다. 마지막에는 feed-forward layer를 둘 수 있고, 출력층은 각 아이템에 대한 score를 만든다. 저자들은 여러 구조를 실험했지만 최종적으로는 단일 GRU layer가 가장 좋았다고 보고한다. 세션 길이가 일반적으로 짧기 때문에, 여러 recurrent layer가 서로 다른 장기 시간 스케일을 만들 필요가 크지 않았을 가능성이 있다.

논문의 재미있는 점은 "딥러닝 모델을 추천에 붙였다"보다 "추천 문제에 맞게 RNN 학습 루프를 바꿨다"에 있다. 세션 길이가 들쭉날쭉하므로 hidden state reset을 세션 단위로 관리했고, item space가 크므로 output sampling을 설계했으며, 추천 화면에서는 확률 보정보다 상위 랭킹이 중요하므로 BPR/TOP1 ranking loss를 썼다. 이 세 가지가 GRU4Rec의 실질적인 기여다.

모델 구조/알고리즘 흐름

  1. 세션들을 시간순으로 정렬하고, 동시에 처리할 X개 세션을 mini-batch 슬롯에 올린다.
  2. 각 슬롯의 현재 아이템을 1-of-N vector로 만들어 GRU에 입력한다.
  3. GRU hidden state는 해당 세션의 지금까지 클릭 흐름을 저장한다.
  4. 출력층은 다음 아이템 후보들의 score를 만든다.
  5. 정답 다음 아이템과 mini-batch의 다른 정답 아이템들을 negative sample로 두고 BPR 또는 TOP1 loss를 계산한다.
  6. 세션이 끝난 슬롯은 hidden state를 0으로 reset하고 다음 세션을 배치한다.
  7. 추론 때는 현재 세션의 클릭을 순서대로 넣고, 마지막 hidden state에서 나온 score가 높은 아이템 top-N을 추천한다.

논문은 classic RNN과 LSTM도 간단히 실험했지만 GRU가 더 좋았다고 한다. 또 item embedding layer, 여러 GRU layer, 추가 feed-forward layer도 성능 개선에 크게 도움이 되지 않았다. 그래서 최종 형태는 생각보다 담백하다. 단일 GRU layer에 큰 hidden size, ranking loss, 세션 병렬 batch가 핵심이다.

논문 그림/표로 이해하기

GRU 기반 세션 추천 네트워크 구조
원문 Figure 1. 입력 아이템 one-hot 표현에서 GRU layer와 feed-forward layer를 거쳐 아이템 점수를 출력한다. 출처: Hidasi et al., "Session-based Recommendations with Recurrent Neural Networks", ICLR/arXiv 2016. arXiv:1511.06939 - arXiv 라이선스 하에 인용.
session-parallel mini-batch 생성 방식
원문 Figure 2. 여러 세션을 병렬 슬롯에 놓고, 세션이 끝나면 해당 hidden state를 reset한 뒤 다음 세션을 투입한다. 출처: Hidasi et al., "Session-based Recommendations with Recurrent Neural Networks", ICLR/arXiv 2016. arXiv:1511.06939 - arXiv 라이선스 하에 인용.
모델 RSC15 Recall@20 RSC15 MRR@20 VIDEO Recall@20 VIDEO MRR@20
Item-KNN baseline 0.5065 0.2048 0.5508 0.3381
GRU TOP1 1000 0.6206 0.2693 0.6624 0.3891
GRU BPR 1000 0.6322 0.2467 0.6311 0.3136
논문 Table 1과 Table 3의 핵심 수치를 블로그용으로 재구성했다.

실험 설정과 결과 해석

실험 데이터는 두 개다. RSC15는 RecSys Challenge 2015의 전자상거래 클릭스트림으로, 학습에는 약 6개월 데이터가 사용됐다. 테스트는 바로 다음 날 세션으로 나누었고, 학습에 등장하지 않은 아이템과 길이 1 세션은 제거했다. VIDEO는 유튜브와 비슷한 OTT 서비스의 시청 이벤트 데이터로, 약 2개월보다 조금 짧은 기간 동안 수집된 300만 세션, 1,300만 watch event, 33만 video item 규모다.

baseline 중에서는 Item-KNN이 가장 강했다. POP은 RSC15 Recall@20 0.0050으로 거의 의미가 없었고, S-POP은 반복성이 높은 도메인에서는 어느 정도 강하지만 일반적인 다음 아이템 예측에서는 한계가 있었다. BPR-MF도 세션 프로필을 item vector 평균으로 억지 구성해야 하므로 세션 추천 본질과 잘 맞지 않았다.

가장 중요한 결과는 GRU 기반 모델이 강한 Item-KNN을 넘어섰다는 점이다. RSC15에서 BPR 1000-unit GRU는 Recall@20 0.6322로 Item-KNN의 0.5065보다 24.82% 높았다. VIDEO에서는 TOP1 1000-unit GRU가 Recall@20 0.6624로 Item-KNN 대비 20.27% 높고, MRR@20도 0.3891로 15.08% 개선됐다. 논문은 이를 약 20-30% 정확도 향상으로 요약한다.

또 하나 눈여겨볼 부분은 cross-entropy의 불안정성이다. 100 hidden unit에서는 꽤 좋아 보이지만, VIDEO의 1000-unit 실험은 수치적으로 불안정해서 결과를 제시하지 못했다. 저자들은 pointwise 방식이 정답 아이템 점수만 독립적으로 끌어올리고 negative push가 약해 불안정해진다고 해석한다. 추천 결과 화면의 목적이 calibrated probability가 아니라 top-N ranking이라면, BPR/TOP1 같은 pairwise ranking loss가 더 자연스럽다는 결론이다.

실험을 읽는 포인트

이 논문은 최신 대규모 추천 벤치마크 논문처럼 복잡한 비교를 하지는 않는다. 대신 "세션의 순서 정보를 GRU hidden state로 누적하면, 마지막 클릭 중심 Item-KNN보다 실제 다음 클릭 예측이 좋아진다"는 가설을 당시 강한 baseline과 수치로 보여준 데 의미가 있다.

한계와 비판적 관점

첫째, 지금 기준으로 보면 feature가 매우 단순하다. 아이템 ID 시퀀스만 사용하고, 상품 이미지, 텍스트, 가격, 카테고리, 시간 간격, 사용자 디바이스 같은 side information은 들어가지 않는다. 논문 결론에서도 후속 작업으로 item content에서 자동 추출한 representation을 학습하겠다고 밝힌다.

둘째, negative sampling이 mini-batch 내부 정답 아이템에 의존한다. 구현은 효율적이지만, mini-batch 구성과 popularity 분포에 따라 학습 신호가 달라질 수 있다. 특히 매우 긴 tail item이 중요한 서비스라면 인기 기반 sampling이 희귀 아이템 추천 품질을 충분히 보장하지 못할 수 있다.

셋째, 세션 기반 추천 자체가 장기 선호를 버린다. 비회원 쇼핑몰이나 뉴스 추천에서는 장점이지만, 음악/영상 구독 서비스처럼 장기 취향과 현재 컨텍스트가 동시에 중요한 도메인에서는 세션 RNN만으로는 부족하다. 이후 추천 연구가 session-aware, sequential recommendation, Transformer 기반 모델로 확장된 것도 이 한계와 연결된다.

넷째, 실험 규모와 재현성은 오늘날 기준으로 다소 제한적이다. 데이터셋 두 개와 당시 기준 baseline 중심이며, 사용자 행동 로그 특성상 공개 재현이 쉽지 않은 부분도 있다. 그래서 이 논문은 "최종 추천 모델의 정답"이라기보다, 세션 기반 추천을 딥러닝 sequence modeling 문제로 바꾼 초기 기준점으로 읽는 편이 좋다.

구현하거나 응용한다면 무엇을 봐야 하나?

실무 구현에서 첫 번째로 볼 것은 데이터 전처리다. 세션 길이 1은 학습 타겟이 없으므로 제거하고, 학습에 없는 item이 테스트에 나오면 cold-start로 따로 처리해야 한다. 이벤트 시간순 정렬, 세션 종료 기준, bot이나 비정상적으로 긴 세션 필터링도 모델보다 먼저 결정해야 한다.

두 번째는 batch 구성이다. 일반적인 DataLoader처럼 샘플을 독립적으로 shuffle하면 GRU hidden state를 세션 흐름에 맞게 유지하기 어렵다. 논문식 session-parallel batch는 세션 슬롯마다 hidden state를 따로 들고 있다가 세션이 끝날 때만 reset한다. PyTorch로 구현한다면 batch index별 hidden state reset mask를 만드는 부분이 핵심이다.

세 번째는 loss 선택이다. 단순 softmax cross-entropy는 구현은 쉽지만 item 수가 커질수록 비용과 안정성 문제가 생긴다. BPR이나 TOP1처럼 정답 item과 sampled negative item의 score 차이를 직접 최적화하면 추천 화면의 top-N 목표와 잘 맞는다. 다만 현재라면 sampled softmax, BPR-max, cross-batch negative, in-batch sampled CE 등 후속 기법도 함께 비교할 만하다.

게임이나 앱 추천으로 확장한다면 "현재 플레이 세션에서 어떤 콘텐츠를 다음에 보여줄지"에 적용할 수 있다. 예를 들어 유저가 최근에 본 스테이지, 장비, 광고 보상, 상점 아이템의 순서를 세션 시퀀스로 만들고, 다음 액션 후보를 랭킹하는 식이다. 단, 개인정보나 장기 프로필을 쓰지 않는다는 장점과 장기 취향을 놓친다는 약점을 함께 고려해야 한다.

한 줄 결론과 다음에 읽을 논문

한 줄로 정리하면, 이 논문은 "추천을 사용자 프로필의 행렬 완성 문제가 아니라 현재 세션의 sequence prediction 문제로 보자"는 전환을 GRU와 ranking loss로 설득한 고전이다.

다음에는 GRU4Rec의 후속 개선인 BPR-max 계열과, 세션 기반 추천을 attention/Transformer로 확장한 SASRec(Self-Attentive Sequential Recommendation)을 이어서 읽으면 흐름이 자연스럽다.

출처

반응형
Comments