ぷそさんのプログラミング研究所

機械学習モデルを自動で生成するautoMLで株価予測してみよう|Python

この記事でわかること
  • autoMLの実装方法(ソースコードつき)
  • autoMLでの株価予測の方法
目次

autoMLとは

autoMLとは,ニューラルネットワークの「層数」や「ノード数」などを自動で構築するフレームワークです。

pythonでは,autokerasというモジュールで出来ます。

その方法を株価予測を題材にしてまとめたいと思います!

autoMLによる株価予測の概要

予測は以下の流れで行います。

つまり,30日後の株価を予測する回帰モデルになります!

他の手法でも予測しているので,ぜひご覧ください!

あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶLightGBMの使い方 この記事でわかること LightGBMの実装方法(ソースコードつき) LightGBMでの株価予測の方法 【LightGBMによる株価予測の概要】 予測は以下の流れで行います。 つまり,...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶランダムフォレストの使い方 この記事でわかること ランダムフォレストの実装方法(ソースコードつき) ランダムフォレストでの株価予測の方法 【ランダムフォレストによる株価予測の概要】 予測は...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶロジスティック回帰の使い方 この記事でわかること ロジスティック回帰の実装方法(ソースコードつき) ロジスティック回帰での株価予測の方法 【ロジスティック回帰による株価予測の概要】 予測は...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶディープラーニングの使い方 この記事でわかること ディープニューラルネットワークの実装方法(ソースコードつき) ディープニューラルネットワークでの株価予測の方法 【による株価予測の概要】 ...

事前準備

まずは,環境についてです。

  • Python 3.10.4

必要なライブラリは以下のようになります。ない場合にはpipcondaで入れてください。

必要なライブラリ

  • pandas
  • numpy
  • tensorflow
  • autokeras
  • datetime
  • pandas_datareader

ライブラリのインポート

データを扱うのに必要なライブラリのインポートを行います。

import pandas as pd
import numpy as np
from datetime import datetime

株価情報の取得

主要な株価指数の取得

予測のための説明変数として,日経平均株価などを取得します。

今回は,日経225,S&P500,ナスダック総合を取得しています。

from pandas_datareader import data
marketData = ['NIKKEI225','SP500','NASDAQCOM']
df_market = data.DataReader(marketData,'fred','2014-01-01', '2023-1-31').asfreq("D")
df_market = df_market.fillna(method='ffill')
df_market = df_market.dropna(how='any')

3行目:df_market = data.DataReader…

指数を2014年1月1日から2023年1月31日まで取得しています。

4行目:df_market = df_market.fillna…

欠損値を埋めています。

5行目:df_market = df_market.dropna…

欠損値がある場所は削除しています。

株価取得の詳しい内容については以下をご覧ください。

あわせて読みたい
【コピペ可】Pythonで株価分析|株価データの取得 Pythonを使った株価分析の基本を解説します! 【株価データを取得する】 株価データを取得するにはpandas-datareaderというライブラリを使用します。 このライブラリで...

主要な株価指数の前処理

株価指数そのままでは学習しにくいので,移動平均との乖離を計算します。

ここは精度に関係するので試行錯誤する必要があります。

# 各指数の移動平均との乖離率を算出する
for index_name in df_market.columns:
    for i in [5,10,30,60,90,120]:
        df_market[index_name + "_" + str(i) + "days_diffrol"] =\
        (df_market[index_name].rolling(i).mean() - df_market[index_name]) / df_market[index_name].rolling(i).mean()
    
    # 生データは削除する
    df_market = df_market.drop(columns=index_name)

予測する企業の株価を取得

予測したい企業の株価を取得します。

CODE=の部分は予測したい企業の株価コードを指定します。

今回は4755の企業の予測をしています。

# 予測する企業の株価データを取得
from pandas_datareader.stooq import StooqDailyReader
CODE = 4755
CODE_str = str(CODE) + ".JP"
start = datetime(2014, 1, 1)
end = datetime(2023, 1, 31)

