본문 바로가기
ML, DL, RL

[DL] SimpleRNN with Keras

by llHoYall 2020. 12. 5.

RNN(Recurrent Neural Network)은 자연어, 주가와 같은 순차 데이터를 모델링하는 데 사용되는 신경망 입니다.

Keras로 이 모델을 구현하는 방법에 대해 알아보겠습니다.

Built-in RNN Layers

Keras에는 다음 3가지의 모델이 내장되어 있습니다.

Input Dataset

간단한 시계열 데이터를 만들어 보겠습니다.

주가 같은 데이터를 사용하면 좋겠지만, 개념을 먼저 확실히 잡아보기 위해 주가와 비슷한 모양을 가지는 sin함수를 사용해서 데이터를 생성해 보겠습니다.

처음엔 단순화시켜 설명을 드리려고 단순히 sin함수만 사용을 했었는데, 너무 단순화되어서인지 완벽한 예측을 보여주길래 랜덤한 값으로 약간의 변화를 주었습니다.

import numpy as np

t = np.arange(0, 1000)
x = np.sin(0.02 * t) + np.random.rand(1000)
train, test = x[0:800], x[800:1000]

먼저 0~999까지의 1000개의 sin값을 생성하고, 각각 train dataset은 800개, test dataset은 200개로 나누었습니다.

 

이제 이 dataset을 학습을 위해 변형을 시켜줄 것입니다.

4개의 연속된 데이터를 묶어 5번째 데이터를 결과로 만들겠습니다.

다음을 보면 쉽게 이해하실 수 있을 것입니다.

# INPUT				OUTPUT
# sin(0) sin(1) sin(2) sin(3)	sin(4)
# sin(1) sin(2) sin(3) sin(4)	sin(5)
# sin(2) sin(3) sin(4) sin(5)	sin(6)
# ...

 

이것을 코드로 구현해보겠습니다.

def convert_to_matrix(data, step):
    x, y = [], []
    for i in range(len(data) - step):
        d = i + step  
        x.append(data[i:d])
        y.append(data[d])
    return np.array(x), np.array(y)

train = np.append(train, np.repeat(train[-1], 4))
test = np.append(test, np.repeat(test[-1], 4))

train_x, train_y = convert_to_matrix(train, 4)
test_x, test_y = convert_to_matrix(test, 4)

train_x = np.reshape(train_x, (train_x.shape[0], 1, train_x.shape[1]))
test_x = np.reshape(test_x, (test_x.shape[0], 1, test_x.shape[1]))

trainX는 (800, 1, 4)의 모양을 갖습니다.

즉, 800개의 세트가 1 x 4의 모양으로 입력이 됩니다.

trainY는 800개의 결과 값이 들어있습니다.

test는 200개씩 있다는 차이 빼고는 모두 동일합니다.

Model

이제 간단한 RNN 모델을 만들어 봅시다.

from keras.models import Sequential
from keras.layers import SimpleRNN, Dense

model = Sequential()
model.add(SimpleRNN(units=32, input_shape=(1, 4), activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam', metrics=['acc'])

SimpleRNN 입력 때문에 삽질을 좀 했는데, 입력 모양 부분을 꼭 넣어줘야 하더라고요.

원하는 모델을 만드실 때, 이 점 주의해주세요.

이젠 굳이 설명을 안해도 나머지는 다 아시겠죠?

각각의 layer마다 unit의 개수를 명시해 주었고, 할성화 함수로는 relu를 설정해주었습니다.

손실 함수로는 mse, 최적화 함수로는 adam을 설정해 주었고, 평가 지표로는 acc를 설정했습니다.

 

생성된 모델을 살펴보겠습니다.

model.summary()

# Layer (type)                 Output Shape              Param #   
# =================================================================
# simple_rnn (SimpleRNN)       (None, 32)                1184      
# _________________________________________________________________
# dense (Dense)                (None, 8)                 264       
# _________________________________________________________________
# dense_1 (Dense)              (None, 1)                 9         
# =================================================================
# Total params: 1,457
# Trainable params: 1,457
# Non-trainable params: 0

결과로 1개의 값이 튀어나오는군요.

Training

이제 학습을 시켜봅시다.

model.fit(train_x, train_y, epochs=100, batch_size=16)

16 덩어리로 나누어 100 epoch동안 학습을 시켰습니다.

 

학습은 엄청 빨리 되네요.

학습이 되어가는 과정을 그래프로 볼까요?

import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(history.history['loss'], label='loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(loc='best')
plt.show()

학습을 시작하자마자 순식간에 안정화가 되어가네요.

Evaluation

이제 학습된 모델을 평가해 봅시다.

test_loss, test_acc = model.evaluate(test_x, test_y)
print('loss: {:.4f}\nacc: {:.4f}'.format(test_loss, test_acc))
# loss: 0.1183
# acc: 0.0000

 

정확도는 왜 저럴까 모르겠지만, 손실은 상당히 적네요.

Prediction

이제 예측을 해볼까요?

test_predictions = model.predict(test_x)

for i in range(5):
    print(test_y[i], test_predictions[i])
# 0.38551802173851374 [0.20283031]
# -0.021098359361594488 [0.06128622]
# -0.036755569826498524 [-0.08885847]
# -0.08457433557120209 [0.23765944]
# 0.30249685570373663 [0.01381123]

plt.plot(test_y)
plt.plot(test_predictions)
plt.show()

 

처음 5개의 값을 뽑아 봤습니다.

숫자로 보니까 감이 잘 안오죠?

파란색이 실제 결과 값, 주황색이 우리 모델이 예측한 값입니다.

그래프로 보니까 상당히 잘 예측한 것을 보실 수 있죠? ^^

 

이제 남은 건, 모델을 씹고 뜯고 맛보고 즐기면서 갖고 놀아 보는 것이죠!

댓글