비슷한 음식점 취향 유저 추천 모델 개발기

yunsang ju
네이버 플레이스 개발 블로그
18 min readAug 5, 2021

--

안녕하세요 AI를 이용해 서비스 품질을 올리기 위해 2021년 2월 AI개발조직이 신설되었습니다

오늘은 서비스 품질을 올리기 위해 나와 비슷한 취향의 음식점을 방문하는 유저 추천 모델 개발 내용에 대해 말씀드리겠습니다

Glace CIC에서는 네이버 예약과 마이플레이스 서비스를 운영하고 있습니다아래 그림은 네이버 플레이스에서 서비스하는 네이버 예약, 마이플레이스 페이지입니다

유저들은 네이버 플레이스에서 예약/영수증 체크인 등 방문한 플레이스에 평점과 리뷰를 남길 수 있고, 방문하지 않아도 가고싶거나 관심있는 플레이스에 좋아요를 누를 수 있습니다

이러한 유저들의 행태를 분석하여 나와 비슷한 취향의 음식점을 방문하는 유저들을 추천하고 싶은 요구사항이 있었고, 이 문제를 풀기위해 진행했던 모델링에 관한 설명을 드리겠습니다

가설

사용자 별로 방문한 플레이스 이력에서 취향인 플레이스를 필터링 하면 사용자별 취향 플레이스 이력을 구할 수 있습니다

이러한 사용자 별 취향 플레이스 이력을 모델이 잘 이해 할 수 있다면 이런 모델의 output vector는 사용자를 대표할 수 있는 user의 embedding으로 볼 수 있습니다

유저 별 취향 플레이스 이력 context를 잘 이해할 수 있는(취향 플레이스 이력이 주어지면 다음에 방문할 취향 플레이스를 잘 예측할 수 있는) 모델을 개발하기로 결정했습니다

이 문제는 Language Model을 푸는 문제와 유사합니다, 아래 그림은 Language Model과 취향 플레이스 이력을 Language Model에 대입한 그림입니다

이런 모델로 유저별 대표 embedding을 추출하면 vector 공간에서 거리가 가까운 embedding은 비슷한 유저로 볼 수 있습니다

이러한 가설을 세웠고 가설 기반으로 모델링을 진행한 내용에 대해 설명드리겠습니다

feature engineering

세운 가설에 따라 유저의 방문 플레이스 중 취향의 척도를 찾아야 했습니다

네이버 플레이스에 있는 데이터 중 취향의 척도로 사용할 수 있는 데이터는 아래와 같습니다

explicit feedback과 implicit feedback을 모두 사용하려 했으나 내부 data pipeline 구축 이슈가 있어 explicit feedback만 사용하였습니다

평점에서 취향의 척도 찾기

좋아요의 경우 취향의 확실한 척도가 되지만 평점의 경우는 데이터를 확인할 필요가 있었습니다

유저는 예약/영수증 체크인 시 0 ~ 5점 사이로 방문 플레이스에 평점을 줄 수 있으며 이러한 평점의 분포는 유저별로 다릅니다(평점에 후한 유저가 있는 반면 그렇지 않은 유저들도 있다)

아래 표는 평균평점 histogram인데 한국 유저들은 평점에 후한 경향이 있습니다

모든 유저를 동일한 기준 이상의 평점 플레이스를 취향 플레이스로 판단하는건 위험하므로 유저별 평균 평점 이상의 평점을 준 플레이스를 취향 방문 플레이스로 정의하였습니다

아래 표는 긍정(평균평점 초과), 중립(평균평점), 부정(평균평점 미만)의 평점 분포입니다 평균 평점 이상의 플레이스 방문이력을 학습데이터에 사용했습니다

유저 별 학습 최대 취향 플레이스 수

학습에 사용하는 유저 별 최대 취향 플레이스 수가 커지면 그보다 방문수가 작은 유저는 아래와 같이 zero padding으로 학습셋을 만들고 학습해야합니다

유저 별 최대 취향 플레이스 수를 늘리면 많은 수의 플레이스 이력을 모델이 볼 수 있지만, 플레이스 방문 이력이 적은 유저들은 zero padding이 많이 들어가고 GPU 메모리 비효율적이며 학습 속도, 학습 성능에 영향이 갑니다 적절한 max length는 중요합니다

또한 max length가 너무 클 경우 일부 헤비유저에 편향된 결과가 나올 수 있으며 추천모델 품질 하락에 원인이 됩니다

max length별 실험도 진행하였으며 문서 마지막에 설명드리겠습니다

