[Recommendation system]Basic Recommendation System 구현 I

4 minute read

ML 기반 추천 엔진: 컨텐츠 기반 추천 엔진 개발

넷플릭스 프라이즈 개요

  • 2006년부터 3년간 운영된 기념비적인 추천 엔진 경진 대회
  • 넷플릭스의 내부에서 쓰던 추천 시스템 품질을 10% 개선하는 팀에게 $1M 수여 약속, RMSE(Root Mean Square Error)가 평가 기준으로 사용됨
  • 이를 기폭제로 캐글과 같은 머신러닝 경진대회 플랫폼이 등장!

넷플릭스 프라이즈 우승팀과 알고리즘

  • 이 대회를 통해 협업 필터링이 한단계 발전!
    • SVD를 활용한 SVD++는 이후 굉장히 많은 분야에서 활용됨
    • 앙상블 방식의 모델들이 가장 좋은 성능을 보임
      • 너무 긴 실행시간 때문에 실제 프로덕션에서는 사용 불가

앙상블(Ensemble)과 랜덤 포레스트(Random Forest)

  • 다수의 분류기를 사용해서 예측하는 방식(여러 모델의 조합)
  • 성능은 좋지만 훈련과 예측 시간이 오래 걸린다는 단점

추천 엔진의 발전 역사

  • 2001년 아마존이 아이템 기반 협업 필터링 논문 발표
  • 2006-2009년 넷플릭스 프라이즈
    • SVD를 이용한 사용자의 아이템 평점 예측 알고리즘 탄생
    • 앙상블 알고리즘이 보편화됨
    • 딥러닝의 일종이라 할 수 있는 RBM(Restricted Boltzman Machine)
  • 2010년 딥러닝이 컨텐츠 기반 음악 추천에 사용되기 시작
  • 2016년 딥러닝을 기반으로 한 추천이 활기를 띄기 시작
    • 오토인코더 기반으로 복잡한 행렬 계산을 단순화 하는 방식
    • 아이템 관련 사용자 정보를 시간순으로 인코드하는 RNN 사용 방식
    • 아마존에서 DSSNTE라는 알고리즘 오픈소스화했다가 SageMaker라는 제품으로 통합
    • 개발 부담을 최소화한 다양한 서비스들이 나오게 됨(클라우드 서비스들)

인기도 기반 추천 엔진 개발

  • Cold Start 이슈가 존재하지 않음. 특정 카테고리에 대해서 인기의 정의에 따라 추천 시스템을 구축하면 되기 때문.
  • 인기도의 기준
    • 평점 / 매출 / 최다 판매
  • 사용자 정보에 따라 확장 가능
    • 서울 지역 인기 아이템 추천
  • 개인화되어 있지는 않음(어느정도는 가능)
    • 같은 20대 사람들에게 인기있는 ~~ -> 개인화 x
  • 아이템의 분류 체계 정보 존재 여부에 따라 쉽게 확장 가능
    • 특정 카테고리에서의 인기 아이템 추천
  • 인기도를 다른 기준으로 바꿔 다양한 추천 유닛 생성 가능
    • top 100 -> newest 등으로 기준을 바꿔 유닛을 생성할 수 있다.

기타 Cold Start 이슈가 없는 추천 유닛

  • 현재 사용자들이 구매한 아이템
  • 현재 사용자들이 보고 있는 아이템(영화, 강좌 등)

유사도 측정: 코사인 유사도와 피어슨 유사도 설명

다양한 유사도 측정 알고리즘

  • 벡터들간의 유사도를 판단하는 방법
  • 코사인 유사도란?
    • N차원 공간에 있는 두 개의 벡터간의 각도(원점에서)를 보고 유사도를 판단하는 기준
  • 대표적인 것은 코사인 유사도와 피어슨 유사도
    • 평점처럼 방향 뿐만 아니라 벡터 크기의 정규화가 중요하면 피어슨 유사도를 사용
      • 피어슨 유사도는 코사인 유사도의 개선 버전
  • 피어슨 유사도란?
    • 먼저 벡터 A와 B의 값들을 보정
      • 각 벡터내 셀들의 평균값을 구한 뒤 평균값을 각 셀에서 빼줌
      • 예를 들어 A = {3, 4, 5} -> 각각 평균값 4를 빼서 보정 -> A = {-1, 0, 1}
    • 그 이후 계산은 코사인 유사도와 동일. 중앙 코사인 유사도 or 보정된 코사인 유사도라 부르기도 함.
  • 피어슨 유사도의 장점
    • 모든 벡터가 원점을 중심으로 이동되고 벡터간의 비교가 더 쉬워짐
      • 평점이란 관점에서는 까다로운 사용자와 아닌 사용자를 정규화하는 효과를 가져옴

