250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 흐름도
- 코딩
- Regression
- 추천시스템
- python
- 코딩테스트
- 머신러닝
- 주식연습
- 알고리즘
- 주식
- 파이썬
- tensorflow
- 딥러닝
- CLI
- 게임
- 프로그래머스
- 선형회귀
- 기초
- PyTorch
- Linear
- DeepLearning
- 크롤링
- 회귀
- 템플릿
- 주식매매
- API
- 주가예측
- 가격맞히기
- 재귀함수
- 연습
Archives
- Today
- Total
코딩걸음마
[추천 시스템(RS)] CBF 장르 기반 영화 추천 코드 본문
728x90
1. 데이터 불러오기
사용할 데이터 셋 : TMDB 5000 Movie Dataset
https://www.kaggle.com/datasets/tmdb/tmdb-movie-metadata/download?datasetVersionNumber=2
import pandas as pd
import numpy as np
movies_df = pd.read_csv('data/tmdb_5000_movies.csv')
print(movies_df.shape) # 행, 열 개수 파악
movies_df.head()
(4803, 20)
2. 데이터 확인
결측치 및 dtype확인
movies_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4803 entries, 0 to 4802
Data columns (total 20 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 budget 4803 non-null int64
1 genres 4803 non-null object
2 homepage 1712 non-null object
3 id 4803 non-null int64
4 keywords 4803 non-null object
5 original_language 4803 non-null object
6 original_title 4803 non-null object
7 overview 4800 non-null object
8 popularity 4803 non-null float64
9 production_companies 4803 non-null object
10 production_countries 4803 non-null object
11 release_date 4802 non-null object
12 revenue 4803 non-null int64
13 runtime 4801 non-null float64
14 spoken_languages 4803 non-null object
15 status 4803 non-null object
16 tagline 3959 non-null object
17 title 4803 non-null object
18 vote_average 4803 non-null float64
19 vote_count 4803 non-null int64
dtypes: float64(3), int64(4), object(13)
memory usage: 750.6+ KB
3. 장르 컬럼 추출
print(type(movies_df['genres'][0]))
movies_df['genres'][0]
딕셔너리 처럼 보이지만 문자열 type이다
<class 'str'>
'[{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}]'
from ast import literal_eval # 문자열 파싱 (리스트 or 딕셔너리 형태의 문자열을 리스트 or 딕셔너리로 변환)
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']][0:3]
4. 장르 컨텐츠 유사도 측정
장르 CBF 추천 : 장르를 피처 벡터화한 후 행렬 데이터 값을 코사인 유사도(0~1)로 계산
<프로세스>
1. 장르 피처 벡터화: 문자열로 변환된 genres 칼럼을 Count 기반으로 피처 벡터화 변환
2. 코사인 유사도 계산 : genres 문자열을 피처 벡터화한 행렬로 변환한 데이터 세트를 코사인 유사도로 비교
3. 평점으로 계산 : 장르 유사도가 높은 영화 중 평점이 높은 순으로 영화 추천
!) CountVectorizer
1. 문서를 토큰 리스트로 변환한다.
2. 각 문서에서 토큰의 출현 빈도를 센다.
3. 각 문서를 BOW(Bag of Words) 인코딩 벡터로 변환한다.
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'안녕하세요~ 감사해요 다시 만나요',
'안녕 내사람 그대여 그대 내가 지켜줄게요',
'안녕 안녕 안녕~',
'안녕이라고 내게 말하지마',
]
# 토큰 별 인덱스 사전을 만들어준다.
vect = CountVectorizer()
vect.fit(corpus)
vect.vocabulary_
{'안녕하세요': 11,
'감사해요': 0,
'다시': 6,
'만나요': 7,
'안녕': 9,
'내사람': 5,
'그대여': 2,
'그대': 1,
'내가': 3,
'지켜줄게요': 12,
'안녕이라고': 10,
'내게': 4,
'말하지마': 8}
# CountVectorizer로 학습시켰더니 4803개 영화에 대한 276개 장르의 '장르 매트릭스'가 생성되었다.
count_vect = CountVectorizer(min_df=0, ngram_range=(1, 2)) # min_df: 단어장에 들어갈 최소빈도, ngram_range: 1 <= n <= 2
genre_mat = count_vect.fit_transform(movies_df['genres_literal'])
print(genre_mat.shape)
print(genre_mat)
# 영화 별 장르 인덱스 사전을 만들어준다
# CountVectorizer로 학습시켰더니 4803개 영화에 대한 22개 장르의 '장르 매트릭스'가 생성되었다.
count_vect2 = CountVectorizer(min_df=1, ngram_range=(1, 1)) # min_df: 단어장에 들어갈 최소빈도, ngram_range: 1 <= n <= 2
genre_mat2 = count_vect2.fit_transform(movies_df['genres_literal'])
print(genre_mat2.shape)
print(genre_mat2)
(4803, 22)
(0, 0) 1
(0, 1) 1
(0, 8) 1
(0, 17) 1
(0, 9) 1
.
.
.
(4799, 3) 1
(4799, 16) 1
(4800, 6) 1
(4800, 3) 1
(4800, 16) 1
(4800, 19) 1
(4800, 13) 1
(4802, 5) 1
5) 코사인 유사도(cosine_similarity)이용해서 영화별 유사도 계산
# 코사인 유사도에 의해 4803개 영화 각각 유사한 영화들이 계산됨
from sklearn.metrics.pairwise import cosine_similarity
genre_sim = cosine_similarity(genre_mat, genre_mat)
print(genre_sim.shape)
print(genre_sim[:10])
print(genre_sim[0][:5])
[1. 0.59628479 0.4472136 0.12598816 0.75592895]
# 자료를 정렬하는 것이 아니라 순서만 알고 싶다면 argsort
# 유사도가 높은 영화를 앞에서부터 순서대로 보여줌
# 0번째 영화의 경우 유사도 순서 : 0번, 3494번, 813번, ..., 2401 순서
genre_sim_sorted_ind = genre_sim.argsort()[:, ::-1] # ::-1 : 역순으로 정렬
print(genre_sim_sorted_ind[:5])
genre_sim_sorted_ind
array([[ 0, 3494, 813, ..., 3038, 3037, 2401],
[ 262, 1, 129, ..., 3069, 3067, 2401],
[ 2, 1740, 1542, ..., 3000, 2999, 2401],
...,
[4800, 3809, 1895, ..., 2229, 2230, 0],
[4802, 1594, 1596, ..., 3204, 3205, 0],
[4802, 4710, 4521, ..., 3140, 3141, 0]])
6) 장르 코사인 유사도에 의해 영화를 추천하는 함수
# 인자로 입력된 movies_df DataFrame에서 'title' 컬럼이 입력된 title_name 값인 DataFrame추출
title_movie = movies_df[movies_df['title'] == 'Avatar']
title_movie
# 추출된 top_n index들 출력. top_n index는 2차원 데이터 임.
# dataframe에서 index로 사용하기 위해서 2차원 array를 1차원 array로 변경
similar_indexes = similar_indexes.reshape(-1)
print(similar_indexes)
[ 0 3494 813 870 46 14 1296 1652 419 420]
movies_df.iloc[similar_indexes]
+) 유사한 장르의 영화를 찾는 함수
def find_sim_movie_ver1(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)
# 2차원 데이터를 1차원으로 변환
similar_indexes = similar_indexes.reshape(-1)
return df.iloc[similar_indexes]
+) 상위 10개 영화 출력
similar_movies = find_sim_movie_ver1(movies_df, genre_sim_sorted_ind, 'The Godfather', 10)
similar_movies[['title', 'vote_average', 'genres', 'vote_count']]
# 문제 ; 평점 기반으로 추천하고자 하는데, vote_count가 낮은 영화는 제외하고 싶음
728x90
'딥러닝 템플릿 > 추천시스템(RS) 코드' 카테고리의 다른 글
[추천 시스템(RS)] Neural Collaborative Filtering (0) | 2022.07.19 |
---|---|
[추천 시스템(RS)] Matrix Factorization (0) | 2022.07.19 |
[추천 시스템(RS)] Surprise 라이브러리를 활용한 추천 시스템 (0) | 2022.07.19 |
[추천 시스템(RS)] 협업 필터링 CF (Collaborate Filtering) (0) | 2022.07.16 |
[추천 시스템(RS)] CF-KNN (Collaborate Filtering K-Nearest Neighbor) (0) | 2022.07.16 |
Comments