df_target = StooqDailyReader(CODE_str, start=start, end=end).read()
df_target = df_target.sort_values('Date')
df_target = pd.DataFrame(df_target).asfreq("D", method="ffill")

5行目:start = datetime(2014, 1, 1)

取得する範囲のスタートを設定します。endも同じです。

8行目:df_target = StooqDailyReader…

データを取得します。

9行目:df_target = df_target.sort_values(‘Date’)

df_targetには最近のデータから順番に入っているので昇順にします。

10行目:df_target = pd.DataFrame…

データの欠損値処理をしています。

予測対象の作成

予測するのは,30日後の株価です。

# 目的変数の作成(30日後の終値)
df_target["target"] = df_target["Close"].shift(-30)

# 不要な行と列を削除
df_target = df_target.dropna(how='any')

2行目:df_target[“target”] = …

Closeに入っている終値を30日ずらすことで,30日後の終値を取得しています。

データの整理

データの結合

これまでに作成したデータを結合して1つのdataframeにします。

# データの結合
df = pd.merge(df_target, df_market, how='left', left_index=True, right_index=True)
df = df.dropna(how='any')

学習データとテストデータに分割

今回は,2021年までのデータを使って2022年の予測を行います。

# トレインとテストに分割
df_train = df[:"2021"]
df_test = df["2022":]

# 目的変数と説明変数に分割
X_train = df_train.drop("target", axis=1)
y_train = df_train["target"]
X_test = df_test.drop("target", axis=1)
y_test = df_test["target"]

データを標準化する

ニューラルネットワークに入れる説明変数は標準化正規化といった前処理をする必要があります。

今回はscikit-learnを使って標準化しました。

#標準化を行う
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

4行目:scaler.fit(X_train)

学習データを使って標準化のための変数を取得しています。

6行目:X_train = scaler.transform(X_train)

学習データを標準化しています。

7行目:X_test = scaler.transform(X_test)

テストデータを標準化しています。

モデルの作成

autokerasでの学習

いよいよ作成したデータを学習させます。

# 学習
model = ak.StructuredDataRegressor(overwrite=True, max_trials=20)
model.fit(X_train, y_train, epochs=200)

2行目:model = ak.StructuredDataRegressor(…

autokerasのモデルを定義しています。

今回は,20回の試行で最も良いモデルを作成します。

3行目:model.fit(X_train, y_train, epochs=200)

200エポックで学習させます。

以下のように計算されていきます。

Trial 29 Complete [00h 00m 06s]
val_loss: 987816.0

Best val_loss So Far: 15680.8203125
Total elapsed time: 00h 04m 22s

Search: Running Trial #30

Value             |Best Value So Far |Hyperparameter
True              |True              |structured_data_block_1/normalize
False             |False             |structured_data_block_1/dense_block_1/use_batchnorm
3                 |3                 |structured_data_block_1/dense_block_1/num_layers
32                |32                |structured_data_block_1/dense_block_1/units_0
0.25              |0.25              |structured_data_block_1/dense_block_1/dropout
1024              |1024              |structured_data_block_1/dense_block_1/units_1
0.25              |0                 |regression_head_1/dropout
adam              |adam              |optimizer
0.001             |0.001             |learning_rate
512               |512               |structured_data_block_1/dense_block

自動生成されたモデルの確認

どんなモデルが構築されたか確認してみましょう。

bestmodel = model.export_model()
bestmodel.summary()

以下のように表示されます。

Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 23)]              0         
                                                                 
 multi_category_encoding (Mu  (None, 23)               0         
 ltiCategoryEncoding)                                            
                                                                 
 dense (Dense)               (None, 16)                384       
                                                                 
 re_lu (ReLU)                (None, 16)                0         
                                                                 
 dense_1 (Dense)             (None, 16)                272       
                                                                 
 re_lu_1 (ReLU)              (None, 16)                0         
                                                                 
 dense_2 (Dense)             (None, 128)               2176      
                                                                 
 re_lu_2 (ReLU)              (None, 128)               0         
                                                                 
 regression_head_1 (Dense)   (None, 1)                 129       
                                                                 
