Post

Session-based Recommendations With Recurrent Neural Networks, (ICLR'16)

Paper LinkImplementation

Abstract

Challenges
  1. Session 기반 추천에서 MF (Matrix Factorization), MDP (Markov Decision Processes)의 성능이 좋지 않다.
  2. 산업에서 사용하는 기존의 방법들(neighborhood methods)은 제일 최근 클릭 정보만 추천할 때 사용한다.
Address
  1. RNN 기반의 model을 추천에 적용해 과거의 클릭 정보들도 사용한다.
  2. 추가적으로 session 추천에 더 적합한 loss (TOP1Loss)를 제안한다.

Ⅰ. Introduction

대부분 site(온라인 쇼핑몰, 뉴스, etc.)는 user의 history를 오랜 기간 추적하지 않는다. Cookies 등으로 user를 인식하는 정도이고, histroy를 추적한다고 하더라도 session-based와 그 환경이 별반 다르지 않다. Session 기반 추천에서는 같은 user가 다른 session을 사용하면 서로 독립적이라고 인식한다.

온라인 쇼핑몰에서 사용하던 기존의 방법들은 item-to-item similarity, co-occurrence 등이 있는데, 이 방법들은 과거 클릭 정보를 활용하지 않고 제일 최근 클릭만 이용해 추천을 한다.

그래서 저자들은 과거의 클릭 정보를 활용하도록 RNN 기반의 session-based 추천 model과 해당 task에 적합한 새로운 ranking loss function을 제안한다.

  • 정확한 점수를 예측하는 것이 아닌, 순위를 예측해야 한다.
    • ex) BPRLoss, 본 논문에서 제안한 TOP1Loss, …

생략

Ⅲ. Recommendations With RNNs

RNN은 가변적인 sequence data를 학습하기 위해 고안되었다. 이러한 RNN 계열 중 GRU라는 model이 있고, 본 논문에서는 GRU를 사용했다.

ⅰ. Customizing the GRU Model

Figure 1: General architecture of the network. Processing of one event of the event stream at once.

Model의 input으로는 바로 직전 클릭한 item 1개 일수도 있고, 과거 클릭한 모든 items 일수도 있다. 전자의 경우 one-hot vector가 input으로 들어갈 것이고, 후자의 경우 item의 representation을 discount weighted sum한 것이 들어간다. 본 논문에서는 전자의 경우가 더 잘된다는 것을 실험적으로 발견했다. 한 session을 예로 들자면, input으로 하나의 item이 들어오면 다음에 클릭할 item 하나를 예측해야 하는 것으로 many-to-many task이다.

ⅱ. Session-Parallel Mini-Batches

NLP는 문장이 있다면, sliding으로 windowed fragments를 만들고 mini-batches로 활용한다. 이러한 방법은 session based 추천에 맞지 않다. 먼저, session당 sequence가 서로 다르다. 그리고 한 session 동안 사용자의 선호도가 어떻게 변해가는 지에 관심이 있기 때문에 fragments로 만드는 것은 적절하지 않다.

그래서 해당 논문에서는 session-parallel mini-batches를 사용한다.

  1. Sessions에 순서를 부여한다.
  2. Batch size를 B라고 했을 때 B개의 session에 대해 각 session마다 item 하나를 input으로 사용하고 그 다음 item을 output으로 사용한다.
  3. 2번을 계속 반복하다 만약 session이 끝나면, 새로운 session을 부여한다.
  4. 새로운 session을 배정한 것에 해당하는 hidden state는 0으로 초기화한다.
  5. 이를 모든 session을 사용할 때 까지 한다.

예시로 살펴보면 아래와 같다.

Figure 2: Session-parallel mini-batch creation.

  1. Batch size를 3이라고 한다.
  2. 처음 3개의 session에 대해 item 하나를 input으로 사용하고 그 다음 item을 output을 사용한다.
  3. Session2가 가장 먼저 끝나고, 해당 부분에 그 다음 session인 session4를 배정한다.
  4. Session2가 사용하던 hidden state는 모두 0으로 초기화한다.
  5. 계속 학습한다.

ⅲ. Sampling On The Output

