추천 시스템 3 — FunkSVD를 이용한 추천 시스템 구현

김희규
4 min readJan 2, 2022
Photo by Umanoide on Unsplash

이번 글에서는 FunkSVD를 이용해서 추천시스템을 구현해보겠습니다. 사용자가 어떤 영화를 몇 점으로 평가했을지 예측하는 문제에서, 이전 글의 SVD는 유저가 아직 평가하지 않은 NaN값을 처리하지 못했는데요, FunkSVD는 이 문제를 간단하게 해결해줍니다.

FunkSVD의 원리

먼저 Matrix Factorization 을 다시보면, 유저가 영화에 줄 평가는 유저 행렬의 유저 벡터, 아이템 행렬의 아이템 벡터의 내적을 이용해서 계산했습니다.

이 User Matrix와 Item Matrix는 처음에는 임의의 값으로 초기화되고, 확률적 경사하강법(SGD)같은 방법을 이용해서 두 행렬의 곱이 실제 User-Item Matrix와 비슷해지도록 학습됩니다.

유저 2는 영화를 2만 봤고 1과 3은 보지 않았습니다. 그렇다면 유저 벡터과 영화 벡터의 내적을 통해 값을 예측하고 갱신될 때, 사용자가 본 영화만을 갱신한다면 어떨까요? 유저 2가 영화 1, 3을 보지 않았더라도, 다른 유저가 영화 1, 3을 봤기 때문에 이 영화 벡터들의 값은 적절한 값으로 갱신될 것입니다. 유저 벡터 역시 해당 유저가 본 영화들에 맞춰서 적절한 값으로 갱신될 것입니다.

FunkSVD 사용하기

깃허브의 FunkSVD 코드를 이용해서 FunkSVD를 사용해보겠습니다. 전체 코드는 여기입니다. 먼저 pip로 설치해줍니다.

pip install git+https://github.com/gbolmier/funk-svd

학습에 필요한 데이터를 불러오는데, 좀 변형이 필요합니다.

학습에는 rating DataFrame을 그대로 주면 되는데, 칼럼 이름만 u_id(유저 칼럼), i_id(아이템 칼럼)으로 바꿔주면 됩니다.

전체 데이터를 학습에 쓰지 않고 10%씩 validation, test으로 준 다음에 학습과정에서 오버피팅하지 않는지 확인하는데 사용합니다. early_stopping=True 인자로 인해 20에폭만에 조기종료됩니다.

FunkSVD를 이용해서 추천해주기

이제 predict_pair(user_id, item_id)메서드를 이용해서 유저와 영화간의 평가를 예측할 수 있습니다. 그렇다면 train set에는 없던 영화들을 가지고 예측해서 평가가 높은 순으로 TOP 100을 추려본 다음, 유저가 실제로는 봤지만 train에는 포함되지 않았던, validation set, test set에 있던 영화가 TOP 100에 얼마나 포함되어있는지를 확인해보겠습니다.

이 함수를 이용해서 유저들의 top 100 을 실제로 살펴보겠습니다.

TOP 100 Accuracy는 전체 유저 평균은 21.6% 정도로 나옵니다. 영화 100개를 추천해주면 5개 중 1개는 실제로 유저가 평가했고, 대체로 긍정적으로 평가했던 것입니다. 저희가 유튜브를 봐도 추천받은 영상을 모두 보는게 아닌걸 생각해봤을 때, 20%면 꽤나 만족스러운 결과인 것 같습니다. 위 결과를 봐도 유저가 실제로 좋게 평가한 영화들이 상위권에 위치한 걸 알 수 있습니다. (안좋은 것도 상위에 있긴 하지만,, ㅠ)

다음 글에서는 SVD가 아닌 딥러닝을 이용해서 머신러닝 추천시스템을 구현해보겠습니다!

--

--

김희규

나는 최고의 선수다. 나를 최고라고 믿지 않는 사람은 최고가 될 수 없다.