본문 바로가기
Recommender System

Content Based Filtering(CB)-3.코드와 함께 이해하기[MovieLens 데이터]

by David_Skawns_Lee 2023. 3. 4.

지난 포스팅에서 간단한 데이터를 생성해서 작업을 했다면 조금은 데이터 양을 늘려 movielens 100k(10만개 데이터)를 활용해 작업한다.

방법론은 동일하게 진행하도록 한다.

MovieLens 100K 데이터 확보

무비렌즈 그룹에서 제공하는 데이터 중 하나를 다운받는다. 구현에 사용될 데이터셋은 older version이긴 하나, 전처리 등의 방법에 초점을 두는 것이 아니므로 문제가 될 것이 없다.

  • grouplens에 접속한다. https://grouplens.org/datasets/movielens/100k/
  • ml-100k.zip 을 클릭하여 다운받는다.
  • 압축을 풀고 폴더를 DB, 클라우드 또는 구글 드라이브에 올린다. -> 본 구현에서는 google colab으로 간편히 활용해본다.

MovieLens 100K 압축된 폴더 내 데이터 뜯어보기

압축된 폴더 내에는 다양한 데이터들이 들어있다. 유저 데이터, 장르데이터, 영화 정보 데이터 등이 존재하며 영화에 대한 메타데이터를 쓸 수 있는 것은 장르와 연도 정도가 존재한다. 텍스트를 추출해 진행하는 방법 또는 직접 크롤링을 통한 영화에 메타데이터 매칭을 하는 방법이 있지만, 디테일하게 다루지 않고, 사용할 수 있는 메타데이터를 이용해본다.
이를 위해 필요한 몇개 데이터를 확인해본다.

1. u.data

가장 기본이 되는 MovieLens 데이터셋이다. 기본 추천원리를 학습할 때에도 많이 활용되는 데이터셋.
이를 확인해본다.

 

import pandas as pd
pd.read_csv('/content/drive/MyDrive/u.data', sep="\t", names=['userId','movieId','rating','timestamp'])

 

데이터셋의 각 feature는 아래와 같이 볼 수 있고, 기본적인 유저가 영화에 대한 평점을 내린 정보기록임을 알 수 있다.

  • userId: 유저의 식별정보. 개별 유저의 id를 의미함 ex. 196번 유저, 186번 유저
  • movieId: 영화(아이템)의 식별정보. 개별 영화의 id를 의미함 ex. 242번 영화, 302번 영화
  • rating: 유저가 해당 영화를 보고 내린 평점
  • timestamp: 유저가 해당 영화를 보고 평점을 내린 시간 정보

2. u.genre

'장르'라는 것은 기본적으로 영화(아이템)에 대한 정보임을 직감적으로 알 수 있다. 어떤 정보가 있는지 한번 확인을 해본다.

pd.read_csv('/content/drive/MyDrive/ml-100k/u.genre', sep='|', header=None, names =['genre','g_id']).head()

19가지 장르를 갖고있기 때문에 이에 대한 내용은 .head()를 통해 어떻게 구성돼있는지만 보았다.
각 장르(genre)가 존재하고, 해당 장르들은 장르에 대한 식별번호(g_id)를 가진 것을 볼 수 있다.

3. u.item

영화(아이템)의 메타정보임을 알 수 있을 것으로 보인다. 해당 내용을 뜯어보고 이를 이야기 해보도록 하자.

# 미리 파악해서 각 컬럼 명은 임의로 설정해주었음 
pd.read_csv('/content/drive/MyDrive/ml-100k/u.item', sep ="|", encoding = 'latin-1', header = None, names = ['moviename','launching','no','image','0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18']).head()

위 데이터를 불러오는 코드에서 'names'인자에 대한 내용이 컬럼 명을 임의로 설정한 부분이다.
해당 코드의 출력 결과는 아래와 같이 나온다.

 

위 이미지와 같이 영화에 대한 정보가 아주 디테일하게는 없지만, 영화의 해당하는 장르, 개봉 연도 등을 파악할 수 있다.
사실 이런 정보만으로는 CB모델로 추천하기에 '장르만 비슷한 영화를 추천'하기 때문에 추천 자체의 성능이 좋지 않을 수 있지만, 예시정도로 생각해본다.

  • moviename: 영화 제목 및 개봉 연도
  • launching: 영화 개봉 일자
  • no: 공백(데이터 불러오기 상에서의 문제로 무시해도됨)
  • link: 해당 영화의 링크정보
  • 0~18: 해당 영화의 장르 해당정보

MovieLens 데이터 '장르'를 이용해 CB 모델 구현해보기

