우아콘 2024가 종료되었다.
10월 경, 참여 신청이 올라왔을 때 신청할까 하다가
모든 세션이 유튭으로도 올라온다고하여 이 날만을 기다렸고
드디어 모든 영상이 떴다지..!
10월 30일에 진행되었고,
영상을 보기까지의 약 두달동안
부트캠프 최종프로젝트에 몰입하고 있었다.
오히려..
부트캠프 최종프로젝트를 모두 마무리하고
보길 잘한 듯 싶은게
AI/LM 파트 영상을 보는데
'어? 저거 저렇게도 적용할 수 있구나', '저런 방식으로 적용해야하는구나' 라는 생각도 들었고
동시에
'와..현업에서 이런저런 시도 다 해볼 수 있어서 넘 부럽다'
란 생각도 들었다.
결론은,
부트캠프를 거치면서 AI/LM에 대한 이해도를 올린 덕분에
이 영상도 이해할 수 있었다는 거...!
우와콘 2024 영상 중에서,
AI와 관련된 영상이 몇 개 있는데
그 중
제일 인상깊은 내용들이면서 동시에 지금 하고 있는 사이드 프로젝트에 적용해볼 만한 소스들이 있는 영상들을
모아봤다.
그 중 첫번째!
'추천 모델 성장 일지'
참고로 우와콘은 배달의민족을 서비스하는 '우아한형제들'에서 진행하는 것이기 때문에
영상 내 도메인은 '배달의민족(음식배달)'에 맞춰져있다.
추천 모델 성장 일지는
이승원 데이터 과학자님께서 발표를 해주셨는데,
발표도, 장표도 말하고자 하는 바가 깔끔히 전달되어서 좋았다.
아래는 원본 영상이다.
WOOWACON 2024 취향 저격 맛집 추천, 더 똑똑하게!: 추천 모델 성장 일지
우아콘 2024 발표 중, 몇개는
우아한 기술블로그에도 올라와있는데
요 영상은..아쉽게도 없다.
배민의 개인화추천 모델의 발전사에 대해 알려주면서 동시에
발생한 문제점과 어떻게 해결해왔는지, 또 앞으로의 과제는 무엇인지를 소개한다.
맛집 추천에 대한 개인화 추천 모델은 아래 이미지처럼 '단순 통계 기반 -> 개인화 적용하여 일단위 -> 시간 단위 -> 실시간(초단위)'로 발전해왔다고 한다.
여기서
최근 '제주맛집추천'이라는 주제로 공모전에 참여했던 부분이 떠올랐다.
고객별 정보는 없고, 맛집 정보만 있는 상태였기 때문에 개인화 추천을 할 수는 없었지만
고객 정보가 있었다면
아래와 같은 방법으로 모델을 더 발전시켜 볼 수 도 있었겠다란 생각이 들었다.
Part1. 개인화 추천 모델 적용(일 단위)
배민의 개인화추천 모델 구조는 Two-tower로 되어 있는데
그에 대한 이유는 아래와 같다.
이 중 가장 핵심적인 부분이 '도메인 특성'을 고려한 4. Ranker로 사용 가능 요소도 크게 작용한 것으로 보였다.
*Two-tower 모델은 추천 모델에서 사용하는 전통적인 Bi-encoder 구조의 Retrieval 모델이다.
- 구조적 특징: Two-Tower는 두 개의 신경망(타워)으로 구성됨
a) User Tower: 사용자 데이터를 인코딩
b) Item Tower: 추천할 아이템 데이터를 인코딩
각각의 타워는 임베딩 벡터를 생성하며, 이 두 벡터의 내적(dot product)이나 코사인 유사도를 통해 사용자와 아이템의 매칭 점수를 계산한다.
- 학습 방식:
a) Representation Learning: 사용자와 아이템을 고차원 임베딩 공간에서 표현
b) Contrastive Learning: 사용자와 실제 선택한 아이템의 매칭 점수를 극대화하고, 나머지 아이템과의 점수는 최소화
User Tower는 User ID와 위치, 요일 피쳐로 구성되는데,
각각의 키값을 사용해서 찾은 임베딩 값이 User Tower의 Input으로 들어가게 된다.
여기서 '위치'와 '요일'이라는 피쳐에 대해 알아보자.
먼저
'요일' 피쳐는 User ID와 위치값이 모두 동일하다고 가정했을 때,
요일이 다르면 임베딩 값은 모두 달라진다.
그래서 학습과 추론은 이 부분을 고려하여 다르게 적용해야 한다.
학습데이터(주문)는 이미 발생한 주문정보의 요일을 선택하여 학습을 진행하면 된다.
반면, 추론을 할 때에는 사용자들에게 추천 결과가 제공될 날짜를 기준으로 요일 피쳐를 픽스 한 상태에서
모든 유저에 대한 임베딩을 만들어내는 구조이다.
'위치' 피쳐는
일반적으로 사용되는 위경도를 사용하지 않고 S2Cell을 사용했는데, (*가장 큰 격자 기준 약 가로 세로 500m)
이는 위경도는 범주화가 까다롭지만 S2Cell을 이용하면 수월히 할 수 있어 Embedding Lookup Table로 사용할 수 있기 때문이다.
범주화를 했기 때문에 '위치'라는 별도의 피쳐를 분리하여 구성할 수 있다.
*S2 Cell은 Google에서 개발한 S2 Geometry Library의 핵심 개념 중 하나로,
지구 표면을 위도와 경도로 표현하는 대신, 구형 표면을 격자 구조로 나누어 고정된 셀(Cell) 구조로 표현하는 방식이다.
모델별 크기도 감소되는데,
User ID와 위치를 동시에 고려하여 유니크한 값을 뽑는다면 2500만개가 나오지만,
위치 피쳐를 분리하여 각각의 유니크한 값을 뽑으면 1700만+6만개로 확 줄게 된다.
이로 인해 모델이 가지고 있어야 하는 Embedding Lookup Table의 각 크기가 줄어 결국에는 모델 크기가 감소되는 효과를 가질 수 있다.
추론 과정에서도 배치화가 가능한데, 아래 우측 이미지의 핑크색 영역을 보면
서로 다른 위경도가 하나의 Cell 안에 있기 때문에 모두 동일한 위치로 가정하고 단일 Matrix로 추천 결과를 동시에 생성할 수 있다.
이로 인해 추론 시간도 크게 감소시있다.
개인화 추천은 '배치 추론'을 사용한다.
학습된 모델을 통해서 모든 추천 결과를 미리 만들어서 DB에 넣어놓고
추천 API를 통해 유저에 대한 추천 요청이 들어오면
그 사용자에 대한 추천 결과를 조회한 후에 조회된 결과값을 반환하는 구조이다.
배치 추론을 선택한 이유는,
서빙 ROI와 성능을 고려한 결과이며
'모델 학습 -> 추천 결과 생성 -> 서빙을 위한 데이터를 적재하는 과정'을 일배치로 처리되도록 하였다.
일배치가 필요한 이유로는
주문 데이터의 특성을 고려하여 최신화된 정보가 필요하였기 때문이고,
새로운 유저 또는 가게도 추천에 반영되도록 하기 위함이다.
모델의 학습 전략은
Warmstart Training을 이용했는데
모델이 일정 성능까지 도달하는데 걸리는 학습 시간을 굉장히 단축할 수 있기 때문에
어제 학습이 완료된 파라미터를 가져와서
오늘 학습할 모델의 초기화에 그 파라미터를 이용하도록 했다.
이러한
개인화 추천 모델을 적용하여
주문 전환율을 약 70% 향상 시켰다.
이게 최선일까?
이후
'시간'에 따른 취향도 반영하기 위해
추천 모델을 고도화 시켰다.
Part2. 개인화 추천 모델 개선(시간 단위)
아래 우측 차트를 보면
카페와 족발 키워드의 주문 분포가 어떻게 되어 있는지 알 수 있다.
카페는 점심시간 이후로 꾸준히 발생하고 있지만, 족발은 저녁 시간에만 집중되어 있기 때문이다.
이를 통해 '시간'이라는 피쳐가
얼마나 중요한 역할을 하는지 알 수 있다.
이러한 '시간' 피쳐를
User Tower에 '시간'이라는 피쳐를 하나 더 추가하여 24개의 Embedding Lookup Table로 만들어
간단하게 구현했다.
아래 우측 이미지에서
'시간' 피쳐가 잘 동작하는지 확인하기 위해 오프라인 테스트 결과를 볼 수 있는데 '12시'로 고정한 시간 피쳐 그래프의 성능이
기존의 '시간' 피쳐가 없던 파란색 그래프에 비해
고정한 12시에 맞춰 성능이 확 좋아진 것을 확인할 수 있다.
그런데 문제점 발생!!
'추론' 시점에는
추론 결과가 제공될 시간으로 시간을 고정해야 하는데
매 시간마다 서로 다른 추천 결과를 생성하기 위해선
24개 시간마다 추론이 필요하게 된다.
이런 문제점을 해결하기 위해
'유사한 시간대'를 병합하는 방법을 고안하게 된다.
시간대별로 카테고리를 모두 벡터화한다음
클러스터링을 진행했을 때, 총 6개 클러스터에서 성능이 가장 좋을 것이라는 걸 확인했다.
그런데 6개의 클러스터링을 다 사용해야 할까?
하는 의문에 확인해보니
1번과 2번 시간대(새벽)에서는 주문이 거의 발생하지 않았고,
이 시간대는 추천을 제공해봐야 효율이 높지 않을 거란 판단하에 두 시간대를 합치게 된다.
최종적으로 5개의 시간대마다
추천 결과를 제공했고, A/B 테스트를 통해 주문 전환율이 dir 6.8% 증가하는 것을 확인할 수 있었다.
그런데 더
놓치고 있는 것은 없을까?
고민하다가
실시간으로 변화하는 사용자의 현재 관심사를 반영하기 어렵다는 생각이 들었다.
Part3. 개인화 추천 모델 개선(실시간 단위)
예를 들어
매일 제육볶음을 주로 즐겨 주문하던 남자가
가~끔 초밥을 주문했다.
그럼 모델 입장에서는 '제육볶음' 위주의 추천이 진행하게 된다.
그런데 사용자는
앱을 켜서 초밥 가게를 클릭해보거나
'초밥'을 검색하는 행위를 한다면
'초밥' 위주의 추천이 진행되어야 하지 않을까?
어떻게 만들어볼까?
실시간 행동 이력과 가게를 각각 임베딩한 다음
두 임베딩의 유사도를 계산한다.
그리고 이 유사도가 연관도라는 것을 표현할 수 있도록 모델을 구성한다면
임베딩 유사도를 통해 실시간 추천 모델 최적화가 가능할 것이라고 생각했다.
여기서 관건은,
바로 연관도를 잘 계산하는 인코더를 개발하는 것!
문제를 단순화하여
실시간 행동 이력 -> 클릭한 가게 로 한정 짓는다면,
가게인코더 하나로 구현이 가능하다.
그럼 Two-tower 모델의 Shop tower를 사용해보면 어떨까?
여기서 한계점이 발생한다.
1. 가게 임베딩은 지역성 문제가 발생한다.
2. ID 기반이기 때문에 새로운 item이 들어왔을 때, 추론 불가
*Transductive Learning
(전이 학습)은 머신러닝의 학습 패러다임 중 하나로, 학습 데이터와 테스트 데이터 간의 관계를 활용하여 모델을 학습하는 방법입니다.
주어진 테스트 데이터에만 최적화된 결과를 생성하는 데 초점을 둔 학습 방식입니다.
**Cold Start 문제
는 시스템이 초기 상태에서 데이터 부족으로 인해 제대로 작동하지 못하거나, 사용자를 만족시키는 결과를 제공하지 못하는 상황
a) 추천 시스템에서의 Cold Start
- 새로운 사용자: 시스템이 새로 가입한 사용자의 선호도 데이터를 알지 못해 적절한 추천을 할 수 없는 상황
- 새로운 아이템: 신규 아이템(상품, 콘텐츠 등)에 대한 사용자 반응 데이터가 없어서 추천하기 어려운 상황
- 초기 시스템 구축: 시스템 초기에는 사용자나 아이템에 대한 데이터 자체가 부족
b) 머신러닝 모델에서의 Cold Start모델을 처음 학습시킬 때 훈련 데이터가 부족하여 성능이 낮음
- 특정 도메인에 대한 데이터가 없거나, 이전 데이터와 다른 새로운 상황에서 모델이 제대로 작동하지 못함
그래서
새로운 인코더를 설계하기로 했다.
사람이 가게 정보를 습득하는 과정을 모방하여
가게 이름과 가게 메뉴 정보만을 토대로 가게에 대한 임베딩을 뽑아내는 구조로 설계했다.
여러가지 테스트를 해보았을 때,
배달의민족 서비스에 가장 적합한 양질의 임베딩을 만드는 것은
'Bi-Encoder Contrastivie Learning'이었다.
가게 인코더와 검색어 인코더로 구성했고 구성한 이유는 아래와 같다.
*Triple Margin Loss
는 딥러닝 모델의 학습에서 사용하는 손실 함수 중 하나로, 데이터 간의 유사도와 차이점을 학습하기 위해 설계되었다.
이 방법은 Triplet Loss와 관련이 있으며, 앵커(Anchor), 긍정(Negative), 부정(Negative) 샘플 간의 관계를 정의하고, 모델이 이러한 관계를 적절히 학습하도록 돕는다.
Triplet 구성: 세 가지 입력으로 구성된다.
- Anchor (A): 기준이 되는 샘플
- Positive (P): Anchor와 유사한 샘플
- Negative (N): Anchor와 다른 샘플
목표:
- Anchor와 Positive의 거리는 가깝게
- Anchor와 Negative의 거리는 멀게
- 이 때, 일정한 마진(margin)을 유지하도록 손실을 최소화.
이런 학습을 통해
동일한 공간에 Embedding을 생성하는 Content-based 가게 인코더와 검색이 인코더를 얻었다.
이 두 인코더의 학습을 평가하기 위해
평가 task를 만들었고, 99.5%의 정확도를 얻을 수 있었다.
인코더는 준비 완료!
그러나 아직 적용하기엔 고민해야 할 요소들이 있었다.
추천 로직 시, 고려 사항 중
사용자의 행동 이력과 후보가게 추천은 아래와 같은 기준으로 선정했다.
최종 랭킹 선정은 RRF를 이용하는데
계산식에서 람다 파라미터는
가장 최근의 행동 이력에 조금 더 가중치를 부여하는 방식으로 조정하여 사용하고 있다.
*RRF (Reciprocal Rank Fusion)는 정보 검색(IR) 및 추천 시스템 분야에서 여러 순위화 결과를 결합하는 기법으로 사용된다. 여러 검색 시스템이나 모델에서 생성된 결과를 결합하여 더 나은 검색 순위를 얻는 데 효과적입니다.
아래는
실시간 반응형 추천 시스템이 사용자에게 어떻게 전달되는지를 보여주는 구조도이다.
이렇게 실시간 반응형 추천을 적용하여
주문 전환율은 기존 대비 33% 향상되었다.
이렇게 만든 인코더로
좀 더 많은 랭킹 개선에 활용해볼 수 없을까?
Part4. Content-based 인코더를 활용한 랭킹 개선 사례
아래 시나리오들처럼
여러가지 방법으로 랭킹을 개선해 볼 수 있었다.
현재 노력하고 있는 것은 아래와 같다.
위 세션을 보고 정리하면서
이론적으로 배워왔던 걸 현업에서는, 배민에서는 저런 방식으로 사용하여 문제를 해결해나갈 수 있다는 것을 알았다.
이 점이 제일 큰 배움이었다.
더불어서 구조화된 접근법도 배울 수 있었고,
도메인에 대한 이해는 어딜가나 기본이라는 것도..!
그리고 개인적으로
위의 과정들을 진행하면서
문제점과 한계에 직면했을 때,
팀원들과 함께 다양한 대안들을 찾아나가면서 얼마나 짜릿했을지 생각하니
나도 어서 취업하고 싶다는 마음이 샘솟는다..!