cs Pandas Library만을 이용하여 간단한 Content Based Filtering 구현하기
본문 바로가기
  • 매일 한걸음씩
  • 매일 한걸음씩
개발/Recommender System

Pandas Library만을 이용하여 간단한 Content Based Filtering 구현하기

by 시몬쯔 2020. 4. 27.
728x90
반응형

Content Based Filtering이란 말그대로 콘텐츠를 기반으로 필터링해서 추천해주는 알고리즘이다.

두 콘텐츠의 유사도는 콘텐츠의 특징에 기반하는데 예를 들면 영화의 경우에는 장르, 출연배우, 감독등이 있다.

 

오늘 구현에서 사용할 Dataset은 MovieLens dataset이다.

"ml-latest-small.zip" 을 다운받고 압축을 풀면 links.csv, movies.csv, ratings.csv, tags.csv 파일이 있는데

우리는 여기서 movies.csv와 ratings.csv파일을 사용할 것이다.

 

Data Visualization and Preprocessing

 

먼저 numpy 와 pandas를 가져오자.

그리고 다운받은 MovieLens dataset에서 ratings.csv를 읽어온다.

ratings_data를 확인해보면 movie Id가 번호로 써있고 titile은 안써있는 걸 확인할 수 있다.

이를 위해 movies.csv를 확인해보면 movie Id와 titile 모두 나와있는 것을 알 수 있다.

ratings.csv와 movies.csv 두 데이터를 모두 이용하기 위해 pandas의 merge를 사용한다.

movie_data = pd.merge(rating_data, movies_name, on='movieId')

여기서 parameter on은 movieId에 맞춰 join on 한다는 뜻이다.

 

확인해보면 userId, movieId, rating, timestamp, title, genres까지 모두 잘 들어간 dataframe을 확인할 수 있다.

각 영화의 점수를 확인해보기 위해 

movie_data.groupby('title')['rating'].mean().head()를 실행한다.

'title'로 그룹짓고 나온 결과를 mean()을 이용하여 평균내서 head() 윗부분만 보여준다.

 

결과를 보면 영화 '71 (2014)'는 평균 4.0을 받은 것을 알 수 있다.

 

평점을 기준으로 내림차순으로 정렬해보면 영화가 위와 같이 정렬된다.

그런데 여기서 문제가 있다.

예를 들어, 인기없는 영화 즉 1명만 시청하고 그 1명이 5.0점을 준 영화가 높은 순위를 차지하는 것은

불공평하기 때문이다.

또 상식적으로 좋은 영화는 대체적으로 잘 알려졌고 많은 사람들에게 평가받았을 확률이 높으므로

평가수가 적은 영화는 안좋은 영화일 확률이 높다.

 

이를 위해 우선 평가자들 수를 알아보자.

 

count()를 이용해 평가자들의 수를 새서 내림차순으로 정렬해보면 위와 같이 나온다.

Forrest Gump가 가장 사람들이 많이 본 영화다.

 

이를 통해 우리는 평가자 수와 평가 점수 두 개 다 추천을 하는데에 중요한 지표임을 알 수 있다.

 

시각화를 통해 좀 더 알아보자.

 

평균점수와 평가자 수를 가진 dataframe인 rating_mean_count를 만들자.

matplotlib와 통계 시각화 라이브러리인 seaborn을 사용하여 시각화 해보자.

 

먼저 평가자들 수를 히스토그램으로 그려보자. x축은 평가자수 y축은 영화 수

확인해보니 대부분의 영화들이 50개 이하의 평가를 받은 것을 알 수 있다.

 

다음은 평가 평균 점수를 히스토그램으로 그려보자.

 

x축은 평가 평균 점수 y축은 영화의 수

대략적으로 정규분포를 따르는 것을 알 수 있다.

 

앞서 좋은 영화는 많은 평가를 받았을 것이고 평가 점수가 좋았을 것임을 예상했는데 

시각화를 통해 확인해보자.

 

위에서 만든 평가자수-영화수 그래프와 평균평점 - 영화 수를 joinplot을 이용하여 그려보았다.

이 그래프를 통해 rating 즉 평균평점이 높을수록 많은 평가 수를 가진 것을 알 수 있다.

 

 

Finding Similarities Between Movies

이제 두 영화의 유사도를 찾아보자.

이를 위해 각 열은 영화 제목이고 각 행은 평가 점수인 행렬을 만들어보자.

(이 행렬은 null값이 많을 것이다. 모든 영화가 모든 사용자에 의해 평가된 것이 아니므로)

이를 위해 pd.pivot_table를 사용한다. 참고

 

여기서 index는 'userId', columns은 'title' 즉 영화제목 그리고 값들은 평가 점수로 한다.

 

 

이제 가장 많은 평가를 받은 영화 포레스트 검프와 유사한 영화를 찾아보자.

 

 

위에서 만든 행렬 user_movie_rating에서 'Forrest Gump (1994)'의 열을 가져와 Forrest_gump_ratings에 저장한다.

head()를 통해 확인해보면 각 userId에 따른 평가 점수를 가지고 있다.

 

이제 다른 영화와의 correlation을 확인한다.

corrwith를 사용하는데 print해보니 각 영화들과의 covariance를 측정하는 함수이다.

 

공분산을 이용한 피어슨 상관계수를 계산하는 방법이다.

 

내림차순으로 정리해보면 상관계수가 높은 값들이 위에 나온다.

 

위에서 계산한 correlation 값으로 dataframe을 만든다.

 

여기서 dropna는 NaN값이 있는 행이나 열을 제거하는 함수로, axis = 0이면 행, axis = 1이면 열을 제거하는 것을 뜻한다. (default는 0) inplace는 원래 dataframe에 저장하느냐에 따른 parameter이다.

 

예시)

inplace = True로 해서 실행 시 원래 df도 바뀐다.

 

 

 

inplace = False(default)로 했을 때 원래 df2는 바뀌지 않는다.

 

 

다시 돌아와서...

 

아까 correlation을 계산해 만든 corr_forrest_gump를 'correlation'을 기준으로 내림차순으로 정리해보면 위와 같이 나온다.

 

join을 이용하여 rating_counts즉 평가 수 까지 붙여보자!

앞에서 말했듯이 평가수가 너무 적은 것은 인기없는 영화일 확률이 높으니 평가수가 50개를 넘는 영화만 추려보자.

 

당연히 correlation이 1이고 평가수가 가장 많은 Forrest Gump 자기 자신이 가장 위에 나오고 밑에는 correlation이 높은 순대로 유명한 영화들이 추천되는 것을 알 수 있다.

 

이제까지 추천 시스템의 알고리즘 중 하나인 Content based Filtering의 가장 간단한 알고리즘을 구현해 보았다.

영화 추천은 단순히 평가 수와 평점이 아닌 장르, 태그와 같은 정보 또한 이용하기에 위에서 구현한 알고리즘은 

성능이 좋지 않은 기초 알고리즘이라 볼 수 있다.

 

앞으로 일주일에 2개 포스팅을 목표로 추천 시스템 알고리즘 구현을 해보고자 한다.

 

 

 

피드백은 언제나 환영입니다 :)

 

 

참고 : https://stackabuse.com/creating-a-simple-recommender-system-in-python-using-pandas/

728x90
반응형

댓글