예제
# 인공신경망을 이용한 추천 시스템
# - 순차형(Sequential) 신경망 생성법
# - 함수형(Functional) 신경망 생성법
# - 지금까지 나온 추천 방식 중에서 가장 좋은 성능
# - Regression 방식으로 분석가능
# - 영화의 평점 정보(userid, movieid, rating)
# - 이용자는 영화에 대한 취향이 모두 다르다
# - 영화는 다양한 장르가 혼합되어 있다
# - 이용자는 자신의 취향에 맞는 영화에 높은 rating을 제시함
# - 어떤 이용자에게 어떤 장르의 영화를 추천할 것인가?
# __call__() 함수를 가진 클래스는 파이썬 함수 callable(클래스)를 사용하면 True를 반환한다
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Embedding, Input
input = Input(shape=(1,))
# 함수형 신경망 생성법
hidden1 = Dense(2, activation='relu')(input) # Dense(2, activation='relu')__call__()
hidden2 = Dense(2, activation='relu')(hidden1)
# callable.object
callable(Dense) # __call__ 함수가 있으면 True, 없으면 False
# Using Functional API
from keras.models import Sequential
from keras.layers import *
model = Sequential()
model.add(Input(shape=(3,))) # Input tensor
model.add(Dense(4)) # hidden layer 1
model.add(Dense(units=4)) # hidden layer 2
model.add(Dense(units=1)) # output layer
# Using Sequential API
from keras.models import Model
from keras.layers import *
inputs = Input(shape=(3,)) # input tensor
hidden1 = Dense(units=4)(inputs) # hidden layer 1
hidden2 = Dense(units=4)(hidden1) # hidden layer 2
outputs = Dense(units=1)(hidden2) # hidden layer 3
# define the model's start and end points
model = Model([inputs,input2], outputs) # 입출력부를 리스트(다수개)로 설정 가능
# numpy.argmax() : 큰 값의 인덱스
# numpy.argsort() : 인덱스 정렬
import numpy as np
np.random.seed(0)
arr = np.random.randint(1, 10, 5) # array([6, 1, 4, 4, 8])
arr.argmax() # 4
arr # array([6, 1, 4, 4, 8])
arr.argsort() # array([1, 2, 3, 0, 4], dtype=int64), 오름차순 인덱스 정렬
-arr # array([-6, -1, -4, -4, -8])
(-arr).argsort() # array([4, 0, 2, 3, 1], dtype=int64), 내림차순 인덱스 정렬
예제2
import pandas as pd
df = pd.read_csv('ratings.csv')
df = df[['userId', 'movieId', 'rating']]
from sklearn.model_selection import train_test_split
Xtrain, Xtest = train_test_split(df, test_size=.2, random_state=1)
Xtrain.shape # (80668, 3)
Xtest.shape # (20168, 3)
df['userId'].nunique() # 610, 중복안되는 행의 갯수
max(df['userId']) # 610, 가장 큰 값
size_of_userId = len(df['userId'].unique()) # 610
df['movieId'].nunique() # 9724
max(df['movieId']) # 193609
size_of_movieId = max(df['movieId']) # 193609
import numpy as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers import Flatten, Embedding, Dense, Concatenate
# user
input_user = keras.Input(shape=(1,))
embedding_user = layers.Embedding(size_of_userId+1, 20)(input_user)
embedding_user_out = layers.Flatten()(embedding_user) # 1차원 배열화
# movie
input_movie = keras.Input(shape=(1,))
embedding_movie = layers.Embedding(size_of_movieId+1, 20)(input_movie)
embedding_movie_out = layers.Flatten()(embedding_movie) # 1차원 배열화
concat_layer = Concatenate()([embedding_user_out, embedding_movie_out])
fc1 = Dense(128, activation='relu')(concat_layer)
fc2 = Dense(32, activation='relu')(fc1)
output = Dense(1)(fc2)
model = keras.Model([input_user, input_movie], output)
model.summary()
model.compile(loss='mse', optimizer='adam') # mean sequare error : 에러 제곱 평균
hist = model.fit(
[Xtrain['userId'],Xtrain['movieId']],
Xtrain['rating'],
batch_size=64,
epochs=5,
verbose=1,
validation_data=([Xtest['userId'], Xtest['movieId']],Xtest['rating']) # 검증 데이터
)
hist.history.keys() # dict_keys(['loss', 'val_loss'])
loss = hist.history['loss']
val_loss = hist.history['val_loss']
import matplotlib.pyplot as plt
plt.figure(figsize=(5,2))
plt.plot(loss,'r--',label='loss')
plt.plot(val_loss,'y--',label='val_loss')
plt.xlabel('Epoch')
plt.ylabel('Error')
plt.legend()
plt.show()
model.evaluate([Xtest['userId'],Xtest['movieId']],Xtest['rating']) # 0.7559361457824707
array_of_all_unique_movies = df['movieId'].unique()
#model.predict(이용자, 모든 영화)
user1 = [1 for i in array_of_all_unique_movies]
user1[:5]
user1 = np.array(user1)
user1.shape # (9724,)
pred = model.predict([user1, array_of_all_unique_movies])
pred[:5]
array([[4.9513497], [4.34624 ], [4.86894 ], [4.941231 ], [5.064878 ]], dtype=float32)
pred2 = pred.flatten()
pred2.shape # (9724,)
(-pred2).argsort() # array([3457, 4750, 3544, ..., 5376, 593, 784], dtype=int64), 1위 평점 3457번 영화
idx = (-pred2).argsort()[:10]
# 영화 평점 Top 10
idx # array([3457, 4750, 3544, 2872, 5281, 2993, 7204, 2158, 6984, 5218], dtype=int64)
# 학습모델 저장
model.save('movie_recommend_model.keras')
# 학습모델 불러오기
import tensorflow.keras
re_model = keras.models.load_model('movie_recommend_model.keras')
# 재학습
re_model.fit()