사용자와 상품 사이의 관계를 분석하고 연관관계를 찾아 고객에게 추천해주는 시스템이다.
추천점수:
1) 분석된 사용자와 아이템 정보를 바탕으로 추천점수를 계산한다.
2) 사용자 또는 상품 프로필에서 어떤 정보를 사용할지에 따라 추천 알고리즘을 결정한다.
3) 사용자 또는 아이템을 추천하기 위해 각각의 아이템 또는 사용자에 대한 정량화된 기준이 필요하다.
4) 추천 알고리즘의 목적은 점수화(Scoring) 하는 것이다.
추천시스템 방식
1. 콘텐츠 기반 추천시스템(Contents-based Recommender System)
사용자가 과거에 좋아했던 아이템을 파악하고 그 아이템과 비슷한 아이템을 추천한다.
2. 협업 필터링
비슷한 성향 또는 취향을 갖는 다른 유저가 좋아한 아이템을 현재 유저에게 추천하는 것이다.
3. 하이브리드 추천 시스템
Content-based와 Collaborative Filtering의 장, 단점을 상호보완한 것
추천시스템 유형 딥러닝 활용
CBF 실습: 장르 유사도 기반 영화 추천시스템
CBF 절차:
1). 콘텐츠에 대한 여러 텍스트 정보들을 피처 벡터화
2). 코사인 유사도로 콘텐츠별 유사도 계산
3). 콘텐츠 별로 가중 평점을 계산
4). 유사도가 높은 콘텐츠 중에 평점이 좋은 콘텐츠 순으로 추천
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings; warnings.filterwarnings('ignore')
movies = pd.read_csv("./datasets/tmdb_5000_movies.csv")
In [28]:
# 장르 데이터 전처리
movies_df = movies[['id','title','genres','vote_average', 'vote_count', 'popularity', 'keywords', 'overview']]
from ast import literal_eval
movies_df['genres'] = movies_df['genres'].apply(literal_eval)
movies_df['keywords'] = movies_df['keywords'].apply(literal_eval)
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])
movies_df[['genres','keywords']][:1]
Out[28]:
genreskeywords0
[Action, Adventure, Fantasy, Science Fiction] | [culture clash, future, space war, space colon... |
In [29]:
from sklearn.feature_extraction.text import CountVectorizer
#CountVectorizer를 적용하기 위해 공백문자로 word단위가 구분되는 문자열로 변환.
movies_df['generes_literal'] = movies_df['genres'].apply(lambda x : (' ').join(x))
count_vect = CountVectorizer(min_df=0, ngram_range=(1,2))
genre_mat = count_vect.fit_transform(movies_df['generes_literal'])
print(genre_mat.shape)
(4803, 276)
- bigram으로 피처 수 276개로 증가
In [30]:
from sklearn.metrics.pairwise import cosine_similarity
genre_sim = cosine_similarity(genre_mat, genre_mat)
print(genre_sim.shape)
print(genre_sim[:2])
(4803, 4803)
(4803, 4803)
[[1. 0.59628479 0.4472136 ... 0. 0. 0. ]
[0.59628479 1. 0.4 ... 0. 0. 0. ]]
Out[30]:
(4803, 4803)
- 영화 간 장르 유사도를 코사인 유사도를 계산
In [16]:
genre_sim_sorted_ind = genre_sim.argsort()[:, ::-1]
print(genre_sim_sorted_ind[:1])
[[ 0 3494 813 ... 3038 3037 2401]]
- 첫번째 영화와 유사도가 높은 영화 순서
In [31]:
def find_sim_movie(df, sorted_ind, title_name, top_n=10):
#인자로 입력된 movies_df DataFrame에서 'title'칼럼이 입력된 title_name값인 DataFrame 추출
title_movie = df[df['title'] == title_name]
#title_named을 가진 DataFrame의 index객체를 ndarray로 반환하고
#sorted_ind 인자로 입력된 genre_sim_sorted_ind 객체에서 유사도 순으로 top_n개의 index추출
title_index = title_movie.index.values
similar_indexes = sorted_ind[title_index, :(top_n)]
#추출된 top_n index출력, top_n index는 2차원 데이터임
#dataframe에서 index로 사용하기 위해서 1차원 array로 변경
print(similar_indexes)
similar_indexes = similar_indexes.reshape(-1)
return df.iloc[similar_indexes]
가중평점(Weighted Rating):
(v/(v+m))* R + (m/v+m))*c
- v: 영화별 평점을 투표한 횟수(vote_count)
- m: 평점을 부여하기 위한 최소 투표 횟수
- R: 개별 영화에 대한 평균 평점
- c: 전체 영화에 대한 평균 평점
- C,m은 고정값이며, v,R은 영화마다 변동값으로 존재한다.
In [32]:
percentile = 0.6
m = movies['vote_count'].quantile(percentile)
c = movies['vote_average'].mean()
In [33]:
print('C:', round(c,3), 'm:', round(m,3))
C: 6.092 m: 370.2
In [34]:
percentile = 0.6
m = movies['vote_count'].quantile(percentile)
C = movies['vote_average'].mean()
def weighted_vote_average(record):
v = record['vote_count']
R = record['vote_average']
return ( (v/(v+m)) * R) + ( (m/(m+v))*C )
movies_df['weighted_vote'] = movies.apply(weighted_vote_average, axis=1)
def find_sim_movie_ver2(df, sorted_ind, title_name, top_n=10):
#인자로 입력된 movies_df DataFrame에서 'title'칼럼이 입력된 title_name값인 DataFrame 추출
title_movie = df[df['title'] == title_name]
print(title_movie)
title_index = title_movie.index.values
#top_n의 2배에 해당하는 장르 유사성이 높은 인덱스 추출
similar_indexes = sorted_ind[title_index, :(top_n*2)]
similar_indexes = similar_indexes.reshape(-1)
#기준 영화 인덱스는 제외
similar_indexes = similar_indexes[similar_indexes != title_index]
#top_n의 2배에 해당하는 후보군에서 weight_vote가 노은 순으로 top_n만큼 추출
return df.iloc[similar_indexes].sort_values('weighted_vote', ascending=False)[:top_n]
In [35]:
similar_movies = find_sim_movie_ver2(movies_df, genre_sim_sorted_ind, 'The Godfather', 10)
similar_movies[['title', 'vote_average', 'weighted_vote', 'genres' ,'vote_count']]
id title genres vote_average vote_count \
3337 238 The Godfather [Drama, Crime] 8.4 5893
popularity keywords \
3337 143.659698 [italy, love at first sight, loss of father, p...
overview generes_literal \
3337 Spanning the years 1945 to 1955, a chronicle o... Drama Crime
weighted_vote
3337 8.263591
Out[35]:
titlevote_averageweighted_votegenresvote_count27311847386616638832814041114912432839
The Godfather: Part II | 8.3 | 8.079586 | [Drama, Crime] | 3338 |
GoodFellas | 8.2 | 7.976937 | [Drama, Crime] | 3128 |
City of God | 8.1 | 7.759693 | [Drama, Crime] | 1814 |
Once Upon a Time in America | 8.2 | 7.657811 | [Drama, Crime] | 1069 |
Catch Me If You Can | 7.7 | 7.557097 | [Drama, Crime] | 3795 |
American Gangster | 7.4 | 7.141396 | [Drama, Crime] | 1502 |
This Is England | 7.4 | 6.739664 | [Drama, Crime] | 363 |
American Hustle | 6.8 | 6.717525 | [Drama, Crime] | 2807 |
Mean Streets | 7.2 | 6.626569 | [Drama, Crime] | 345 |
Rounders | 6.9 | 6.530427 | [Drama, Crime] | 439 |
Gotfather장르가 Drama, Crime이다.
우선 Drama, Crime 장르 기준으로 상위 20개 영화를 뽑아보고
그 중 평가횟수를 반영한 가중평점 기준 상위 10개 영화를 뽑아서 추천해준다.
728x90
'딥러닝' 카테고리의 다른 글
RNN (순환신경망) (0) | 2022.05.11 |
---|---|
CNN - mnist 데이터 셋 (0) | 2022.05.11 |
퍼셉트론 (0) | 2022.04.29 |
딥러닝 기초 (0) | 2022.04.29 |