=================================================================
Total params: 2,961
Trainable params: 2,961
Non-trainable params: 0
_________________________________________________________________

中間層は384⇨272⇨2176→129と4層になりました。

結果の保存

予測結果を保存して精度を確認します。

df_resultに結果をまとめます。

# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["Price"] = df_target["Close"]["2022-01-31":]
df_result["true"] = y_test.values[:366-30]
df_result["pred"] = model.predict(X_test)[:366-30]

結果の確認

matplotlibで結果を表示してみましょう。

import matplotlib.pyplot as plt

plt.figure()
df_result[["true","pred"]].plot(figsize=(6, 4))

青線は実際の株価オレンジ線が予測結果を示しています。

大まかな傾向はなんとなく予測できているような気がします。

下の記事のディープラーニングでの予測結果と似たような傾向になっています。

あまり精度が良くないのは,説明変数が少なすぎるのが原因だと考えられます。

あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶディープラーニングの使い方 この記事でわかること ディープニューラルネットワークの実装方法(ソースコードつき) ディープニューラルネットワークでの株価予測の方法 【による株価予測の概要】 ...

簡単にディープラーニングの構築ができて便利なフレームワークでした。

精度を上げる方法は以下の方法が考えられます。

精度を上げる方法

  • 他のアルゴリズムを使用する
  • 試行回数を増やす
  • 他の変数を使って予測する

ソースコードまとめ

今回使用したコードはこちらになります。

import pandas as pd
import numpy as np
from datetime import datetime

# 市場データの取得
from pandas_datareader import data
marketData=['NIKKEI225','SP500','NASDAQCOM']
df_market = data.DataReader(marketData,'fred','2014-01-01', '2023-1-31').asfreq("D")
df_market = df_market.fillna(method='ffill')
df_market = df_market.dropna(how='any')

# 各指数の移動平均との乖離率を算出する
for index_name in df_market.columns:
    for i in [5,10,30,60,90,120]:
        df_market[index_name + "_" + str(i) + "days_diffrol"] =\
        (df_market[index_name].rolling(i).mean() - df_market[index_name]) / df_market[index_name].rolling(i).mean()
    
    # 生データは削除する
    df_market = df_market.drop(columns=index_name)

# 予測する企業の株価データを取得
from pandas_datareader.stooq import StooqDailyReader
CODE = 4755
CODE_str = str(CODE) + ".JP"
start = datetime(2014, 1, 1)
end = datetime(2023, 1, 31)

df_target = StooqDailyReader(CODE_str, start=start, end=end).read()
df_target = df_target.sort_values('Date')
df_target = pd.DataFrame(df_target).asfreq("D", method="ffill")

# 目的変数の作成(30日後の終値)
df_target["target"] = df_target["Close"].shift(-30)

# 不要な行と列を削除
df_target = df_target.dropna(how='any')

# データの結合
df = pd.merge(df_target, df_market, how='left', left_index=True, right_index=True)
df = df.dropna(how='any')

# トレインとテストに分割
df_train = df[:"2021"]
df_test = df["2022":]

# 目的変数と説明変数に分割
X_train = df_train.drop("target", axis=1)
y_train = df_train["target"]
X_test = df_test.drop("target", axis=1)
y_test = df_test["target"]

#標準化を行う
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

# 学習
model = ak.StructuredDataRegressor(overwrite=True, max_trials=20)
model.fit(X_train, y_train, epochs=200)

bestmodel = model.export_model()
bestmodel.summary()

# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["Price"] = df_target["Close"]["2022-01-31":]
df_result["true"] = y_test.values[:366-30]
df_result["pred"] = model.predict(X_test)[:366-30]

import matplotlib.pyplot as plt

plt.figure()
df_result[["true","pred"]].plot(figsize=(6, 4))
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

このブログでは,PythonやLaTeXの使い方などを紹介しています!
仕事でも趣味でもプログラミングをしています。
ブログは2022年8月にスタートしました。
【経歴】東京大学大学院修了→大手IT企業勤務

コメント

コメントする

目次