해결된 질문
작성
·
321
0
아래 부분에서 불균일한 데이터임을 나타내는 에러가 발생하는데 이유를 못찾겠습니다.
전체 코드입니다.
from inspect import Signature
import os
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
### 데이터 불러오기 및 필요한 함수 정의 ###
# user 데이터
base_src = 'drive/MyDrive/RecoSys/Data'
u_user_src = os.path.join(base_src, 'u.user')
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv(u_user_src,
sep='|',
names=u_cols,
encoding='latin-1')
users = users.set_index('user_id')
u_item_src = os.path.join(base_src, 'u.item')
i_cols = ['movie_id','title','release date','video release date',
'IMDB URL','unknown','Action','Adventure','Animation',
'Children\'s','Comedy','Crime','Documentary','Drama','Fantasy',
'Film-Noir','Horror','Musical','Mystery','Romance','Sci-Fi','Thriller','War','Western']
movies = pd.read_csv(u_item_src,
sep='|',
names=i_cols,
encoding='latin-1')
movies = movies.set_index('movie_id')
u_data_src = os.path.join(base_src, 'u.data')
r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv(u_data_src,
sep='\t',
names=r_cols,
encoding='latin-1')
# 정확도(RMSE)를 계산하는 함수
def RMSE(y_true, y_pred):
return np.sqrt(np.mean((np.array(y_true) - np.array(y_pred))**2))
# 유사집단의 크기를 미리 정하기 위해서 기존 score 함수에 neighbor_size 인자값 추가
def score(model, neighbor_size=0):
id_pairs = zip(x_test['user_id'],x_test['movie_id']) # user_id와 movie_id 쌍을 만든다
y_pred = np.array([model(user, movie, neighbor_size) for (user, movie) in id_pairs])
y_true = np.array(x_test['rating'])
return RMSE(y_true,y_pred)
# 데이터셋 만들기
x = ratings.copy()
y = ratings['user_id']
x_train, x_test, y_train, y_test = train_test_split(x, y,
test_size=0.25,
stratify=y)
rating_matrix = x_train.pivot(index='user_id', columns='movie_id', values='rating')
# 코사인 유사도 계산
# train set의 모든 가능한 사용자 pair의 cosine similarity 계산
from sklearn.metrics.pairwise import cosine_similarity
matrix_dummy = rating_matrix.copy().fillna(0)
user_similarity = cosine_similarity(matrix_dummy, matrix_dummy)
user_similarity = pd.DataFrame(user_similarity,
index=rating_matrix.index,
columns=rating_matrix.index)
### 사용자 평가 경향을 고려한 함수 ###
rating_mean = rating_matrix.mean(axis=1)
rating_bias = (rating_matrix.T - rating_mean).T # 평점 평균에 대한 편차
#####################################
rating_binary_1 = np.array(rating_matrix > 0).astype(float) # 0 초과의 값이 있는 셀은 true, 나머지는 false로
rating_binary_2 = rating_binary_1.T
counts = np.dot(rating_binary_1, rating_binary_2)
counts = pd.DataFrame(counts,
index=rating_matrix.index,
columns=rating_matrix.index).fillna(0)
def CF_knn_bias_sig(user_id, movie_id, neighbor_size=0):
if movie_id in rating_bias:
sim_scores = user_similarity[user_id].copy()
movie_ratings = rating_bias[movie_id].copy()
no_rating = movie_ratings.isnull() # 평가가 없는
common_counts = counts[user_id] # 주어진 user_id를 기준으로 다른 user들과 공통으로 평가한 영화의 개수들을 담은 배열
low_significance = common_counts < SIG_LEVEL # 공통 평가한 영화 개수가 미리 정해진 level보다 낮은 사용자에 대해 false 처리
none_rating_idx = movie_ratings[no_rating | low_significance].index # 추천 알고리즘에서 제외할 인덱스 추출
movie_ratings = movie_ratings.drop(none_rating_idx)
sim_scores = sim_scores.drop(none_rating_idx)
if neighbor_size == 0:
prediction = np.dot(sim_scores, movie_ratings) / sim_scores.sum()
prediction = prediction + rating_mean[user_id]
else:
if len(sim_scores) > MIN_RATINGS:
neighbor_size = min(neighbor_size, len(sim_scores))
sim_scores = np.array(sim_scores) # 행렬 연산을 위해 배열 형태로 변환
movie_ratings = np.array(movie_ratings)
user_idx = np.argsort(sim_scores)
sim_scores = sim_scores[user_idx][-neighbor_size:]
movie_ratings = movie_ratings[user_idx][-neighbor_size:]
prediction = np.dot(sim_scores, movie_ratings) / sim_scores.sum()
prediction = prediction + rating_mean
else:
prediction = rating_mean[user_id]
else:
prediction = rating_mean[user_id]
# RMSE 개선을 위한 조정
# if prediction <= 1:
# prediction = 1
# elif prediction >= 5:
# prediction = 5
return prediction
SIG_LEVEL = 3
MIN_RATINGS = 3
score(CF_knn_bias_sig, 30)