Inflearn brand logo image

인프런 커뮤니티 질문&답변

part-spt님의 프로필 이미지
part-spt

작성한 질문수

(UPDATED) Python을 이용한 개인화 추천시스템 | 추천알고리즘 | 추천인공지능

Keras로 MF 구현하기

6장 Keras로 MF 구현하기 학습 결과

작성

·

90

·

수정됨

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

 

6장.ipynb 받은 파일에 있는 소스코드로 학습 진행 후, 시각화를 해보는데

image.pngimage.png

 

결과가 너무 안 좋게 나옵니다...

(위 2회 실행 결과)

6장.ipynb에 따로 코드를 수정하지는 않았고 강의 영상 보면서 순서대로 실행만 시켜본 상태인데..

 

(추가) 바로 밑에 딥러닝을 적용한 추천시스템 학습에 대한 결과 그래프도 안좋아요.

image.png

(추가)딥러닝에 변수 추가하기

image.png

 

 

 

어디 잘못된거나, 사전에 뭔가 따로 처리해줘야 하는게 있나요?

 

 

답변 2

0

거친코딩님의 프로필 이미지
거친코딩
지식공유자

안녕하세요.

죄송합니다. 해당 질문글을 제가 놓쳤네요.

일단 질문에 대한 답변을 드리자면,

해당건은 혹시 이전에 실행한 코드 부분과 혼재가 되어서 혹시나 결과가 안좋게 나올 수 있을 것 같습니다.

그런게 아니라면,

혹시 코드 그대로 한번 올려주실 수 있으실까요?

part-spt님의 프로필 이미지
part-spt
질문자

#첫번째 결과에 대한 코드
# 6.2 Keras로 MF 구현하기


# csv 파일에서 불러오기
import pandas as pd

# train set과 test set을 나누기 위한 라이브러리
from sklearn.model_selection import train_test_split

# 필요한 tensorflow 모듈들을 가져온다.
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input,Embedding,Dot,Add,Flatten
from tensorflow.keras.regularizers import l2
from tensorflow.keras.optimizers import SGD,Adamax

# DataFrame 형태로 데이터를 읽어온다.
r_cols = ['user_id','movie_id','rating','timestamp']
ratings = pd.read_csv('drive/MyDrive/RecoSys/Data/u.data',
                      names=r_cols,
                      sep='\t',
                      encoding='latin-1')

ratings_train,ratings_test = train_test_split(ratings,
                                              test_size=0.2,
                                              shuffle=True,
                                              random_state=2021)

K = 200

mu = ratings_train.rating.mean()

M = ratings.user_id.max() + 1
N = ratings.movie_id.max() + 1

def RMSE(y_true ,y_pred):
  return tf.sqrt(tf.reduce_mean(tf.square(y_true-y_pred)))

user = Input(shape=(1,))
item = Input(shape=(1,))

P_embedding = Embedding(M,K,embeddings_regularizer=l2())(user)
Q_embedding = Embedding(N,K,embeddings_regularizer=l2())(item)

user_bias = Embedding(M,1,embeddings_regularizer=l2())(user)
item_bias = Embedding(N,1,embeddings_regularizer=l2())(item)

R = layers.dot([P_embedding,Q_embedding],axes=(2,2))

R = layers.add([R,user_bias,item_bias])

R = Flatten()(R)

model = Model(inputs=[user,item],outputs=R)
model.compile(
    loss=RMSE,
    optimizer=SGD(),
    metrics=[RMSE]
)

model.summary()

result = model.fit(
    x = [ratings_train.user_id.values,
         ratings_train.movie_id.values],
    y=ratings_train.rating.values - mu,

    epochs = 60,
    batch_size=256,
    validation_data = (
        [ratings_test.user_id.values,
         ratings_test.movie_id.values],
         ratings_test.rating.values - mu
    )
)

# Plot RMSE
import matplotlib.pyplot as plt
plt.plot(result.history['RMSE'],label="Train RMSE")
plt.plot(result.history['val_RMSE'],label='Test RMSE')
plt.legend()
plt.show()

 

#두번째 결과에 대한 코드
# 6.3 딥러닝을 적용한 추천 시스템

# csv 파일에서 불러오기
import pandas as pd

# train set과 test set을 나누기 위한 라이브러리
from sklearn.model_selection import train_test_split

# 필요한 tensorflow모듈들을 가져온다.
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input,Embedding,Dot,Add,Flatten
# layer 구성에 필요한 라이브러리 불러오기
from tensorflow.keras.layers import Dense,Concatenate,Activation
from tensorflow.keras.regularizers import l2
from tensorflow.keras.optimizers import SGD,Adamax

# DataFrame 형태로 데이터를 읽어온다.
r_cols = ['user_id','movie_id','rating','timestamp']
ratings = pd.read_csv('drive/MyDrive/RecoSys/Data/u.data',
                      names=r_cols,
                      sep='\t',
                      encoding='latin-1')

ratings_train,ratings_test = train_test_split(ratings,
                                              test_size=0.2,
                                              shuffle=True,
                                              random_state=2021)

