- autoMLの実装方法(ソースコードつき)
- autoMLでの株価予測の方法
autoMLとは
autoMLとは,ニューラルネットワークの「層数」や「ノード数」などを自動で構築するフレームワークです。
pythonでは,autokerasというモジュールで出来ます。
その方法を株価予測を題材にしてまとめたいと思います!
autoMLによる株価予測の概要
予測は以下の流れで行います。
つまり,30日後の株価を予測する回帰モデルになります!
![](https://icochan1.net/wp-content/uploads/2023/02/0ae7c62e50dc705df75843b104ce66cd-1-1024x576.png)
他の手法でも予測しているので,ぜひご覧ください!
![](https://icochan1.net/wp-content/uploads/2023/02/7d2a8a5d380f463388d1c8d4512bef57-2-300x169.png)
![](https://icochan1.net/wp-content/uploads/2023/02/40dcbe9d88c96297b642179a653642d8-1-300x169.png)
![](https://icochan1.net/wp-content/uploads/2023/02/c64c5ece666a6407486987541305a212-1-300x169.png)
![](https://icochan1.net/wp-content/uploads/2023/02/9d831d187199270f191b3999ca596311-1-300x169.png)
事前準備
まずは,環境についてです。
- Python 3.10.4
必要なライブラリは以下のようになります。ない場合にはpip
やconda
で入れてください。
必要なライブラリ
- 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…
欠損値がある場所は削除しています。
株価取得の詳しい内容については以下をご覧ください。
![](https://icochan1.net/wp-content/uploads/2022/09/0ae7c62e50dc705df75843b104ce66cd-1-300x169.jpg)
主要な株価指数の前処理
株価指数そのままでは学習しにくいので,移動平均との乖離を計算します。
ここは精度に関係するので試行錯誤する必要があります。
# 各指数の移動平均との乖離率を算出する
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))
![](https://icochan1.net/wp-content/uploads/2023/02/autokeras-1024x683.png)
青線は実際の株価,オレンジ線が予測結果を示しています。
大まかな傾向はなんとなく予測できているような気がします。
下の記事のディープラーニングでの予測結果と似たような傾向になっています。
あまり精度が良くないのは,説明変数が少なすぎるのが原因だと考えられます。
![](https://icochan1.net/wp-content/uploads/2023/02/9d831d187199270f191b3999ca596311-1-300x169.png)
簡単にディープラーニングの構築ができて便利なフレームワークでした。
精度を上げる方法は以下の方法が考えられます。
精度を上げる方法
- 他のアルゴリズムを使用する
- 試行回数を増やす
- 他の変数を使って予測する
ソースコードまとめ
今回使用したコードはこちらになります。
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))
コメント