1. 영화 제목과 장르 불러오기
import csv
titles = {}
genresets = {}
with open('../datas/ml-25m/movies.csv', 'r') as f:
print(f.readline())
csv_reader = csv.reader(f)
for mid, title, genres in csv_reader:
titles[int(mid)] = title # 영화 ID를 키로, 제목을 값으로 저장
genresets[int(mid)] = set(genres.split('|')) # 영화 ID를 키로, 장르를 set으로 저장
2. 자카드 유사도
def jaccard(a, b):
"""두 집합의 자카드 유사도 계산"""
if len(a | b) == 0:
return 0
return len(a & b) / len(a | b)
def get_topk_jaccard_genres(target_mid, k=10):
"""타겟 영화와 장르가 가장 유사한 상위 k개의 영화 ID를 반환"""
target_genres = genresets[target_mid]
res = []
for mid, title in titles.items():
genresest = genresets[mid]
score = jaccard_similarity(target_genres, genresest)
res.append((score, title))
res.sort(reverse=True)
return res[:k]
3. 유사도 검사
mid = 164909 # 영화 ID
res = get_topk_jaccard_genres(mid, 20)
res
4. 다른 사용자가 함께 본 영화 찾기
with open('../datas/ml-25m/ratings.csv', 'r') as f:
print(f.readline())
csv_reader = csv.reader(f)
ratings = []
for uid, mid, rating, timestamp in csv_reader:
uid = int(uid)
mid = int(mid)
rating = float(rating)
ratings.append((uid, mid, rating))
ratings[:2]
from collections import defaultdict # defaultdict을 사용하여 ratings를 uid별로 그룹화
usets = defaultdict(set)
for uid, mid, rating in ratings:
usets[mid].add(uid)
5. 장르가 유사한 영화 찾기
from tqdm import tqdm
def get_topk_jaccard_ratings(target_mid, k=10):
"""타겟 영화와 장르가 가장 유사한 상위 k개의 영화 ID를 반환"""
target_uset = usets[target_mid]
res = []
for mid, title in tqdm(titles.items()):
usest = usets[mid]
score = jaccard_similarity(target_uset, usest)
res.append((score, title))
res.sort(reverse=True)
return res[:k]
mid = 112552 # 위플레시
res = get_topk_jaccard_ratings(mid, 20)
res
6. 비슷한 평가를 받는 영화 찾기
ursets = defaultdict(dict)
for uid, mid, rating in ratings:
ursets[mid][uid] = rating
for mid, urset in ursets.items():
avg = sum(urset.values()) / len(urset)
for k in urset:
urset[k] -= avg # 평균 평점을 빼서 중심화
def cosine_similar(a, b):
"""두 집합의 코사인 유사도 계산"""
nu = sum(a[k] * b[k] for k in a.keys() & b.keys())
de = (sum(v ** 2 for v in a.values()) ** 0.5) * (sum(v ** 2 for v in b.values()) ** 0.5)
if de == 0:
return 0
return nu / de
def get_topk_pearson_ratings(target_mid, k=10):
"""타겟 영화와 장르가 가장 유사한 상위 k개의 영화 ID를 반환"""
target_urset = ursets[target_mid]
res = []
for mid, title in tqdm(titles.items()):
urset = ursets[mid]
score = cosine_similar(target_urset, urset)
res.append((score, title))
res.sort(reverse=True)
return res[:k]
mid = 164909 # 타겟 영화 ID
res = get_topk_pearson_ratings(mid, 20)
res