• 카테고리

    질문 & 답변
  • 세부 분야

    딥러닝 · 머신러닝

  • 해결 여부

    해결됨

score를 실행하면 항상 nan이 출력됩니다

24.03.13 21:16 작성 24.03.13 21:49 수정 조회수 90

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

안녕하세요.

전체 코드에 대한 디버깅을 해드리긴 어렵습니다.

해당 부분 깊은 양해를 부탁드립니다.

강의에 나오는대로 그대로 따라만 하시는게 아니라,

강의에 나온 내용 이해를 토대로 차근히 따라가주시면 감사하겠습니다.

감사합니다.