문장의 유사도 측정을 하는 방법 중 하나인 코사인 유사도 측정을 수행
confusion_matrix와 비슷하게 해석
import pandas as pd
import numpy as np
import warnings; warnings.filterwarnings('ignore')
movies = pd.read_csv('./data/movie/tmdb_5000_movies.csv')
movies_df = movies[['id', 'title', 'genres', 'vote_average', 'vote_count', 'popularity', 'keywords', 'overview']]
1) genres와 keywords는 컬럼안에 dict형이지만 dtype=object
2) literal_eval
사용해 list와 dict으로 복구
literal_eval
: 문자열(str) 속 표현 인식시켜줌 3) dict의 value 값을 특성으로 사용하도록 변경
4) genres의 각 단어들을 띄어쓰기로 구분된 하나의 문장으로 변환
from ast import literal_eval
# 2
movies_df['genres'] = movies_df['genres'].apply(literal_eval)
movies_df['keywords'] = movies_df['keywords'].apply(literal_eval)
# 3
movies_df['genres'] = movies_df['genres'].apply(lambda x : [y['name'] for y in x])
movies_df['keywords'] = movies_df['keywords'].apply(lambda x : [y['name'] for y in x])
# 4
movies_df['genres_literal'] = movies_df['genres'].apply(lambda x: (' ').join(x))
1) 영화 전체 평균평점과 최소 투표 횟수를 60%지점으로 지정
2) 가중치가 부여된 평점을 계산하기 위한 함수
2) weighted_vote
컬럼 만들기
# 1
C = movies_df['vote_average'].mean()
m = movies_df['vote_count'].quantile(0.6)
# 2
def weighted_vote_average(record):
v = record['vote_count']
R = record['vote_average']
return ((v/(v+m) * R) + ((m/(m+v)) * C))
# 3
movies_df['weighted_vote'] = movies_df.apply(weighted_vote_average, axis=1)
1) 문자열로 변환된 genres를 CountVectorize 수행
2) 코사인 유사도
3) genre_sim 객체에서 높은 값 순으로 정렬
argsort()
array 정렬argsort()[::-1]
내림차순 정렬4) 추천 영화를 DataFrame으로 반환하는 함수
5) '대부'와 비슷한 결과
# 1
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
count_vect = CountVectorizer(min_df=0, ngram_range=(1, 2))
genre_mat = count_vect.fit_transform(movies_df['genres_literal'])
# 2
genre_sim = cosine_similarity(genre_mat, genre_mat)
# 3
genre_sim_sorted_ind = genre_sim.argsort()[:, ::-1]
# 4
def find_sim_movie(df, sorted_ind, title_name, top_n=10):
title_movie = df[df['title'] == title_name]
title_index = title_movie.index.values
similar_indexes = sorted_ind[title_index, :(top_n * 2)]
similar_indexes = similar_indexes.reshape(-1)
similar_indexes = similar_indexes[similar_indexes != title_index]
return df.iloc[similar_indexes].sort_values('weighted_vote', ascending=False)[:top_n]
# 5
similar_movies = find_sim_movie(movies_df, genre_sim_sorted_ind, 'The Godfather', 10)
similar_movies[['title', 'vote_average', 'weighted_vote']]
Reference
1) 제로베이스 데이터스쿨 강의자료