# Defining RMSE measure
# y_true, y_pred은 신경망에서 실제값, 예측값을 나타내는 Tensorflow/Keras 표준 변수이다.
def RMSE(y_true, y_pred):
  # Tensorflow의 math 클래스에 미리 정의된
  # 제곱근(sqrt), 평균(reduce_mean), 제곱(square) 함수를 통해 RMSE 계산
  return tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred)))

# Variable 초기화
# 잠재요인의 수를 200으로 지정한다.
K = 200
# 전체평균을 계산한다.
mu = ratings_train.rating.mean()
# 사용자 아이디와 영화 아이디의 최대값을 구한다.
# +1를 더해주는 이유는 나중에 bias term의 크기 1를 추가로 고려한 것이다.
M = ratings.user_id.max() + 1
N = ratings.movie_id.max() + 1

########################################################################
# Keras model
# 아래 부분은 앞에서와 동일하게 사용자와 아이템 데이터를 embedding을 통해
# 각각 K개의 노드를 갖는 layer로 변환하고
# 사용자 bias와 아이템 bias를 1개의 노드를 갖는 layer로 변환한다.
user = Input(shape=(1,))
item = Input(shape=(1,))
P_embedding = Embedding(M,K,embeddings_regularizer=l2())(user)
Q_embedding = Embedding(N,K,embeddings_regularizer=l2())(item)

user_bias = Embedding(M,1,embeddings_regularizer=l2())(user)
item_bias = Embedding(N,1,embeddings_regularizer=l2())(item)


P_embedding = Flatten()(P_embedding)
Q_embedding = Flatten()(Q_embedding)
user_bias = Flatten()(user_bias)
item_bias = Flatten()(item_bias)

R = Concatenate()([P_embedding,Q_embedding,user_bias,item_bias])

R = Dense(2048)(R)
R = Activation('linear')(R)

R = Dense(256)(R)
R = Activation('linear')(R)

R = Dense(1)(R)

model = Model(inputs=[user,item],outputs=R)

model.compile(
    loss=RMSE,
    optimizer=SGD(),
    metrics=[RMSE]
)

model.summary()


# Model fitting
# 모델 입력에 필요한 데이터 정리
train_user_ids = ratings_train.user_id.values
train_movie_ids = ratings_train.movie_id.values
train_ratings = ratings_train.rating.values

test_user_ids = ratings_test.user_id.values
test_movie_ids = ratings_test.movie_id.values
test_ratings = ratings_test.rating.values

result = model.fit(
    x = [train_user_ids,train_movie_ids],
    y = train_ratings - mu,
    epochs= 65,
    batch_size=512,
    validation_data=(
        [test_user_ids,test_movie_ids],
        test_ratings - mu
    )
)

# Plot RMSE
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
plt.plot(result.history['RMSE'],label="Train RMSE")
plt.plot(result.history['val_RMSE'],label='Test RMSE')
plt.legend()
plt.show()
#세번째 결과에 대한 코드
# 6.4 딥러닝 모델에 변수 추가하기


# csv 파일에서 불러오기
import pandas as pd

# train set과 test set을 나누기 위한 라이브러리
from sklearn.model_selection import train_test_split

# 필요한 tensorflow모듈들을 가져온다.
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input,Embedding,Dot,Add,Flatten
from tensorflow.keras.regularizers import l2
from tensorflow.keras.optimizers import SGD,Adamax
from tensorflow.keras.layers import Dense,Concatenate,Activation

# Defining RMSE measure
# y_true, y_pred은 신경망에서 실제값, 예측값을 나타내는 Tensorflow/Keras 표준 변수이다.
def RMSE(y_true, y_pred):
  # Tensorflow의 math 클래스에 미리 정의된
  # 제곱근(sqrt), 평균(reduce_mean), 제곱(square) 함수를 통해 RMSE 계산
  return tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred)))

r_cols = ['user_id','movie_id','rating','timestamp']
ratings = pd.read_csv('drive/MyDrive/RecoSys/Data/u.data',
                      names=r_cols,
                      sep='\t',
                      encoding='latin-1')

ratings_train,ratings_test = train_test_split(ratings,
                                              test_size=0.2,
                                              shuffle=True,
                                              random_state=2021)


# 사용자(user) 데이터 가져오기
u_cols = ['user_id','age','sex','occupation','zip_code']
users = pd.read_csv('drive/MyDrive/RecoSys/Data/u.user',
                      names=u_cols,
                      sep='|',
                      encoding='latin-1')
# 사용자 ID와 직업(occupation)만 남긴다.
users = users[['user_id','occupation']]


occupation = {}
def convert_occ(x):
  if x in occupation:
    return occupation[x]
  else:
    occupation[x] = len(occupation)
    return occupation[x]

users['occupation'] = users['occupation'].apply(convert_occ)

L = len(occupation)

train_occ = pd.merge(ratings_train,users,on='user_id')['occupation']
test_occ = pd.merge(ratings_test,users,on='user_id')['occupation']


K = 200
mu = ratings_train.rating.mean()


