전무익 (Ed Jeon)
May 8 · 9 min read

당근마켓 첫화면은 동네 사람들이 사용하는 다양한 물품을 보는 재미가 있어요. 누군가에겐 이제 필요없지만 나에게 유용한 물건들을 발견하게 되고 더불어 저렴하게 득템 할 기회도 종종 있죠. 매일 새로운 글이 올라오는 첫 화면의 스크롤을 내리며 탐색하는 즐거움이 일상이 되어가고 있습니다.

이러한 화면을 저희는 피드(feed)라고 부릅니다. 비슷하게 첫 화면을 탐색하는 피드 관련된 서비스인 페이스북, 인스타그램, 유튜브 등은 이미 개인화된 추천으로 피드 탐색을 더욱 흥미있게 해주고 있습니다.

당근마켓도 사용자 개인의 취향과 관심에 맞는 물건을 발견할 수 있도록 도와주는 개인화 추천 시스템을 도입하면 좋을 것 같았어요! 문제는 저희 팀에 아직 추천 시스템을 만들어 본 사람이 없어서 알아보고 배워야 했었지만, 다행히 의지가 충만했어요🙂

추천 시스템 알아보기

추천 시스템을 찾아보면 대표적으로 협업 필터링(Collaborative filtering), 내용 기반 필터링(Content-based filtering), 하이브리드 등 같은 방법이 있습니다. 그리고 CF를 구현하는 방법 중 행렬 분해(Matrix Factorization)로 구현된 라이브러리도 쉽게 찾을 수 있었습니다.

하지만 이러한 방법과 라이브러리 만으로는 실시간 개인화 추천 시스템을 구축하기에는 다음과 같은 문제로 충분하지 않았습니다.

  • 학습 데이터가 많아지면 메모리 사용량이 급격히 늘어나거나 학습 속도가 느려짐
  • 사용자 정보를 ID의 단일 값이 아닌 다양한 정보를 활용하기 유연하지 않음
  • 실시간으로 빠른 추천 구현에 대한 고려가 부족

그래서 실제 서비스 중인 전체적인 추천 시스템에 대한 이해가 필요했었고, 유튜브에서 딥러닝 추천 시스템에 대한 논문을 공개한 것을 보게 되었습니다. 이 시스템은 다양한 사용자 정보를 활용하고 실시간으로 빠르게 추천할 수 있도록 고려되어 있어 당근마켓 개인화 추천 시스템으로 적합했어요!

또한 핀터레스트에서도 공개한 홈 피드 추천 시스템을 참고하면서 도움이 되었습니다. 공개해준 기업들 감사합니다!

그럼 공개된 논문을 훑어보고 관련 글과 영상들을 참고해보며 구현한 내용을 계속 소개해보겠습니다.

딥러닝 추천 시스템

two-stage

출처: Deep Neural Networks for YouTube Recommendations 논문

유튜브, 핀터레스트의 추천 시스템의 공통된 점은 2단계로 나눠있다는 점입니다. 우선 사용자에게 추천할 후보군을 수백개 뽑는 1단계 후보 모델, 그리고 그 수백개의 후보들이 사용자가 얼마나 관심있을지 점수를 계산하는 2단계 랭킹 모델이 있습니다.

이렇게 2단계로 나눈 이유를 생각해보면 추천할 대상이 많아 사용자가 모든 글에 대한 관심 점수를 계산하기에는 너무 오래 걸리기 때문에 추천할 후보를 대략적으로 빠르게 추린 후 랭킹 점수를 계산하여 다시 정렬하는 것 입니다.

후보 모델

학습 데이터는 유튜브 추천 시스템과 비슷하고 단순하게 초기 모델을 학습 시작했습니다. 단순하게 설명해보면 Input에 대한 Target의 확률을 높이는 방식입니다.

  • Input : 최근 본 글 ID 50개, 지역, 다음 글을 본 시간
  • Target : 다음 본 글 ID

후보 모델은 기존 머신러닝 기법이 잘 조화된 모델인 것 같습니다. 계속해서 후보 모델에 포함된 주요 기법을 소개합니다.

Matrix Factorization

학습 원리는 Matrix Factorization(MF)과 비슷했습니다. MF는 사용자x아이템 행렬이 있을 때 사용자 벡터와 아이템 벡터로 분해하고, 다시 사용자 벡터와 아이템 벡터를 dot product 연산을 하여 나온 값으로 점수를 예측할 수 있습니다.

다양한 사용자 정보를 Neural network으로 학습하여 사용자 벡터를 생성하는 부분만 다르고 결과적으로 사용자 벡터와 컨텐츠 벡터를 dot product 연산되는 원리는 같습니다.

Language Model

출처: https://web.stanford.edu/class/archive/cs/cs224n/cs224n.1184/lectures/lecture8.pdf

문장에서 이전 단어들로 다음 단어를 예측하는 Language model를 볼 수 있었습니다. 사용자가 봤던 글 목록을 문장으로 보고, 이전에 봤던 50개의 글을 기반으로 다음 글을 예측하는 방식이 비슷합니다. 그래서 Language model의 학습 기법처럼 negative sampling과 binary cross entropy loss를 사용해서 학습했습니다.

Nearest neighbor index

빠른 실서비스에 고려된 중요한 부분은 유사 벡터 검색을 예측할 때 사용한 부분입니다. 학습할 때는 negative sampling 으로 연산 부담이 적지만, 예측할 때는 한 사용자 벡터와 전체 글을 모두 연산을 해야하는데 글이 많다면 오래 걸릴 수 밖에 없습니다.

