콘텐츠 기반 필터링 실습

yeoni·2023년 6월 18일
0

머신러닝

목록 보기
40/40

데이터

코사인 유사도

코사인 유사도 계산식


문장의 유사도 측정을 하는 방법 중 하나인 코사인 유사도 측정을 수행
confusion_matrix와 비슷하게 해석

영화 선정을 위한 가중치 식

  • 평점과 평점을 매긴 횟수를 보면 문제 데이터가 존재해서 가중치를 선정해야 함
  • v : 개별 영화에 평점을 투표한 횟수
  • m : 평점을 부여하기 위한 최소 투표 횟수
  • R : 개별 영화에 대한 평균 평점
  • C : 전체 영화에 대한 평균 평점

1. 데이터 선택

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']]

2. 데이터 정리

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))

3. 가중치 함수

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)

4. 유사도

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) 제로베이스 데이터스쿨 강의자료

profile
데이터 사이언스 / just do it

0개의 댓글