Python {Article124}

ようこそ「Python」へ...

ディープラーニングでビットコイン(BTC)の価格を予測するには〔3〕LSTMモデルを作成する

ここでは6回に分けて仮想通貨ビットコイン(Bitcoin)の価格を予測する方法を解説します。 このシリーズでは、ディープラーニングのLSTM(Long Short Term Memory)モデルを使用してビットコインの価格を予測します。

第3回目では、ディープラーニングのLSTMモデルを作成して学習・検証する方法について解説します。 ここでは、LSTMモデルの入力層、中間層、出力層を追加して学習用(Train)データで学習させます。 更に、検証用(Test)データでモデルの予測精度も検証します。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

click image to zoom!
図A epochs=10
click image to zoom!
図B epochs=30
click image to zoom!
図C epochs=60
click image to zoom!
図D load_model()
click image to zoom!
図E model_summary()

LSTMモデルを作成して学習させたあと予測精度を検証する

  1. LSTMモデルを作成して入力層、中間層、出力層を追加したらコンパイルする

    Visual Studio Code (VS Code)を起動したら、 シリーズ第2回目の「記事(Article123)」で作成したプログラムファイル(*.py)を開いて行245-304をコピペして追加します。

    行251-254ではすでにLSTMモデルが作成されているかチェックしています。 LSTMモデルは「data/model/*.h5」フォルダに作成されます。 LSTMモデルのファイルは「dl_lstm({symbol})_model.h5」の名称で作成されます。 ビットコイン(BTC-USD)の場合「dl_lstm(BTC-USD)_model.h5」の名称で作成されます。

    LSTMモデルのファイルが保存されているときは、行293の「load_model()」を実行してロードします。

    行255-263ではLSTMモデルを生成して入力層、中間層、出力層を追加しています。 行255ではモデルのインスタンを生成しています。 行257ではモデルに入力層を追加しています。 引数「input_shape()」では学習用データ(Train)の形状(型)を指定しています。 複数の中間層があるときは「return_sequences=True」を追加して出力情報を次の層に引き継ぐ必要があります。 行250では「Dropout()」層を追加して過学習(overfitting)が発生するのを防いでいます。 行260-261では中間層を追加しています。 行263では出力層を追加しています。 「Dense()」の引数に「units=1」を指定しているので1個の予測値が出力されます。

    行265ではLSTMモデルをコンパイルしています。 引数には、optimizer='adam'、loss='mean_squared_error'を指定しています。 ここでは、Adam最適化アルゴリズムを使用します。 引数「loss='mean_squared_error'」の使い方については後述する記事で解説します。

    行267-274では学習データ(Train)を使用してLSTMモデルを学習させています。 同時に検証データ(Test)を使用して予測精度を検証させています。

    行279-287では、学習データと検証データの損失値をグラフに表示しています。 行290ではLSTMモデルをファイルに保存しています。

    * Article.py:
    #############################################################
    ### Part 3 : Build the LSTM model
    #############################################################
    
    ### Build the LSTM model
    
    model_path = f'data/model/dl_lstm({symbol})_model.h5'   # data/model/dl_lstm(BTC-USD)_model.h5
    isFile = os.path.isfile(model_path)
    
    if not isFile:
        model = Sequential()
    
        model.add(LSTM(units=128, activation='relu',return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2])))
        model.add(Dropout(0.2))
    
        model.add(LSTM(units=64, input_shape=(x_train.shape[1], x_train.shape[2])))
        model.add(Dropout(0.2))
     
        model.add(Dense(units=1))
    
        model.compile(optimizer='adam', loss='mean_squared_error')
    
        history = model.fit(
            x_train, y_train, 
            batch_size=32, 
            epochs=60, # 100, 60, 30, 10
            verbose=1, 
            shuffle=False, 
            validation_data=(x_test, y_test)
            ) 
      
        # print(f"{history.history['loss']=}")  
        # print(f"{history.history['val_loss']=}")
    
        plt.figure(figsize=(16,7))
        plt.plot(history.history['loss'], label='loss (train)')
        plt.plot(history.history['val_loss'], label='val_loss (test)')
        plt.legend()
        plt.title(f'{symbol} LSTM Loss vs Val_loss')
        plt.xlabel('Epochs')
        plt.ylabel('Loss')
        plt.legend(loc='best')    
        plt.show()          
    
        ### Save the model and architecture to single file
        model.save(model_path)
    else:
        ### Load the LSTM model
        model = load_model(model_path)
    # end of if not isFile:
    
    ### Print the model summary
    model.summary()
    
    ### Evaluate the model
    # scores = model.evaluate(x_train, y_train, verbose=0)
    # print(f"{model.metrics_names[0]} = {scores:.2%}") 
    
    
    # %%
    click image to zoom!
    図1-1
    行244-303のセルを選択したら[Ctrl + Enter]で実行します。 行276-274の「model.fit()」が実行されてモデルの学習を開始します。 ここでは引数に「epochs=60」を指定しているので60回学習します。 「インタラクティブ」ウィンドウには学習の途中経過が表示されています。

    「model.fit()」の引数に「validation_data=(x_test, y_test)」を指定しているので、 検証データ(テストデータ)の予測も同時に行います。

    「インタラクティブ」ウィンドウの途中経過に「loss:0.0097」と「val_loss: 0.0721」が表示されています。 「loss」は学習用データ(Train)に対する損失値です。 「val_loss」は検証用データ(Test)に対する損失値です。 損失値は「0~1」の数値で表示されます。 損失値が小さいほど予測精度が高いことを意味します。

    click image to zoom!
    図1-2
    ここでは「インタラクティブ」ウィンドウに「loss」の値(損失値)を表示しています。 ここに表示されているのは学習用データ(Train)に対する損失値です。 値が小さいほど予測精度が高いことを意味します。
    click image to zoom!
    図1-3
    ここでは「インタラクティブ」ウィンドウに「val_loss」の値(損失値)を表示しています。 ここに表示されているのは検証用データ(Test)に対する損失値です。 値が小さいほど予測精度が高いことを意味します。
  2. 学習用データ(Train)を使用して学習させたあと、検証用データ(Test)で予測精度を検証する

    ここでは、LSTMモデルの学習用データ(Train)に対する損失値(loss)と、 検証用データ(Test)に対する損失値(val_loss)をグラフに表示して検証します。

    click image to zoom!
    図2-1
    ここでは「epochs=10」のときの「loss」と「val_loss」の損失値をプロットしています。 この状態では損失値の変動が高いので「epochs」の数値(回数)を増やす必要があります。
    click image to zoom!
    図2-2
    ここでは「epochs=30」のときの「loss」と「val_loss」の損失値をプロットしています。 途中で損失値が高くなっていますが、 これは過学習(overfitting)が発生していることを意味します。 過学習が発生しているときは、「Dropout(0.2)」の引数の値を調整します。
    click image to zoom!
    図2-3
    ここでは「epochs=60」のときの「loss」と「val_loss」の損失値をプロットしています。 時間が経過するごとに損失値が小さくなっています。 これが理想的な状態です。
    click image to zoom!
    図2-4
    ここではLSTMのモデルから「Dropout()」層を削除して学習させています。 「epochs=60」ですが「win_size=60」に設定しています。 グラフから過学習(overfitting)が頻発しているのがわかります。
    click image to zoom!
    図2-5
    ここではLSTMのモデルに「Dropout()」層を追加して学習させています。 「epochs=60」ですが「win_size=60」に設定しています。 グラフから過学習(overfitting)がだいぶ解消されているのがわかります。
  3. LSTMモデルが既に作成されているときはモデルを保存ファイルからロードする

    ここでは、「load_model()」を実行してLSTMモデルの保存ファイルをロードします。 LSTMモデルを学習させたらそのモデルをファイルに保存することにより、 次回からはLSTMモデルのファイルをロードして直接ビットコインの価格を予測することができます。 これで、ビットコインの予測時間を大幅に短縮することができます。

    click image to zoom!
    図3-1
    ここでは「load_model()」を実行してビットコイン(BTC-USD)のモデルファイル「dl_lstm(BTC-USD)_model.h5」をロードしています。
    click image to zoom!
    図3-2
    ここでは「model.summary()」の実行結果を「インタラクティブ」ウィンドウに表示しています。