본문 바로가기

프로그래머스 데브 코스/TIL

[6기] 프로그래머스 인공지능 데브코스 103일차 TIL

1212

[17주차 - Day1] Recommendation system

추천 엔진 개발

# TMDB 인기 영화 컨텐츠 기반 추천 시스템 실습 코드

이번 실습에서 사용하는 데이터셋: https://www.kaggle.com/tmdb/tmdb-movie-metadata

 

TMDB 5000 Movie Dataset

Metadata on ~5,000 movies from TMDb

www.kaggle.com

 

입력 데이터 로딩

import pandas as pd
import numpy as np


movies = pd.read_csv("https://grepp-reco-test.s3.ap-northeast-2.amazonaws.com/tmdb_5000_movies.csv")


import json

def f(j):
    genres = []
    ar = json.loads(j)
    for a in ar:
        genres.append(a.get("name"))
    return " ".join(sorted(genres))

movies['genres_name'] = movies.apply(lambda x: f(x.genres), axis=1)

 

여러 텍스트 필드들을 모아서 텍스트 유사도에 사용할 텍스트 필드 하나를 생성

for f in ['original_title','overview','genres_name']:
  movies[f] = movies[f].fillna('')
  
  
  def combine_features(row):
	try:
		return row['original_title']+" "+row['overview']+" "+row["genres_name"]
	except:
		print ("Error:", row)
        
        
movies["combined_features"] = movies.apply(combine_features,axis=1)
movies = movies.reset_index()

 

 

TF-IDF 기반 벡터 생성 후 코사인 유사도로 영화들간의 유사도 계산

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


tfidfvectorizer = TfidfVectorizer(analyzer='word', stop_words='english', norm='l2')


tfidf_matrix = tfidfvectorizer.fit_transform(movies["combined_features"])


cosine_sim = cosine_similarity(tfidf_matrix) # linear_kernel을 사용해도 동일함. tfidf 벡터가 생성될 때 L2 normalization이 되었기 때문


df_cosine_sim = pd.DataFrame(data = cosine_sim)
df_cosine_sim.head()

 

 

컨텐츠 기반 추천 함수 만들기

def get_title_from_index(df, index):
	return df[df.index == index]["original_title"].values[0]

def get_index_from_title(df, title):
	return df[df.original_title == title]["index"].values[0]
    

def reco_top_similar_movies(movie_title, n=10):
  movie_index = get_index_from_title(movies, movie_title)
  similar_movies =  enumerate(cosine_sim[movie_index])
  sorted_similar_movies = sorted(similar_movies, key=lambda x:x[1], reverse=True)

  ret_movies = []
  i = 0
  for element in sorted_similar_movies:
    title = get_title_from_index(movies, element[0])
    ret_movies.append(title)
    i=i+1
    if i >= n:
      break
  return ret_movies