# -*- coding: utf-8 -*- !pip install datasets from sklearn.decomposition import TruncatedSVD from scipy.sparse.linalg import svds import matplotlib.pyplot as plt import seaborn as sns import pandas as pd import numpy as np import warnings warnings.filterwarnings("ignore") from datasets import load_dataset """## 데이터로드 및 전처리 """ # df:도서관,박물관,공원이 place_id,place_name,gu_name,type 으로된 데이터: csv 파일로 읽어오기 df= read_csv('places.csv', index=False, encoding='utf-8') """# 사용자 평점데이터 """ user_rating= read_csv('user_rating_1000.csv', index=False, encoding='utf-8') """아이템-특성 데이터 만들기""" # place_id, type, place_name만 추출 item_feature = df[['place_id', 'type', 'place_name']] item_feature.head() """추천시스템구현 """ # 사용자-장소-평점 피봇만들기 df_user_place_ratings = user_place_data.pivot_table(index='user_id', columns='place_id', values='rating') df_user_place_ratings.head() """ 이후 할일 1)pivot table을 matrix로 변환 2)np.mean(axis = 1)을 통해 장소별 각 사용자들이 매기는 평점 평균을 구함 1에서 구한 값과 2에서 구한 값을 빼서 사용자-평균 데이터 값을 변경 """ # float타입을 str로 변환 df_user_place_ratings.columns = df_user_place_ratings.columns.astype(str) # df_user_place_ratings: pivot_table 값을 numpy matrix로 만든 것 df_user_place_ratings.columns = df_user_place_ratings.columns.str.strip() # 화이트스페이스 지우기 matrix = df_user_place_ratings.values #as_matrix function은 depricated. # user_ratings_mean: 사용자의 평균 평점 user_ratings_mean = np.mean(matrix, axis = 1) # # matrix_user_mean : 사용자-영화에 대해 사용자 평균 평점을 뺀 것. matrix_user_mean = matrix - user_ratings_mean.reshape(-1, 1) pd.DataFrame(matrix_user_mean, columns = df_user_place_ratings.columns).head() # scipy에서 제공해주는 svd. # U 행렬, sigma 행렬, V 전치 행렬을 반환. U, sigma, Vt = svds(matrix_user_mean, k = 12) # 현재 이 Sigma 행렬은 0이 아닌 값만 1차원 행렬로 표현된 상태입니다. # 즉, 0이 포함된 대칭행렬로 변환할 때는 numpy의 diag를 이용해야 합니다. sigma = np.diag(sigma) sigma.shape # U, Sigma, Vt의 내적을 수행하면, 다시 원본 행렬로 복원이 된다. # 거기에 + 사용자 평균 rating을 적용한다. svd_user_predicted_ratings = np.dot(np.dot(U, sigma), Vt) + user_ratings_mean.reshape(-1, 1) df_svd_preds = pd.DataFrame(svd_user_predicted_ratings, columns = df_user_place_ratings.columns) df_svd_preds.head() df_svd_preds.shape # 예측 결과 정렬 및 반환코드 # 사용자의 예측 평점이 높은 순으로 정렬된 데이터 # user_id가 0부터 시작하므로 user_row_number로 쓴다. 1부터시작하면 user_id-1하면됨. user_id = 0 # 0번회원의 평점 예측 user_row_number = user_id sorted_user_predictions = df_svd_preds.iloc[user_row_number].sort_values(ascending=False) sorted_user_predictions = pd.DataFrame(sorted_user_predictions.reset_index()) sorted_user_predictions.columns = ['place_id', 'predict_rating'] sorted_user_predictions['place_id'] = sorted_user_predictions['place_id'].astype('int64') # 원본 평점 데이터에서 user id에 해당하는 데이터를 추출 user_data = user_rating[user_rating['user_id'] == user_id] # user_data에서 평점이 0인 데이터는 아직 안 가본 것이므로 삭제 user_data = user_data[user_data['rating'] != 0.0] # (가본 장소) 추출된 데이터와 원본 장소 데이터를 합침 user_history = user_data.merge(item_feature, on='place_id').sort_values(['rating'], ascending=False) # 사용자가 평가하지 않은 장소를 추천 대상으로 설정 recommendations = item_feature[~item_feature['place_id'].isin(user_history['place_id'])]