해결된 질문
작성
·
208
·
수정됨
0
안녕하세요! score를 실행할때마다 nan이 출력이되서 잘못쓴 부분이 있나 여러번 체크해봤는데 도저히 모르겠어서 질문남겨봅니다..
import pandas as pd
import os
import numpy as np
from sklearn.model_selection import train_test_split
# 사용자 u.user파일을 DataFrame으로 열기
base_src = './drive/MyDrive/RecoSys/Data'
os.listdir('./drive/MyDrive/RecoSys/Data')
###### 데이터불러오기 #####
# os.path.join -> 경로 합치기
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')
users.head()
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','FilmNoir','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')
movies.head()
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')
# ratings = ratings.set_index('user_id')
ratings.head()
# 실제값과 예측값을 넣기
def RMSE(y_true, y_pred):
return np.sqrt(np.mean((np.array(y_true) - np.array(y_pred)) **2 ))
# # 모델별 RMSE를 계산 하는 함수
def score(model, neighbor_size=0):
id_pairs = zip(x_test['user_id'], x_test['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)
ratings_matrix = x_train.pivot(index = 'user_id', columns = 'movie_id', values = 'rating')
# 코사인 유사도 계산
from sklearn.metrics.pairwise import cosine_similarity
## 코사인 유사도를 구하기 위해 rating값을 복제하고, 계산 시 Nan값 에러 대비를 위해 결측치를 0으로 대처
matrix_dummy = ratings_matrix.copy().fillna(0)
## 모든 사용자 간 코사인유사도를 구함
user_similarity = cosine_similarity(matrix_dummy,matrix_dummy)
## 필요한 값 조회를 위해 인덱스 및 칼럼명 지정
user_similarity = pd.DataFrame(user_similarity,
index=ratings_matrix.index, columns=ratings_matrix.index)
# Neighbor size를 정해서 예측치를 계산하는 함수
def CF_knn(user_id, movie_id, neighbor_size=0):
if movie_id in ratings_matrix.columns:
sim_scores = user_similarity[user_id].copy()
movie_ratings= ratings_matrix[movie_id].copy()
none_movie_ratings = movie_ratings[movie_ratings.isnull()].index
# print(none_movie_ratings)
moive_ratings = movie_ratings.dropna()
sim_scores = sim_scores.drop(none_movie_ratings)
# print(sim_scores)
# 여기까지는 동일(0일 경우는 일반적인 cf)
if neighbor_size == 0:
mean_rating = np.dot(sim_scores,movie_ratings) / sim_scores.sum()
else:
# 나와 유사한 사람이 없는경우
if len(sim_scores)>1:
# 5명을 10개로 나눌수 없으니까 최소값으로 해줘야한다
neighbor_size = min(neighbor_size,len(sim_scores))
sim_scores = np.array(sim_scores)
movie_ratings = np.array(movie_ratings)
# simscore가 작은 순서대로 작은 유저아이디를 넣는다
user_idx = np.argsort(sim_scores)
sim_scores = sim_scores[user_idx][-neighbor_size:]
## sim_scores 즉, 유사도를 뽑아냈으면 무비평가값을 뽑아내
movie_ratings = movie_ratings[user_idx][-neighbor_size:]
mean_rating = np.dot(sim_scores, movie_ratings) / sim_scores.sum()
else:
mean_rating = 3.0
# movie_id가 rating train pivot table에 포함되지 않을 경우
else:
mean_rating = 3.0
return mean_rating
# 정확도 계산
score(CF_knn,neighbor_size=30)
#### 실제 주어진 사용자에 대해 추천을 받는 기능 구현(테스트 데이터와 훈련데이터를 만들필요가없다) ####
ratings_matrix = ratings.pivot_table(values='rating', index = 'user_id', columns='movie_id')
matrix_dummy = ratings_matrix.copy().fillna(0)
user_similarity = cosine_similarity(matrix_dummy,matrix_dummy)
user_similarity = pd.DataFrame(user_similarity,index = ratings_matrix.index, columns=ratings_matrix.index)
def recom_movie(user_id, n_items, neighbor_size):
# 해당 유저가 평가한 영화가 나온다
user_movie= ratings_matrix.loc[user_id].copy()
for movie in ratings_matrix.columns:
# 현재 영화평점이 null이 아닌 경우 -> 영화를 본경우는 추천 리스트에서 제외하기 위해
if pd.notnull(user_movie.loc[movie]):
user_movie.loc[movie] = 0
else:
user_movie.loc[movie] =CF_knn(user_id,movie,neighbor_size)
movie_sort = user_movie.sort_values(ascending=False)[:n_items]
recom_movie = movies.loc[movie_sort.index]
recommendation = recom_movie['title']
return recommendation
recom_movie(user_id = 729, n_items=5, neighbor_size=30)
score(CF_knn,neighbor_size=30)
+ gpt한테 물어보니
none_rating_idx = movie_ratings[movie_ratings.isnull()].index
moive_ratings = movie_ratings.dropna()
sim_scores = sim_scores.drop(none_rating_idx)
이 부분을
movie_ratings = movie_ratings.dropna()
sim_scores = sim_scores.loc[movie_ratings.index]
이렇게 변경해라해서 수정했더니 nan이 아닌 실수값이 나오기는 하는데 올바른 방법인지를 모르겠습니다. 그래도 같은 방법인거같긴 한데 어디서 차이가 발생하는건지 잘 모르겠습니다!
답변 1
0
안녕하세요.
전체 코드에 대한 디버깅을 해드리긴 어렵습니다.
해당 부분 깊은 양해를 부탁드립니다.
강의에 나오는대로 그대로 따라만 하시는게 아니라,
강의에 나온 내용 이해를 토대로 차근히 따라가주시면 감사하겠습니다.
감사합니다.