1. 장르(feature)를 활용한 벡터화

# 장르들만 활용하기 위해 기타 데이터는모두 삭제 
# 각 index가 각 영화를 대표하는 id가 되며, 0~18까지는 각 영화의 벡터로 생각하여 유사도를 구한다.
item_vectors_with_name = item.drop(columns = ['launching','no','link'])
item_vectors_with_name

필요한 feature를 one-hot vector 혹은 기타 임베딩 방식을 사용하여 의미를 가진 벡터로 맵핑을 해야 하는데, 해당 데이터셋에서는 이미 각 장르에 대해 영화가 해당하면 1, 아니면 0으로 표시가 되어있기 때문에 손쉽게 사용가능하다.
위와 같이 각 영화 별로 벡터처럼 활용할 수 있음을 볼 수 있다.

2. 각 벡터들을 가진 아이템 간의 유사도 확인

from sklearn.metrics.pairwise import cosine_similarity

# 각 영화의 유사도를 구하기 위해 영화제목을 삭제하고, 해당 데이터프레임간의 유사도를 구한다. 
item_vectors = item_vectors_with_name.drop(columns = 'moviename')
similarity_df = pd.DataFrame(cosine_similarity(item_vectors, item_vectors))

# 아이템이 1부터 시작하므로 index 및 columns 다시 재설정
similarity_df.index = similarity_df.index+1
similarity_df.columns = similarity_df.columns+1
similarity_df

 

 

전체 데이터프레임의 유사도를 구하기 위해 영화이름을 제거하고, 한 row에 장르 one-hot encoding 데이터만 남도록하여 유사도를 구했다.
그 결과로 다양한 스코어를 갖게 되며, 장르에 따른 CB모델을 활용할 수 있게된다.

 

3. (장르 only)유사도를 활용한 CONTENT-BASED 모델 추천로직 구현

import numpy as np
# 토이스토리 (1번영화)와 유사한 장르의 영화 10개 뽑아 lst에 넣기
lst = np.argsort(similarity_df[1])[::-1][1:11]

# 해당 lst영화들과 1번영화와의 장르 유사도를 확인
similarity_df[1].iloc[lst]

 

위와 같이 numpy 라이브러리 argsort를 통해 유사도가 높은 순으로 뽑아내어 장르가 아예 동일하게 겹쳐서 유사도가 1이 나오는 422번 영화와 함께 내림차순으로 유사도가 높은 영화를 10개 추출했다. 장르만 이용했으므로, 1이라는 유사도가 나왔을 뿐이지, 더 디테일한 정보를 많이 넣게되면 더욱 디테일하게 비슷한 상품을 추리게 된다.

 

4. CB 모델의의 실효성 확인

CB를 진행해서 추천을 해보면 기본적으로 '유사한 특성을 가진 아이템'을 추천해주는 방식이기 때문에 평가지표로 평가하기 어려운 단점이 있다.
그러므로 실제 추천 로직을 구현해 비슷한 상품이 추천되었는지 확인 해볼 수 있다.

item.iloc[lst]['moviename']

[output]
422     Aladdin and the King of Thieves (1996)
95                              Aladdin (1992)
1219                     Goofy Movie, A (1995)
243                       Jungle2Jungle (1997)
261                             Air Bud (1997)
259                George of the Jungle (1997)
63                    Santa Clause, The (1994)
1032                  Little Big League (1994)
377                        Heavyweights (1994)
383                    Flintstones, The (1994)

크게 비슷한 영화가 나온지는 알 수 없지만, 겹치는 장르가 많은 순으로 나왔다.
실제 장르가 겹치는지는 위에서 만들어놓은 item 테이블에서 불러와 비교해볼 수 있지만, 현 데이터셋에선 크게 중요치 않으므로 넘어가도록 한다.

5. CB의 실무활용

CB의 원리에 대해 포스팅을 하면서 언급했지만, CB는 그 자체만으로 전체 추천을 진행할 수 없다. 비슷한 상품만 추천해주기 때문이다. 그러므로 적재적소에 맞춰, 유저가 상품을 클릭한 순간 이탈을 방지하기 위해서, 또는 이탈했던 고객이 다시 흥미를 갖도록 하기 위해서 사용할 수 있다. 따라서 CB모델은 특정 Task에 맞춰 사용하고 다른 모델들과 함께 사용하는 것이 바람직하다.(모든 것을 CB로만 구현하면 같은 것만 나온다는 의미이다)

 

 

CB 모델에 대해 구현해봤고, 이후엔 다른 데이터셋에서 다른 모델과 하이브리드로 구현해보도록 한다.

댓글