학습데이터

  • 유저 별 선호 플레이스 방문 이력
  • 플레이스 dongcode (플레이스기반 추천 특성상 지역성이 중요하므로 이 feature를 추가했습니다)
  • 플레이스 category (한식/양식/중식 등의 플레이스의 카테고리 정보)

학습 데이터 사이즈

2021–05–28 기준

  • 학습 유저 수 : 696197
  • 학습 플레이스 수 : 802088

Modeling

유저 별 embedding을 잘 추출할 수 있는 모델들을 찾기 위해 여러 논문들을 리서치 하였으며 최종적으로 YouTube 2016 candidate layer 모델과 BERT 를 추천 모델 후보군으로 선정했습니다

YouTube 2016 Candidate Model

2010년 부터 2019년 까지의 YouTube 추천 논문을 리서치 하였고, 가설과 가장 적합한 모델은 2016년 candidate layer 모델이라 판단하여 네이버 플레이스 데이터로 실험을 진행했습니다

2016 YouTube Candidate Layer Architecture
2016 YouTube Candidate Layer Architecture

위 모델은 user의 다양한 feature(비디오 시청 이력, 검색 질의어, 연령, 성별..)들을 input으로 넣은 뒤 Feed Forward Network를 거친 후 user, video vector로 factorize하는 모델입니다

네이버 플레이스 feature 추가 방법

위에 설명한 학습에 사용한 feature는 취향 place 이력, place dongcode, place second category입니다

place id, place dongcode, place second category 각각의 embedding layer output값을 concat하여 Feed Forward Network의 input으로 넣었습니다

user embedding 추출 방법

마지막 layer에서 factorize되서 나온 user embedding을 유저의 대표 embedding으로 사용합니다

참고논문

The YouTube Video Recommendation System — 2010

Deep Neural Networks for YouTube Recommendations — 2016

Recommending What Video to Watch Next: A Multitask Ranking System — 2019

MMOE — 2019년에 유투브 추천 알고리즘에 들어간 주요 개념 논문

Wide & Deep Learning for Recommender Systems — 2019년 유투브 추천 architecture가 모티브를 받은 구조 논문(구글 플레이 스토어 추천 엔진 논문)

BERT 기반 추천 모델

플레이스 방문이력을 잘 이해하는 문제를 Language Model과 유사한 문제로 가설을 세웠으므로 Language Model을 잘 학습하는 것으로 유명한 BERT 모델을 실험했습니다

BERT를 추천 도메인에 적용했던 시도는 이미 있었습니다, BERT4Rec 논문을 보면 MovieLense dataset의 Movie ID 값만 사용하여 BERT 모델로 학습을 진행했을 때 성능이 좋게 나오는걸 확인할 수 있습니다

BERT는 품질 좋은 embedding이 내뱉고 이 기반으로 여러 downstream task에서는 간단한 top만 쌓아 fine-tuning하여 많은 task에서 SOTA를 이룬 모델 구조입니다

BERT를 이용하여 Language Model의 품질 좋은 embedding을 추출 한 것 처럼 네이버 플레이스 취향 이력을 Language Model과 같이 학습하면 품질좋은 유저 embedding을 추출할 수 있다고 가정하였습니다

BERT 학습 방법

BERT에서 제안한 Pretrained Model 학습 방법은 Masked Language Model, Next Sequence Prediction이 있는데 추천의 경우에는 사용자의 취향 플레이스 이력을 나누어 Next Sequence를 정의하기도 애매하고 Next Sequence Prediction는 너무 쉬운 문제라 BERT에서 크게 효과가 없는 학습 방법이라는 의견들이 있어서 제외했습니다

Masked Language Model 이하 MLM

BERT Pretrained model을 학습하는 방법 중 1가지 이며, Cloze Task 방식으로 랜덤하게 token중 일부를 [MASK] token으로 변경한 뒤 [MASK] Token의 원래 값을 맞추면서 학습하는 방식입니다

Cloze Task

아래 그림은 Language Model의 MLM 학습을 표현한 그림이며 문장의 단어 중 일부를 [MASK] token으로 치환 후 모델이 [MASK] token에 위치해야 할 단어를 맞추도록 학습합니다

추천에 적용했을때는 유저 취향 플레이스 이력의 일부 place를 [MASK] token으로 치환 후 모델이 [MASK] token에 위치해야 할 place를 맞추도록 학습합니다

네이버 플레이스 feature 추가 방법

위에 설명한 feature들을 BERT 모델에 input으로 BERT embedding layer처럼 3개의 embedding들을 add하여 input embedding layer를 구성했습니다

