-
머신 러닝으로 금 시세를 예측해 보자 feat. LSTM모델 구축 2020. 4. 13. 14:44
1. LSTM에 대한 간략한 설명
2. 데이터 전처리
3. 모델 구축
4. 모델 평가
1. LSTM에 대한 간략한 설명
LSTM은 뉴럴 네트워크의 한 종류로 기존의 음성, 글 등과 같이 순차적인 데이터(Sequence)를 다루기 위한 RNN 알고리즘을 바탕으로 하고 있다. 하지만 RNN는 Sequence의 길이가 길어지면, 다소 떨어진 데이터의 정보가 사라진다는 단점이 있다. 이를 보완하기 위해 나온 알고리즘이 LSTM이다. 딥러닝을 기반으로 하고 있어 앞서 설명한 ARIMA나 prophet 보다 복잡한 패턴을 찾아내는 것이 가능하다.
자세한 설명은 훌룡한 설명을 하고 있는 많은 사이트들이 있기 때문에 그 링크를 남긴다.
https://brunch.co.kr/@chris-song/9
2. 데이터 전처리
sklearn의 train_test_split로 train과 test로 데이터를 나눈다.
from sklearn.model_selection import train_test_split train, test = train_test_split(gold_price_series, train_size = 0.8, shuffle=False)
2016년 3월 까지를 학습 데이터로 사용하여, 2016년 3월부터 2020년 4월까지의 데이터로 모델 검증을 해보겠다.
sklearn의 MinMaxScaler를 사용하여 0~1로 데이터의 사이즈를 축소하도록 한다.
import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() scaler.fit(train) train_trans = scaler.transform(train) test_trans = scaler.transform(test)
pd.DataFrame(train_trans, index=train.index, columns=train.columns)
밑의 코드로 일정한 기간의 데이터(본 포스팅의 예시에는 20일을 하나의 input단위로 놓겠다)를 설명변수(x)로 놓고 그 바로 다음날()을 종속변수(y)로 놓도록 하겠다.
def step_split(sequence, n_steps, n_features, n_predict_steps, test_set=False): sequence = np.array(data).reshape(-1, n_features) X, y = list(), list() if test_set: start_n = len(sequence) % n_steps finish_n = len(sequence) - n_steps + 1 for i in range(start_n, finish_n): seq_x = sequence[i:i+n_steps] X.append(seq_x) X = np.array(X) X = X.reshape(X.shape[0], n_steps, n_features) else: start_n = (len(sequence) + n_predict_steps) % n_steps finish_n = len(sequence) - n_predict_steps - n_steps + 1 for i in range(start_n, finish_n): seq_x, seq_y = sequence[i:i+n_steps], sequence[i+n_steps:i+n_steps+n_predict_steps][:,0] X.append(seq_x) y.append(seq_y) X = np.array(X) y = np.array(y) X = X.reshape(X.shape[0], n_steps, n_features) y = y.reshape(y.shape[0], n_predict_steps) return X, y
n_steps에 하나의 input데이터의 기간의 길이를 정한다. 복수의 설명 변수를 사용하고 싶으면, n_features를 조정하고 복수의 날짜를 예측하고 싶으면 n_predict_steps를 조정하면 된다. 본 예시에서는 설명변수 1개, 바로 다음날 1일을 예측하도록 하겠다.
n_steps = 20 n_features = 1 n_predict_steps = 1 x_train, y_train = step_split(train_trans, n_steps,n_features, n_predict_steps) x_test, y_test = step_split(test_trans, n_steps,n_features, n_predict_steps)
변환된 최종 학습데이터는 하기와 같다. 하나의 열이 하나의 input 데이터가 된다.
pd.DataFrame(x_train.reshape(x_train.shape[1],x_train.shape[0]), index = [f'day{x+1}' for x in range(x_train.shape[1])], columns = [f'input_{x+1}' for x in range(x_train.shape[0])])
3. 모델 구축
필요한 package를 불러오고
import tensorflow as tf from tensorflow.keras import Sequential from tensorflow.keras.layers import Dense, LSTM, Bidirectional, Dropout from tensorflow.keras.preprocessing.sequence import pad_sequences
16층의 LSTM을 만들고, 마지막의 1가지 숫자를 예측하므로, Dense(1) 층을 넣어 가장 단순한 LSTM을 만들었다.
def create_model(stateful,batch_size, n_steps, n_features): model = Sequential() model.add(LSTM(16, batch_input_shape=(batch_size, n_steps, n_features), stateful=stateful )) model.add(Dense(1)) model.compile(loss='mse', optimizer='adam') return model batch_size = 1 epochs = 11 x, y = step_split(scaler.transform(gold_price_series), n_steps, n_features, n_predict_steps) y = scaler.inverse_transform(y) model_stateful = create_model(True, batch_size, n_steps, n_features) for i in range(epochs): print('Epoch', i + 1, '/', epochs) model_stateful.fit(x_train, y_train, batch_size=batch_size, epochs=1, verbose=1, shuffle=False, validation_data=(x_test, y_test) ) if i % 5 == 0: y_hat = model_stateful.predict(x, batch_size=batch_size) y_hat = scaler.inverse_transform(y_hat) plt.figure(figsize=(25, 10)) plt.plot(gold_price_series.index[:len(y_hat)],y[:len(y_hat)]) plt.plot(gold_price_series.index[:len(y_hat)],y_hat) plt.show()
4. 모델 평가
이전 포스팅의 ARIMA, Propeht 과 같이 다음 포스팅에서 비교 평가를 하겠다.
'모델 구축' 카테고리의 다른 글
머신 러닝으로 금 시세를 예측 해보자 feat. Prophet (0) 2020.04.01 머신 러닝으로 금 시세를 예측 해보자 feat. ARIMA (3) 2020.03.31