reommender system

[추천 시스템#2] 콘텐츠 기반 추천 시스템(content-based recommender system)

j.d 2023. 4. 27. 09:40

지난 시간에는 추천 시스템의 정의, 종류 등을 살펴보았습니다. 

이번 포스팅은 추천 시스템 종류 중 콘텐츠 기반 추천 시스템(content-based, CB)에 대해서 얘기를 나눠볼려고 합니다.

 

Content-based filtering

content-based filtering이라고도 불리는 CB는 사용자의 구매 이력을 통해 이와 비슷한 카테고리의 제품을 추천하는 방법을 의미합니다. 

CB의 특징은 다음과 같습니다.

  1. 독립적 정보 활용
    • 추천 대상 사용자의 과거 구매이력이나 profile 정보만 이용하기 때문에 CF처럼 다른 사용자의 정보가 부족할 경우에도 유용하게 쓰일수 있습니다.
    • 위의 특징은 다시 말해 사용자의 정보가 부족하다면 성능이 낮아지거나 존재하지 않는다면 구현이 불가능하다는 뜻과 같습니다
  2. First rater
    • First rater: 평가가 되지 않은 상품들은 추천 리스트에 포함될 수 없는 문제
    • CB는 아이템에 대한 평가 점수가 존재하지 않더라도 유사도가 높은 카테고리의 아이템들이 추천되기 때문에 First rater 문제가 발생하지 않습니다.
  3. Over fitting
    • 앞의 특징에서 비롯된 단점으로, 다른 카테고리의 제품들이 추천되기 어렵기 때문에 비슷한 상품들만 추천된다는 문제점을 지니고 있습니다. 

 

Python code

CB를 python으로 간단하게 구현하기 위해 데이터를 불러오겠습니다.

※ 사용한 데이터는 캐글에서 다운받으실 수 있습니다.

movies = pd.read_csv('/content/drive/MyDrive/archive/tmdb_5000_movies.csv')
movies_df = movies[['id','title', 'genres', 'vote_average', 'vote_count',
                 'popularity', 'keywords', 'overview']]
movies_df = movies_df.drop_duplicates(['title'])                 
print(movies_df.shape)
movies_df.head()

위의 데이터를 확인했을 때 CB의 개념을 구현할 수 있는 방법을 생각해보면 다음과 같은 과정이 나올수 있습니다.

  1. genres 변수를 통해 영화 간 유사도를 도출한다.
  2. 사용자가 시청한 영화중 유사도가 높은 영화 순으로 추천

이러한 기준으로 코딩 하는 법을 알아보겠습니다.

 

먼저, genre 데이터에 대해 좀 더 살펴 보겠습니다.

pd.set_option('max_colwidth', 200)
print(type(movies_df["genres"].iloc[0]))
movies_df[["genres"]]

위의 사진과 같이 딕셔너리 형태로 데이터가 형성되어 있습니다. 또한 type은 문자열로 되어 있어 이를 list로 변환해주는 작업이 필요합니다.

from ast import literal_eval
movies_df['genres'] = movies_df['genres'].apply(literal_eval)
pd.set_option('max_colwidth', 200)
print(type(movies_df["genres"].iloc[0]))
movies_df[["genres"]]

list로 잘 변환된것을 알 수 있습니다.

 

이제 유사도를 구하는 과정입니다. 이번 실습에서는 코사인 유사도를 사용했는데 다른 유사도와 비교해서 성능이 좋은 metric으로 사용하시면 됩니다.

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity

movies_df['genres'] = movies_df['genres'].apply(lambda x : [ y['name'] for y in x])

count_vect = CountVectorizer(min_df=0, ngram_range=(1,2))
genre_mat = count_vect.fit_transform(movies_df['genres_literal'])

genre_sim = cosine_similarity(genre_mat, genre_mat)
print(genre_sim.shape)
print(genre_sim[:2])

다음으로는 특정 영화를 본 사용자에게 비슷한 영화를 추천하는 함수를 위의 유사도를 통해서 간단하게 구현해보도록 하겠습니다.

def recommend_list(df, title, sim,top_n=10):

    title_index = df[df['title'] == title].index
    
    df["sim"] = sim[:, index]

    df = df.drop(index, axis = 0).sort_values("sim", ascending = False).iloc[:top_n, :][["title", "genres", "keywords", "overview"]]
    

    return df

위의 알고리즘은 단순합니다. 

  1. 제공된 영화 제목의 위치를 가져온다.
  2. 해당 영화의 유사도 정보를 원래의 데이터 프레임에 추가(index하기 위함입니다.)
  3. 지정된 영화 index 부분의 유사도를 제외하고 내림차순으로 정렬
  4. 상위 10개의 영화 리스트를 도출

함수를 지정하고 예시로 Point Blank라는 영화를 넣어보았을때의 결과는 아래의 사진과 같습니다.

recommend_list(movies_df, "Point Blank", genre_sim)


이번 시간에는 콘텐츠 기반 추천 시스템(Content-based recommender system, CB)의 개념과 파이썬 구현 코드에 대해 알아보았습니다. 위의 코드는 정말 간단하게 나타낸 코드이고 좀 더 섬세하게 표현하기 위해서는 다양한 개념들이 필요합니다. 하지만 위의 코드의 틀에서 크게 바뀌지 않으니 의미 있는 내용들을 추가하며 공부해 나가면 좋을것 같습니다.  

 

포스팅 내용 중  다른 생각이 있는 분 혹은 수정해야할 부분이 있으시면 댓글을 통해 그 의견을 나눠보면 너무 좋을 것 같습니다.