추천 모델에서는 아래 BERT에서 사용하던 position embedding은 제거했습니다

position embedding의 유/무 비교 실험에서 정량적 지표는 차이가 없었지만 정성적 검증에서 position embedding이 제거된 결과가 더 좋았습니다

언어의 경우는 각 token의 위치가 매우 중요하지만(문법 등의 이유로) 플레이스 방문 이력의 경우는 먼저 먹고 나중에 먹는다고 유저의 특징이 달라지는 것이 아니므로 이러한 결과가 나왔다고 생각하고 있습니다

user embedding 추출 방법

BERT에 output layer에서 나오는 token(추천에서는 취향 place)별 embedding 값들을 average한 값을 user의 대표 embedding으로 사용했습니다

참고논문

BERT

Attention Is All You Need

BERT4Rec

YouTube vs BERT 추천 모델 비교실험

다음에 올 유저 별 취향 플레이스 이력을 잘 맞추는 모델을 만들기로 가설을 세웠으므로 정량적 지표로는 Top@10 accuracy를 사용했습니다

YouTube의 경우 마지막 place를 예측하는 Top@10 accuracy, BERT의 경우 [MASK] token place를 예측하는 Top@10 accuracy를 사용했습니다

BERT가 정량적 지표에서 Youtube보다 2.45배 성능이 좋습니다

기획자 분들 대상으로 추천결과에 대한 정성적 검증에서도 BERT 추천모델이 품질이 좋다는 결과가 나왔습니다

아래 결과를 보면 YouTube 모델의 경우는 학습 step을 늘려도 overfit이 되며 Val Accuracy는 유지됩니다

YouTube

Train Top@10 Accuracy

  • 94%

Train Loss

Val Top@10 Accuracy

  • 14.5%

BERT

Train Top@10 Accuracy

  • 39.35%

Train Loss

Val Top@10 Accuracy

  • 35.64 %

학습 시간 향상

실시간으로 새로운 사용자가 추가되고, 기존 사용자는 새로운 활동을 하므로 추천의 경우 한번 학습하고 계속 사용하면 품질이 떨어집니다

처음에는 continual learning을 적용하려 했으나, BERT 추천 모델에서는 token id값의 이슈로 적용하기 어려웠습니다

Language Model에서 BERT의 경우 tokenizer의 학습을 시키지 않으면 input token id값이 변경되지 않습니다

추천 BERT의 경우에는 token id에 해당하는 값이 place id인데 place의 경우에는 하루에도 개/폐업이 잦게 발생합니다

이러한 특성으로 continual learning을 적용하기에는 적합하지 않는 구조라 생각하여 진행하지 않기로 결정했습니다

저희는 최소한 하루에 한번 새로운 데이터를 scratch 부터 학습하기로 목표를 세웠습니다

BERT를 scratch부터 학습하는건 큰 비용이 들어가며 학습시간을 줄이기 위해 적용한 방법들을 소개하겠습니다

BERT model size 비교 실험

아래표는 BERT의 size별 정리된 표 입니다

BERT-medium으로만 사이즈를 키우더라도 수렴하는데 24시간이 넘어가서 비교 실험 후보 size는 tiny와 mini, mini_small(FFN의 dim을 hidden의 4배가 아닌 2배로 설정)로 선정했습니다

V100 5장으로 실험한 결과이며, tiny가 시간 대비 성능차이 효과가 크지만 mini_small이 성능이 높고 하루에 한번 학습하기 무리가 없는 시간이라 mini_small로 채택했습니다

tiny size가 학습시간대비 성능이 효과적이라 tiny와 mini_small간의 정성적 검증은 추후에 진행해보려합니다

실험결과

tiny

  • Val@10 Accuracy : 33.39%
  • 학습시간 : 3시간 52분 07초

mini_small

  • Val@10 Accuracy : 35.64%
  • 학습시간 : 6시간 9분 3초

mini

  • Val@10 Accuracy : 36.56%
  • 학습시간 : 7시간 29초

Accelerating Training of Transformer-Based Language Models with Progressive Layer Dropping 적용 실험

Microsoft에서 transformer 기반 모델을 성능저하 없이 모델의 학습시간을 2.8배 향상시키는 방법에 대한 논문이 있어 적용하였습니다

이 논문의 핵심 method는 아래와 같습니다

