LSTM 시계열 예측 코드 - LSTM sigyeyeol yecheug kodeu

딥러닝과 금융이론

5. Keras LSTM 유형 정리 (5/5) : 시계열 데이터 예측 예시

1. 단층-단방향 & many-to-one 유형
2. 단층-단방향 & many-to-many 유형
3. 단층-양방향 & many-to-one/many-to-many 유형
4. 2층-단방향/양방향 & many-to-one 유형 

시계열 예측 예시 : 단방향-2층 & many-to-one 유형


이번 시간에는 이전 포스트에서 살펴본 단방향-2층 & many-to-one 구조의 LSTM으로 시계열 데이터를 예측해 본다. 시계열 데이터는 sine 함수로 주기적인 패턴을 만들고 노이즈를 삽입해서 100개를 만들었다. 제대로 학습이 된다면 주기적 패턴을 검출하고 노이즈는 제거하는 방향으로 예측할 것이다.

 from keras.models import Model
 from keras.layers import Input, Dense, LSTM, Bidirectional
 from keras import backend as K
 import numpy as np
 import matplotlib.pyplot as plt

 # 학습 데이터를 생성한다.
 # ex: data = [1,2,3,4,5,6,7,8,9,10]가 주어졌을 때 generateX(data, 5)를 실행하면
 # 아래와 같은 학습데이터 변환한다.
 #
 # x                      y
 # ---------              -
 # 1,2,3,4,5              6
 # 2,3,4,5,6              7
 # 3,4,5,6,7              8
 # ...
 def generateX(a, n):
     x_train = []
     y_train = []
     for i in range(len(a)):
         x = a[i:(i + n)]
         if (i + n) < len(a):
             x_train.append(x)
             y_train.append(a[i + n])
         else:
             break
     return np.array(x_train), np.array(y_train)

 # Sine 함수에 노이즈를 섞은 데이터로 학습 데이터 100개를 생성한다
 data = np.sin(2 * np.pi * 0.03 * np.arange(0, 100)) + np.random.random(100)
 x, y = generateX(data, 10)
 x = x.reshape(-1,10,1)
 y = y.reshape(-1,1)

 # 학습용 데이터와 시험용 데이터
 x_train = x[:70, :, :]
 y_train = y[:70, :]
 x_test = x[70:, :, :]
 y_test = y[70:, :]

 # 2층-양방항 구조의 LSTM 모델을 생성한다.
 K.clear_session()     # 모델 생성전에 tensorflow의 graph 영역을 clear한다.
 xInput = Input(batch_shape=(None, x_train.shape[1], x_train.shape[2]))
 xLstm_1 = LSTM(10, return_sequences = True)(xInput)
 xLstm_2 = Bidirectional(LSTM(10))(xLstm_1)
 xOutput = Dense(1)(xLstm_2)


 model = Model(xInput, xOutput)
 model.compile(loss='mse', optimizer='adam')

 # 학습
 model.fit(x_train, y_train, epochs=500, batch_size=20,verbose=1)

 # 예측
 y_hat = model.predict(x_test, batch_size=1)

 # 예측 결과 시각화
 a_axis = np.arange(0, len(y_train))
 b_axis = np.arange(len(y_train), len(y_train) + len(y_hat))

 plt.figure(figsize=(10,6))
 plt.plot(a_axis, y_train.reshape(70,), 'o-')
 plt.plot(b_axis, y_hat.reshape(20,), 'o-', color='red', label='Predicted')
 plt.plot(b_axis, y_test.reshape(20,), 'o-', color='green', alpha=0.2, label='Actual')
 plt.legend()
 plt.show()

학습 진행 과정: 

Epoch 496/500 

70/70 [==============================] - 0s 1ms/step - loss: 0.1044
Epoch 497/500
70/70 [==============================] - 0s 1ms/step - loss: 0.1028
Epoch 498/500
70/70 [==============================] - 0s 1ms/step - loss: 0.1027
Epoch 499/500
70/70 [==============================] - 0s 1ms/step - loss: 0.1024
Epoch 500/500
70/70 [==============================] - 0s 1ms/step - loss: 0.1022

학습 결과:
 

학습 결과를 이용하여 시험 데이터를 예측해 본 결과는 아래와 같다. 예측 구간의 원 시계열 (y_test)을 빨간색 곡선 (y_hat)으로 예측했다. 육안으로 봐도 그런대로 예측이 잘 된 것 같다. 예측 능력을 수치화해서 성능을 표시하려면 y_test와 y_hat으로 MSE (mean-square-err)나, (수정된) 결정계수 혹은 상관계수 등으로 표시해 볼 수 있다.

참고로 시험 데이터의 끝 부분에서 다음 시계열을 예측하고, 예측 값을 다시 시험 데이터에 추가하고, 또 다음 시계열을 예측해 보기를 반복하면, 과거의 주기적인 패턴을 검출하고, 노이즈를 제거하는지 확인해볼 수 있을 것이다. 여기까지 5편의 포스트를 통해 Keras LSTM의 여러 유형의 사용 방법을 정리해 봤다.

업데이트 (2020-10-31) : 예측값으로 그 다음값을 예측하는 코드는 https://blog.naver.com/chunjein/222131850058 참조.