추천 시스템이 items가 많을 때 유용하다. 그렇지만 모든 items에 대한 점수/ranking을 부여하는 것은 현실적으로 불가능하다. 그래서 작은 subset에 대해 점수를 계산해야 한다. Subset을 활용하면, 몇몇의 weights만 update가 될 것이고 negative samples이 필요하게 된다.

  • 예를 들면, Fig. 1에서 output으로 모든 items 대신 일부 items에 대한 점수만 얻고 그것만 고려한다.
  • 따라서 개념적으로는 점수를 고려하지 않은 item에 대한 weight는 backpropagation을 통해 update가 되지 않는 것이다.
  • 일부 items가 target item과 negative samples를 합친게 될 것이다.

사용자가 item이 진짜 싫어서 클릭하지 않았는지, 단순히 item이 존재하는 지를 모르기 때문에 클릭하지 않았는지 알 수 없다. 그래서 사용자들에게 많이 노출이 될 수 있으면서도 클릭 되지 않은 item, 즉 클릭 되지 않은 popular items를 negative samples로 사용한다.

ⅳ. Ranking Loss

추천 시스템의 핵심은 items의 상대적인 순위도이다. 추천 task를 classification task로 생각할 수 있지만, rank로 접근하는 것이 다른 방법보다 일반적으로 성능이 더 좋다. Ranking은 point-wise, pair-wise, 또는 list-wise가 될 수 있다.

  • Point-wise
    Items의 선호도를 독립적으로 생각하고, target item의 선호도가 높도록 만든다. 예로 cross-entropy loss가 있다.
  • Pair-wise
    Items 간의 선호도를 비교해서 target item의 선호도가 하나의 negative sample의 선호도 보다 더 높도록 만든다. 예로 BPR loss와 논문에서 제안하는 TOP1 loss가 있다.
  • List-wise
    모든 item에 선호도를 부여하고 정렬을 해야 한 것을 활용한다. 하지만 computational complexity가 높아서 자주 사용하지 않는다. 그리고 target item이 하나라면 pair-wise 방식으로 해결할 수 있다.

저자들은 실험적으로 pair-wise를 사용하는 것이 성능이 더 좋다는 것을 발견했다. BPR은 다른 post를 참고하자.

TOP1 loss는 저자들이 session-based task를 위해 만든 것이다. TOP1 loss는 target item의 상대적 선호도에 대한 정규화된 loss를 의미한다. 추천 시스템에서 특정 positive items는 negative samples로 사용되어 negative samples의 선호도 값이 높게 나올 수 있다. 그렇게 되면 학습이 불안정 해진다. 이를 방지하기 위해 저자들은 negative items의 선호도 값이 0에 가까워지도록 regularization term을 loss에 추가하였다.

잘 이해가 되지 않는다. 어쨌든 item id와 각 seesion의 과거 기록을 통해 output이 만들어진다. 그렇게 되면 model이 자연스럽게 특정 session에서는 선호도를 낮게 만들도록 output이 나오지 않을까? 뭐 아무튼 그렇다고 한다.

\[L_s = \frac{1}{N_s} \cdot \sum_{j=1}^{N_s}\sigma(\hat{r}_{s,j}-\hat{r}_{s,i}) + \sigma(\hat{r}^2_{s,j})\]

Ⅳ. Experiments

RecSys Challenge 2015의 click dataset을 사용한 것을 post에 정리하겠다. Youtube-like OTT dataset도 있는데 이것은 논문을 참고하자.

Data pre-processing은 아래와 같이 진행한다.

  1. Session 길이가 1인 것을 없앤다.
  2. Interaction이 5개 이하인 items를 없앤다.
    • 이 부분은 논문에 없는 것으로 repo를 참고해서 논문과 같은 수치를 만들었다.
  3. 다시 session 길이가 1인 것을 없앤다.
  4. Dataset 수집 기간 중 최근 1달을 test dataset으로 활용한다.
    • 이때, session id는 각각 train 또는 test dataset에 존재해야 한다.
    • 즉, 같은 id가 train, test dataset에 모두 존재할 수 없다.
    • 만약 최근 1달에 interaction이 하나라도 있으면 test dataset으로 분류한다.
  5. Test datset에서 train dataset에 없는 item을 없앤다.
  6. Test dataset에 session 길이가 1인 것을 없앤다.

그리고 주의할 점은 gradient inplace이다. Hidden state을 0으로 reset할 때 해당 문제가 발생한다. 이때, detach()를 사용해보자.

마지막으로 epoch, optimizer 등의 자세한 setting 값은 논문을 참고하자.

This post is licensed under CC BY 4.0 by the author.