Pre Layer Normalization

  • Transformer layer의 구조는 Multi-Head Attention, Position-Wise MLP 이후에 Layer Normalization을 진행합니다
  • Layer Normalization의 순서를 바꿔서 Multi-Head Attention, Position-Wise MLP 이전에 진행하면 학습 시 hyperparameter에 robust하고 수렴이 빠르게 된다는 연구들이 있어 해당 논문에서는 Pre Layer Normalization 기법을 적용했습니다

Switchable Transformer

transformer block을 bernoulli distribution으로 학습에 포함/미포함 시키는 방식입니다

Progressive Layer Drop

Switchable 방식은 vision의 Stochastic Depth 방식과 유사하며 vision에서는 성공적이었지만 transformer 계열에서는 적용 시 성능이 떨어지는 이슈가 있었습니다

아래 그래프를 보면 transformer에서 낮은 layer일수록 input과 output embedding이 dissimilarity의 양상을 띄며 layer가 낮을수록 switch on하고 layer가 높을수록 switch off하도록 Layer에 따라 Progressive하게 Switchable Transformer를 적용하여 성능이 떨어지지 않도록 적용했습니다

실험 결과

BERT base vs Progressive Layer Dropping

아래의 Train loss를 보면 같은 loss에 도달하는데 base는 7시간 53분 36초 Progressive Layer Dropping는 4시간 4분 33초가 걸립니다

더 적은 step으로 학습해도 같은 성능을 낼 수 있고 Progressive Layer Dropping 적용 후 1.93배 학습시간 효율화를 하였습니다

Switchable Transformer를 적용했으므로 같은 step을 학습하는데도 Progressive Layer Dropping이 더 빠르게 학습됩니다

Train Top@10 Accuracy

Train Loss

Val Top@10 Accuracy

Automatic Mixed Precision 적용 실험

Mixed Precision 방식은 half-precision으로 forward, backward propagation을 진행 한 후 weight update 전에 single-precision으로 변환하여 update하는 방식입니다

Mixed Precision을 적용하면 GPU 메모리를 효율적으로 사용하여 큰 batch size를 사용할 수 있고 그로인해 학습속도를 향상시킬 수 있습니다

Mixed Precision 적용 후 성능이 저하되더라도 작은 폭으로 저하되고 오히려 성능이 증가하는 케이스들이 있어 실험을 진행했습니다

실험 결과

Mixed Precision을 사용해서 메모리를 적게 쓰므로 mini batch size를 증가시킬 수 있었고 학습속도를 20% 향상했습니다

Mixed Precision

  • batch_size : 21
  • 학습시간 : 6시간 9분 3초

Progressive Layer Drop

  • batch_size : 17
  • 학습시간 : 7시간 20분 57초

Train Accuracy

Train Loss

Val top@10 accuracy

학습 데이터 취향 플레이스 max length별 실험

max length를 80,100,120,150으로 변경하여 실험하였습니다

BERT의 경우 multi-head attention에서 length의 제곱으로 GPU memory를 사용하므로 적절한 length값이 중요합니다

실험 환경

  • batch_size : 14
  • V100 5장

실험 결과

max length 80

  • Val Top@10 Accuracy : 34.68%

max length 100 (최종 결정)

  • Val Top@10 Accuracy : 35.67%

max length 120

  • Val Top@10 Accuracy : 33.63%

max length 150

  • Val Top@10 Accuracy : 33.77%

비슷한 유저 찾는 방법

Indexing

학습이 완료된 후 BERT 추천 모델에서 학습에 사용된 유저들의 embedding을 추출합니다

추출한 전체 유저의 embedding 값을 FAISS를 이용하여 indexing 합니다

FAISS는 10억개의 feature들을 index했을때도 nearest neighbor search에 성능저하가 없는 facebook에서 발표한 라이브러리입니다

Search

추천을 받을 유저의 최근 100개의 취향 place id, place dongcode, place second category 정보를 BERT 추천 모델에 inference 합니다

나온 BERT token embedding들을 average해서 256 dim의 user embedding을 추출합니다

추출된 user embedding으로 만들어놓은 FAISS index에 가장 유사한 유저를 search합니다

추천 모델 적용

현재 마이플레이스 피드탭 팔로잉탭에 추천 모델이 적용되어 있습니다

추천 모델 적용된 영역은 내 주변 popularity 기반의 유저들을 추천해주는 영역이었습니다

추천 모델로 해당영역 변경 후 팔로우 버튼 클릭 유저 85% 증가, 리뷰 이미지 카드 영역 클릭 유저 27% 증가했습니다

Glace CIC AI 조직에서는 위 추천 모델 이외에 아래와 같은 다양한 과제들을 진행하고 있습니다

많은 지원 부탁드립니다~!

--

--