ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 머신 러닝으로 금 시세를 예측해 보자 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

     

    LSTM(RNN) 소개

    Recurrent Neural Network의 대표적인 LSTM 알고리즘 | 안녕하세요. 송호연입니다. 요즘.. 딥러닝에 푹 빠져있어서.. 퇴근후 RNN 공부할겸 아래 블로그 글을 한글로 번역하였습니다. 원 저작자, Google Brain의 Chris Olah의 허락을 받고 번역하였습니다. http://colah.github.io/posts/2015-08-Understanding-LSTMs/ RNN(Recurrent Neural

    brunch.co.kr

     

    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()

    1epoch 후의 fittig
    6 epoch 후의 fitting
    11 epoch 후의 fitting

     

    4. 모델 평가

    이전 포스팅의 ARIMA, Propeht 과 같이 다음 포스팅에서 비교 평가를 하겠다.

    댓글

Designed by Tistory.