TF-IDF 소개

텍스트를 행렬(벡터)로 표현하는 방법

  • 텍스트 문서를 행렬로 표현하는 방법은 여러가지
    • 기본적으로 일단 단어를 행렬의 차원으로 표현해야함
    • Bag of Words 방식은 문서들에 나타나는 단어수가 N개이면 N차원으로 문서 표현
      • 딥러닝의 워드임베딩 사용시 차원수도 축소되고 공간상에서 비슷한 단어들끼리 가깝게 위치
    • 원핫 인코딩 + Bag of Words(카운트)
      • 단어의 수를 카운트해서 표현
    • 원핫 인코딩 + Bag of Words(TF-IDF)
      • 단어의 값을 TF-IDF 알고리즘으로 계산된 값으로 표현
      • 단순한 카운트가 아니라 문서 전체적으로 단어가 중요한지 의미적으로 더 접근

원핫 인코딩 + Bag of Words(카운트)

  • 먼저 stopword 제외 (the, is, in, we, can, see)
  • 그 뒤 단어수 계산 -> 유니크하게 나온 단어가 총 5개 (sky, blue, sun, bright, shining)
  • 단어별로 차원을 배정: sky(1), blue(2), sun(3), bright(4), shining(5)
  • 예를들어 문서 doc1에서 sky, blue가 한번씩 나왔다면 [1, 1, 0, 0, 0]이 된다.

CountVectorizer 소개

  • 앞서 Bag of Words 카운팅 방식을 구현한 모듈
  • 이렇게 벡터로 표현이 되면 문서들간의 유사도 측저이 가능
  • CountVectorizer(analyzer=’word’, stop_words=’english’)
  • 들어오는 텍스트를 word단위로 끊는다(공백이 항상 단어 단위를 의미하지 않는 한국어, 중국어의 경우 좋지 않음)
  • stop_words=’english’하면 영어에서 의미없는 것들, is, the등등을 스탑워드로 자동으로 만들어줌.

TF-IDF 소개

  • 앞서 카운트 방식은 자주 나오는 단어가 높은 가중치를 갖게 됨
  • TF-IDF의 기본적인 아이디어
    • 한 문서에서 중요한 단어를 카운트가 아닌 문서군 전체를 보고 판단하자
    • 어떤 단어가 한 문서에서 자주 나오면 중요하지만 이 단어가 다른 문서들에서는 자주 나오지 않는다면 더 중요
  • 단어 t의 문서 d에서의 점수: TF-IDF = TF(t, d) * IDF(t)
    • TF(t, d): 단어 t가 문서 d에서 몇번 나왔나?
    • DF(t): 단어 t가 전체 문서군에서 몇번 나왔나?
    • IDF(t): 위의 DF(t)의 역비율
      • 단어 t가 전체 문서들중(총 N개) 몇개의 문서에서 나왔는지의 비율을 역으로 계산한 것이 IDF -> 다른 문서에서는 안나올수록 더 중요한 단어
      • ln(N/DF): N은 총 문서수를 나타내고 DF는 단어가 나온 문서를 말한다.

원핫 인코딩 + Bag of Words(TF-IDF)

  • 카운트 기반 Bag of Words랑 동일한데 카운트 대신에 TF-IDF 점수를 사용
  • TF-IDF = TF(t, d) * IDF(t)
    • TF(t, d): 단어 t가 문서 d에서 카운트
    • IDF(t): 역문서 비율. 단어 t가 전체 N개의 문서들 중 몇개의 문서에서 나타났는지의 비율을 역으로 한 값
      • ln(N/DF)
        • N은 총 문서수
        • DF는 단어가 나온 문서의 수

TfidfVectorizer소개

  • TfidfVectorizer(analyzer=’word’, stop_words=’english’, norm=’l2’)
  • analyzer, stop_words는 CountVectorizer와 동일.
  • L2 normalization: 벡터를 단위 벡터로 만든다. 길이가 1인 벡터로 만드는 것.
  • 사이킷런의 TF-IDF 공식은 조금 다름
    • IDF = ln(N+1)/(DF+1)+1
    • 왜 다를까? ln 1은 0, 0으로 나누면 에러.

TF-IDF 문제점

  • 정확하게 동일한 단어가 나와야 유사도 계산이 이뤄짐
    • 동의어 처리가 안됨
  • 단어의 수가 늘어나고 아이템의 수가 늘어나면 계산이 오래걸림
  • 결국은 워드 임베딩을 사용하는 것이 더 좋음
    • 아니면 LSA(Latent Semantic Analysis)와 같은 차원 축소 방식 사용

CountVectorizer/TFIdfVectorizer/코사인 유사도 실습

TF-IDF를 이용한 컨텐츠 기반 추천과 실습