M = ratings.user_id.max() + 1
N = ratings.movie_id.max() + 1

user = Input(shape=(1,))
item = Input(shape=(1,))

P_embedding = Embedding(M,K,embeddings_regularizer=l2())(user)
Q_embedding = Embedding(N,K,embeddings_regularizer=l2())(item)

user_bias = Embedding(M,1,embeddings_regularizer=l2())(user)
item_bias = Embedding(N,1,embeddings_regularizer=l2())(item)

P_embedding = Flatten()(P_embedding)
Q_embedding = Flatten()(Q_embedding)

user_bias = Flatten()(user_bias)
item_bias = Flatten()(item_bias)

occ = Input(shape=(1,))
OCC_embedding = Embedding(L,3,embeddings_regularizer=l2())(occ)
OCC_layer = Flatten()(OCC_embedding)

R = Concatenate()([P_embedding,Q_embedding,user_bias,item_bias,OCC_layer])

R = Dense(2048)(R)
R = Activation('linear')(R)
R = Dense(256)(R)
R = Activation('linear')(R)
R = Dense(1)(R)

model = Model(inputs=[user,item,occ],outputs=R)

model.compile(
    loss=RMSE,
    optimizer=SGD(),
    metrics=[RMSE]
)

model.summary()

# Model fitting
train_user_ids = ratings_train.user_id.values
train_movie_ids = ratings_train.movie_id.values
train_ratings = ratings_train.rating.values
train_occs = train_occ.values

test_user_ids = ratings_test.user_id.values
test_movie_ids = ratings_test.movie_id.values
test_ratings = ratings_test.rating.values
test_occs = test_occ.values

result = model.fit(
    x = [train_user_ids,train_movie_ids,train_occs],
    y = train_ratings - mu,
    epochs = 65,
    batch_size=512,
    validation_data = (
        [test_user_ids,test_movie_ids,test_occs],
        test_ratings - mu
    )
)


# Plot RMSE
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
plt.plot(result.history['RMSE'],label="Train RMSE")
plt.plot(result.history['val_RMSE'],label='Test RMSE')
plt.legend()
plt.show()

위 수행 결과가 나오는 코드입니다.

6장.ipynb 코드 그대로 사용했습니다.

데이터 파일은 강의에서 안내한 경로에서 다운받은, u.data, u.user 파일 그대로 사용했습니다!

 

학습 진행 중 출력 수치 캡쳐입니다.

image.png



***제공 코드를 그대로 사용 했습니다. 약간의 수정한 부분이 있다면,

그래프 시각화 부분에서

학습 결과에서 키값이 소문자로 찍혀서, 대문자로 인식이 안되어 소문자로 수정했습니다.

plt.plot(result.history['RMSE'],label="Train RMSE") plt.plot(result.history['val_RMSE'],label='Test RMSE')

 

plt.plot(result.history['rmse'],label="Train RMSE") plt.plot(result.history['val_rmse'],label='Test RMSE')

 

 

 

거친코딩님의 프로필 이미지
거친코딩
지식공유자

안녕하세요.

저도 다시 코드 결과를 돌려보니,

학습자님과 동일한 결과가 발생합니다.

이는 최근 TensorFlow나 Keras 라이브러리의 버전이 변경되면서, 내부의 초기 weight 설정 방식, 최적화 함수의 기본 learning rate, 정규화의 기본 강도 등이 바뀐 데에 기인할 수 있습니다.

특히, SGD 옵티마이저나 Embedding 레이어의 초기화 전략은 버전에 따라 수렴 속도나 안정성에 상당한 차이를 만들 수 있어요. 예전에는 잘 작동했던 코드라도, 라이브러리 업데이트로 인해 수렴하지 않거나, 성능이 오히려 퇴화하는 경우가 실제로 발생합니다.

이런 현상은 머신러닝 모델 개발 시 매우 일반적인 경우라,

학습에 대한 플로우정도만 고려해주시면 좋을 것 같습니다.

감사합니다.

part-spt님의 프로필 이미지
part-spt
질문자

알겠습니다. 답변 감사합니다.
라이브러리 버전별로, 내부 라이브러리 작동과 하이퍼 파라미터 등 큰 변화가 생길 수 있으니, 지속적으로 검토해봐야 한다는 내용으로 받아들이고, 말씀하신대로 학습 플로우 일단 이해해보도록 하겠습니다!

혹시 저 코드로 수행하시던 당시에

텐서플로와 케라스 라이브러리 버전을 기억하고 계시다면 알려주실수 있나요?

 

*추가로
강의 따라 실습 진행중에, 결과가 심히 다르게 나와 잘못한게 있나 여러번 체크하게 되었습니다. 다른 학습자들도 같은 케이스로 혼란스러울 수 있으니, 코멘트 정도 남겨주시면 좋을것 같습니다!

 

 

0

part-spt님의 프로필 이미지
part-spt
질문자

오늘 기준으로 질문 한지 12일이 경과된 상태인데, 답변 언제 받을 수 있을까요?

part-spt님의 프로필 이미지
part-spt

작성한 질문수

질문하기