dot product 연산은 가까운, 유사성을 찾기 위한 계산으로 볼 수 있는데, 유사 벡터 검색으로 대체할 수 있습니다. 유사 벡터 검색은 학습을 통해 매우 빠르게 찾을 수 있고 이런 부분은 잘 구현된 라이브러리가 있어서 구현 부담을 덜 수 있습니다. 참고로 저희는 faiss 라이브러리를 만족적으로 잘 사용하고 있어요.

Metric

성능 측정하기 위해 Mean Average Precision(MAP)와 Top 50을 사용했습니다. 두가지 수치 모두, 전체 글 중 target 글을 예측한 순위가 얼마나 높은지 나타내기 위함입니다.

아래 그래프는 3일간의 사용자가 글을 본 로그로 학습하고, 그 다음날 하루의 미래 데이터로 테스트를 해본 결과입니다.

  • 2 epochs
  • 전체 target 글 수 : 315,714
  • MAP : 0.12
  • top 50 : 12%

수치를 해석해보면 학습한 모델로 50개를 추천했을 때 12% 사용자가 클릭을 했을 거라 예상해 볼 수 있을 것 같습니다. 실제 추천 후 클릭률 측정은 아직 준비 중입니다.

랭킹 모델

후보 모델과 다르게 사용자 정보와 글 정보 등을 모두 concat하여 학습합니다. 그리고 최종 결과값은 dot product가 아닌 Neural network layer에서 나와 더 정확하게 선호도를 예측할 수 있고 값의 정도를 나타내는 regression 모델로 볼 수 있습니다.

전체적인 추천 시스템의 복잡도가 높아 단계적으로 프로젝트를 나누었습니다. 현재 후보 모델까지 구현하여 추천 시스템을 서비스에 적용하였고, 다음 단계로 랭킹 모델은 준비 후 추천 시스템을 더욱 향상 시킬 예정입니다.

예측 결과

사용자 별 이해

한 지역에서 사용자를 뽑아 개인별 추천이 어떻게 다른지 보겠습니다.

왼쪽 A : 아기엄마, 오른쪽 B : 인테리어 관심있는 직장인 (이미지 클릭하면 확대해서 볼 수 있어요.)

옥수동의 두 사용자가 다른 글을 봤을 때 각각 최근 본 글을 기반하여 다르게 추천할 수 있는 걸 볼 수 있습니다.

지역 조건 글 이해

당근마켓은 지역 한정으로 사용자가 위치한 주변 동네의 글만 볼 수 있습니다. 학습 데이터를 지역으로 구분해서 학습하지 않은 이유는 지역간 볼 수 있는 범위가 서로 겹치는 부분 많고, 2개의 지역을 번갈아 볼 수 있어서 전체 지역을 함께 학습했습니다. 대신 학습할 때 지역 정보를 주어 조건부 확률을 학습하도록 했습니다.

위에서 뽑은 사용자가 다른 지역으로 변경했을 때 어떻게 추천하는지 보겠습니다.

(이미지 클릭하면 확대해서 볼 수 있어요.)

두 사용자 모두 아직 서초동의 글을 본 적이 없지만, 다른 지역에서도 본 취향을 반영하여 개인화 추천하는걸 알 수 있습니다.

시간 경향 이해

유튜브와 비슷하게 당근마켓의 상품 글도 최신 글의 소비가 매우 높습니다. 기존에 최신 순으로 글을 표시한 이유가 크겠지만, 인기 있는 글은 시간이 지남에 따라 이미 예약중이나 거래완료가 되었기 때문입니다. 따라서 시간이 지날 수록 볼만한 글은 적어집니다.

왼쪽의 그래프는 학습 데이터에서 사용자가 본 글의 등록된 후 지난 시간에 대한 분포를 나타냅니다. 사용자가 얼마나 최신 글을 많이 보는지 나타내고, 사용자가 보는 글의 70%는 7.3시간 이내의 글입니다.

오른쪽의 그래프는 학습한 모델에서 테스트 데이터로 예측했을 때 첫 번째 결과로 나오는 글에 대한 시간 분포를 나타냅니다. 학습 데이터(왼쪽)과 비슷하게 최신 글을 추천하는 경향을 보이고 있습니다.

참고로 분포에서 음수(-)값은 끌올 기능으로 글의 등록 시간이 변경되어 잡음 데이터로 무시하시기 바랍니다. 사용자가 글을 봤을 때 글의 등록 후 지난 시간을 정확히 측정하는 기록은 아직 준비중입니다.

마치며

개인화 추천 시스템을 최대한 단순화시켜서 개발을 해봤습니다. 현재 baseline 모델로도 개인화 추천 가능성을 확인하고, 빠르고 점진적으로 나아가기 위해 간단히 서비스에 적용 후 A/B 테스트 그리고 개선을 반복해 나가고 있습니다.

앞으로 사용자 정보를 추가해보는 실험, 랭킹 모델 추가 등 계속 성능을 개선해나갈 예정입니다.

다음으로 추천 시스템을 지속적으로 업데이트하는 파이프라인과 서빙 시스템을 구축한 내용을 소개해보려고 합니다~!!

당근마켓 팀블로그

당근마켓은 동네 이웃 간의 연결을 도와 따뜻하고 활발한 교류가 있는 지역 사회를 꿈꾸고 있어요.

전무익 (Ed Jeon)

Written by

Software Engineer at Daangn

당근마켓 팀블로그

당근마켓은 동네 이웃 간의 연결을 도와 따뜻하고 활발한 교류가 있는 지역 사회를 꿈꾸고 있어요.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade