Python {Article123}

ようこそ「Python」へ...

ディープラーニングでビットコイン(BTC)の価格を予測するには〔2〕Train/Testデータを準備する

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

第2回目では、Yahoo! Financeからダウンロードしたビットコインの価格データをディープラーニングで利用できるように準備します。 ここではYahoo! Financeからダウンロードしたビットコインのデータを学習用(Train)とテスト用(Test)に分割します。 さらに、これらの分割したデータ(Train/Test)を正規化してnumpyの配列に変換する処理も行います。

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

click image to zoom!
図A df.filter()
click image to zoom!
図B df.values
click image to zoom!
図C plot train/test
click image to zoom!
図D split train/test
click image to zoom!
図E x_train
click image to zoom!
図F y_train

ビットコインの価格データを学習用とテスト用に分割して正規化&numpyの配列に変換する

  1. ビットコインの価格データが格納されているPandasのDataFrameから終値(close)の列(カラム)のみ取り出す

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

    行153ではDataFrameのfilterメソッドを実行してDataFrameから「close」のカラムのみ抽出してDataFrameを変数「close_df」に格納しています。 行158ではDataFrameのvalues属性(プロパティ)から「close」の値を取得してnumpy配列に変換して変数「close_ndarr」に格納しています。 変数名の「ndarr」は「N-dimension Array」の略称です。変数名に「*_df, *_list, *_ndarr」のようにデータ型を付加すると保守が容易になります。

    行166-171では、変数「close_ndarr」に格納されている終値(close)を学習用(Train)とテスト用(Test)に分割しています。 テスト用には60件のデータが格納され、学習用には残りのデータが格納されます。 行180-187では学習用とテスト用データの終値(close)を線グラフに表示しています。

    行193-194では学習用のデータを「0~1」の数値に正規化しています。 行199-206では学習用のデータを入力ウィンドウのサイズ「5」でスライスして結合しています。 変数「x_train」には1番目から5番目のデータが格納され、変数「y_train」には6番目のデータが格納されます。 この処理を変数「scaled_train_ndarr」の全てのデータに対して行います。 詳細は後述する解説を参照してください。

    行209-212では変数「x_tran, y_tran」のデータをnumpy配列に変換して、更に3次元の配列に変換しています。

    行222-238ではテスト用データに対して同様の処理を行っています。

    TIP1: ここでは解説しやすいように「prediction_days」に「60」を設定していますが、 本番では「8:2」くらいの比率になるようにしてください。
    prediction_days = 60
        ⇓ ⇓
    prediction_days = int(close_ndarr.shape[0] * 0.2)
    TIP2: ここでは解説しやすいように「win_size」に「5」を設定していますが、 本番では「60」くらいのサイズを設定してください。
    win_size = 5
        ⇓ ⇓
    win_size = 60


    * Article.py:
    #%%
    
    #############################################################
    ### Part 2 : Prepare Train / Test data 
    #############################################################
    
    ### Create a new dataframe with only the 'close' column
    close_df = df.filter(['close'])
    # print(type(close_df))  
    # print(f"{close_df=}")
    
    ### Convert filtered dataframe to a numpy array
    close_ndarr = close_df.values   # N-dimension array : ndarray
    # print(close_ndarr.shape)    
    # print(close_ndarr)
    
    
    # %%
    
    ### Get the number of rows to train the model on
    prediction_days = 60    
    train_len = len(close_ndarr) - prediction_days
    
    ### Split train and test 
    train_ndarr = close_ndarr[0:train_len] 
    test_ndarr = close_ndarr[train_len:]
    # print(f"{train_len=}")              
    # print(f"{train_ndarr.shape}")       
    # print(f"{test_ndarr.shape}")        
    
    
    # %%
    
    ### Plot train / test data
    plt.figure(figsize=(13,7))
    plt.plot(train_ndarr, label='Train', color='green')
    plt.plot(test_ndarr, label='Test', color='red')
    plt.title(f'{symbol} Train / Test Data', fontsize=18)
    plt.xlabel('Time')
    plt.ylabel('Close Price USD ($)')
    plt.legend(['Train','Test'], loc='best')
    plt.show()
    
    
    # %%
    
    ### Scale the train data & reshape  
    scaler = MinMaxScaler(feature_range=(0,1))  
    scaled_train_ndarr = scaler.fit_transform(train_ndarr)
    # print(scaled_train_ndarr.shape)    
    # print(f"{scaled_train_ndarr=}")
    
    ### Split the data into x_train and y_train data sets
    x_train = []    
    y_train = []    
    
    win_size = 5     # time series sequence length
    
    for i in range(win_size, len(scaled_train_ndarr)):          # train_data (scaled data)    
        x_train.append(scaled_train_ndarr[i - win_size:i, 0])   # slice ndarray [start:stop,step]
        y_train.append(scaled_train_ndarr[i, 0])                # slice ndarray [start,step]     
    
    ### Convert the x_train and y_train to numpy arrays
    x_train, y_train = np.array(x_train), np.array(y_train)
    
    ### Reshape the train data (scaled data)
    x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1)) 
    # print(f"{x_train.shape=}")     
    # print(f"{x_train=}")
    
    
    # %%
    
    ### Scale the test data & reshape
    
    # scaler = MinMaxScaler(feature_range=(0,1))  
    scaled_test_ndarr = scaler.fit_transform(test_ndarr)
    # print(scaled_test_ndarr.shape)   
    # print(f"{scaled_test_ndarr=}")  
    
    ### Split the test data into x_test and y_test data sets
    x_test = []    
    y_test = []    
    
    for i in range(win_size, len(scaled_test_ndarr)):       # test_data (scaled data)    
        x_test.append(scaled_test_ndarr[i - win_size:i, 0]) # slice ndarray [start:stop,step]
        y_test.append(scaled_test_ndarr[i, 0])              # slice ndarray [start,step]   
    
    ### Convert the x_test and y_test to numpy arrays
    x_test, y_test = np.array(x_test), np.array(y_test)
    
    ### Reshape the test data (scaled data)
    x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))  
    # print(f"{x_test.shape=}")     
    # print(f"{x_test=}")  
    
    
    # %%
    click image to zoom!
    図1-1
    第1回目の「記事(Article122)」をまだ実行していないときは、 事前に実行しておいてください。

    ソースコードの行147-162の任意の行をクリックしてセルを選択します。 セルを選択した状態で[Ctrl + Enter]を押して実行します。 行153ではDataFrameのfilter()メソッドでDataFrameから「close]のカラムを抽出して変数「close_df」に格納します。 close_dfにはDataFrameが格納されます。このDataFrameはインデックスとカラム「close」から構成されています。 「インタラクティブ」ウィンドウに「close_df.shape」を入力したら[Shift + Enter]で実行します。 「(3054, 1)」が表示されているので3054件のデータが格納されています。

    次に「インタラクティブ」ウィンドウに「close_df」を入力したら[Shift + Enter]で実行します。 「インタラクティブ」ウィンドウには「close_df」のDataFrameの先頭と最後のデータが5件づつ表示されています。

    click image to zoom!
    図1-2
    行158ではDataFrameのvalues属性(プロパティ)から「close」のカラムの全ての値を取得して変数「close_ndarr」に格納します。 この変数には「close:終値」の値が「N-dimension array」として格納されます。 変数名「close_ndarr」の「ndarr」は「N-dimension array」の略称です。

    「インタラクティブ」ウィンドウに「close_ndarr」を入力したら[Shift + Enter]で実行します。 「(3054, 1)」が表示されているので、3054件のデータが格納されています。 同様の手順で「close_ndarr」を入力したら実行します。 「インタラクティブ」ウィンドウに配列変数に格納されている終値「close」の値が表示されます。
  2. ビットコインの終値(close)が格納されている配列データを学習用(Train)とテスト用(Test)に分割する

    行164-176の任意の行をクリックしてセルを選択したら[Ctrl + Enter]で実行します。

    click image to zoom!
    図2-1
    「インタラクティブ」ウィンドウから「train_len」を入力して実行します。 変数「train_len」には「2994」が設定されているので、 変数「close_ndarr」に格納されているデータを学習用に2994件とテスト用に60件に分割しています。

    同様に「train_ndarr.shape」と「test_ndarr.shape」を入力して実行します。 変数「train_ndarr」には2994件のデータが格納されています。 変数「test_ndarr」には60件のデータが格納されています。

    click image to zoom!
    図2-2
    行178-199のセルを選択したら実行します。 「インタラクティブ」ウィンドウにグラフが表示されます。 ここでは、変数「train_ndarr, test_ndarr」の終値を線グラフで表示しています。 このグラフでは、学習データとテストデータの終値がどのように推移しているかがわかります。
  3. 学習用(Train)のデータを正規化して3次元の配列に格納する

    行191-216をクリックしてセルを選択したら実行します。 行193-194ではMinMaxScalerで変数「train_ndarr」に格納されている終値(close)を「0~1」の数値に正規化しています。 行199-206では変数「scaled_train_ndarr」に格納されている終値(close)を「win_size」に設定されているウィンドウサイズ(5)でスライスしています。

    株価や仮想通貨のような時系列データを「x_train, y_train」、「x_test, y_text」に分割するときは、 過去の「n日間」のデータを1つのデータポイント(※)として結合します。 たとえば、「n=5」ならば、過去5日分のデータを1つのデータポイントとして結合します。

    わかりやすいように具体的な数字を使って説明します。 list型の変数「train_list」には「1~10」の数値が格納されています。 入力ウィンドウ(データポイント)のサイズとして「3」を使用するものとします。 この場合、変数「x_train」には[1,2,3],[2,3,4],[3,4,5],...が格納されます。 そして、変数「y_train」には[4],[5],[6],...が格納されます。

    ※データポイントのことを、入力シーケンス(input sequence)、入力ウィンドウ(input window)、 入力時系列(input time series)などと呼ぶこともあります。
    list型の変数に格納されている学習(Train)データを「x_train」と「y_train」に分割する。
    train_list =
    [1,2,3,4,5,6,7,8,9,10]
    ========================
    x_train y_train
    [1,2,3] [4]
    [2,3,4] [5]
    [3,4,5] [6]
    :::::::::::
    入力ウィンドウのサイズが「3」のときは、
    [1,2,3], [2,3.4], [3,4,5],...がx_trainに格納される。
    そして、[4],[5],[6],...がy_trainに格納される。
    
    click image to zoom!
    図3-1
    ここでは変数「scaled_train_ndarr」のshapeと内容を「インタラクティブ」ウィンドウに表示しています。 ビットコインの終値(close)が0~1の間に正規化されています。

    click image to zoom!
    図3-2
    ここでは変数「x_train」のshapeと内容を「インタラクティブ」ウィンドウに表示しています。 変数「scaled_train_ndarr」に格納されている終値(close)が変数「win_size」に設定したウィンドウサイズ(5)でスライスされて格納されています。 終値(0.0032753)に注目するとシフトされて格納されているのが確認できます。

    click image to zoom!
    図3-3
    ここでは変数「y_train」のshapeと内容を「インタラクティブ」ウィンドウに表示しています。 変数「win_size」にはウィンドウサイズとして「5」が設定されているので6番目の終値がスライスされて変数「y_train」に格納されます。 変数「scaled_train_ndarr」に格納されている6番目の終値(0.00332473)が変数「y_train」の先頭に格納されているのが確認できます。
  4. テスト用(Test)のデータを正規化して3次元の配列に格納する

    ここでは学習用(Train)のデータと同じような処理をテスト用(Test)データに対して行います。 行218-242のセルを選択したら[Ctrl + Enter]で実行します。

    click image to zoom!
    図4-1
    「インタラクティブ」ウィンドウに「scaled_test_ndarr」を入力したら[Shift + Enter]で実行します。 「(60, 1)」が表示されます。 同様の手順で「scaled_test_ndarr」を入力して実行します。 変数の内容が表示されます。 この変数には60件の終値(close)の価格が「0~1」に正規化されて格納されています。

    click image to zoom!
    図4-2
    「インタラクティブ」ウィンドウに「x_test.shape」を入力して実行します。 「(55, 5, 1)」が表示されます。 同様の手順で「x_test」を入力して実行します。 この変数にはビットコインの終値(close)が「0~1」に正規化されて格納されています。 さらに、「x_test」には終値(close)がウィンドウサイズの5日単位でスライスされて格納されています。 終値(0.12627102)に注目するとシフトされて格納されているのが確認できます。

    click image to zoom!
    図4-3
    ここでは変数「y_test」に対して「shape」と「内容」を表示しています。 この変数にはビットコインの終値(close)が「0~1」に正規化されて格納されています。 さらに、変数「scaled_test_ndarr」の6番目の終値(0.10012460)が変数「y_test」の先頭に格納されているのが確認できます。