TensorFlowでニューラルネットワークを使ってFX予想をする方法(機械学習初心者向け)
更新情報 2019年3月12日
記事を執筆した時からライブラリのバージョンが代わりエラーが発生しているとコメントでご指摘頂きました。改めてコードが動くよう更新済みです。2019年3月時点のGoogle Colabのデフォルトライブラリで動作確認済み。
こんばんは、新米データサイエンティスト(@algon_fx)です。機械学習でのFX予想を趣味としてやっていますが、ここ最近はLSTM(ディープラーニングの一種)を使ったFX予想にはまっていました。(参考:LSTMでFX予測をやってみよう)
機械学習にはたくさんの手法があり、LSTMにこだわる必要はありません。LSTMをメインに使っていた理由としては、①海外では最も人気が高く実績のある手法であり、②為替レートのような時系列データが得意だからです。
先日に少し息抜き感覚で、たまには基本的なニューラルネットワークでやってみようかな〜と思い、気分一新に超基本的な構造のニューラルネットワークでFX予想をやったところ…自分でも目を疑うような予測精度が…。(注意:それでも利益が出るかは分かりませんし、改善の余地は腐る程あります)
下記はニューラルネットワークを使って予測した結果をツイートしたものです。
0.032の誤差でした… pic.twitter.com/vGjgcaxpbY
— 新米データサイエンティスト (@algon_fx) 2018年7月19日
時間に注目してもらいたいのですが、こちらは22:38の時点で22時のドル円の終値を予想したツイートです。
3.2pipの誤差で予測が出来たわけです。実のところLSTMでもこの程度の誤差で予測をすることは出来ていたのですが、局所的に誤差が広くなったりしてしまうことがありました。
対してニューラルネットワークは全体的に予測精度が安定しており、誤差を表すMAE(平均絶対誤差)の指標も桁違いで改善をしました・・。非常に情けない話ですが、まず最初に疑ったのは自分のコードな訳ですが・・どうやら間違いは無さそうです。
ってことで、前置きが長くなりましたが、今回は機械学習初心者の方へ向けたニューラルネットワークを使ったFX予想の方法をまとめます!本記事は上の予想精度が高いニューラルネットワークのコードを公開するものではありません!ご自身でニューラルネットワークを構築してFX予想をするための最初の一歩的な記事です。
では、やってみましょう!
そもそもニューラルネットワークとは?
今回のメインのお題でもある「ニューラルネットワーク」。ニューラルネットワークの概要をしっかり説明しようと思えば、それこそ本が一冊かけるレベルですので、本記事では初心者がFX予測をするにあたって、特に知っておくべ重要な4項目のみ簡単に説明をします。
その1 – 人間の脳神経を超簡易化したもの
人工知能感溢れる説明ですが、これは一般的にニューラルネットワークを説明する時に用いられる方法です。まずは下の図を見てください。
これはニューロンと呼ばれる脳神経を図式化したものです。上の図が全てで一つの「ニューロン」を表しています。人間の脳神経はこのニューロンが数千億以上繋がっており、一つ一つのニューロンが微弱な信号を送りあっています。
ニューロンはアンテナのような「樹状突起」と呼ばれる部分から信号をまず受け取ります。受け取った信号を「細胞体」が計算をして新たに信号を作ります。処理された新たな信号は次のニューロンへ「軸索」を通じて伝わる訳です。
このように人間の脳細胞は「信号を入力する」「受け取った信号を処理する」「次へ出力する」を繰り返しているのです。これを超簡単にコンピューターで真似したのが「ニューラルネットワーク」です。
その2 – 様々な種類がある
ニューラルネットワークは非常に大きなカテゴリだと思ってください。私が普段使っているLSTMも一種のニューラルネットワークなんです。他にもニュースなどで頻繁に出てくる「ディープラーニング」なんてのもニューラルネットワークの1つの種類に過ぎません。
上の図のように、ネットワークをどのように構成するのか、どのような出力をするのかなど詳細は異なりますが、全てニューラルネットワークの一種類です。
ここで何がポイントかと言うと、ニューラルネットワークは奥が深いと言うことです!本当にFX予想を極めるのであれば、それぞれのニューラルネットワーク(またはディープラーニング)の特色をしっかり勉強する必要があります。
とはいえ、いきなり全てを勉強するなんて大変なので、まずはシンプルな構成のニューラルネットワークからやってみましょう!ただ、この記事で紹介しているのがニューラルネットワークだ!なんて思わず、もっともっと深い分野だと言うことを認識して頂ければと思います。
その3 – 活性化関数を理解すべき
先ほど説明でニューロンは受け取った信号を「処理する」と言いました。この処理する部分を機械的に行うのが「活性化関数」と呼ばれるものです。英語ではActivate Functionとも呼ばれます。
深追いはしませんが、それぞれのニューロン(または層)が次のニューロン(または層)にどのように信号を渡すかを決める非常に重要な役割をします。
本記事では「ReLU」と呼ばれる活性化関数を使用します。これはRectified Linear Unitと呼ばれる関数で、ここ最近のニューラルネットワーク界隈では最も一般的な活性化関数の一つです。
その他にもステップ関数やシグモイド関数など、様々な関数を活性化関数として使うことが可能です。活性化関数の詳細は後ほど各自で勉強するべきですが、特に覚えておくべき重要なポイントとしては「受け取った信号をどのように処理するか」を決める重要な役割があると言うことです。
その4 – 正規化について
ニューラルネットワークを理解する上で「正規化(せいきか)」は外せません。まず混乱を避けるために明記しておきますが、機械学習には「正規化」と「正則化」があります。
よく機械学習を使い始めたばかりの方と話をしていると、この2つがごっちゃになっているケースがあります。正規化と正則化は言葉は似ていますが、全く異なるタスクですので一緒にしてはダメです。
さて、正則化ですが英語ではNormalization(ノーマライゼーション)と呼ばれています。主な役目は特徴量のレンジを揃えることにあります。
実際のデータを使って考えてみましょう。下記は7月16日から7月20日のドル円の1日足のデータです。注目頂きたいのは終値(close)と取引高(volume)の値のレンジです。
終値(close)のレンジは111.164(最小値)〜111.908(最大値)なのに対して、取引高(volume)のレンジは12518(最小値)〜33445(最大値)です。桁違いで2つの特徴量のレンジが異なります。
そこで、機械学習のモデルへこれらのデータ(特徴量)を学習させる前に「正規化」=データのレンジを整えるわけです。下のテーブルは特徴量の正規化を行なった後のデータです。
7月16日のドル円終値は112.908円という値でしたが、これは0.4101という値へ変換されています。正則化の方法は多数ありますが、最もメジャーな手法として「min-max-normalization」を本チュートリアルでは使っています。
正規化において非常に重要なのが、テストデータや予想したい実際のデータも全て同じルールで正規化をしなくてはいけません。なぜならモデルは112.908円を0.4101という値で認識してるからです。
なぜこんな面倒なことをやるの?って話ですが、特徴量の値を正規化してあげないと、機械学習のアルゴリズムが上手くデータを学習してくれないケースがあるからです。ただし全てのアルゴリズムで正規化が必須な訳ではなく、正規化しなくても問題なく学習するアルゴリズムも多数あります。
慣れるまでは正規化は少しややこしいですが、機械学習では初歩中の初歩ですし、正しい予測を行うには必須の行程です!
ニューラルネットワークの説明が長くなってしまいましたが、次からは実際にPythonを使ってニューラルネットワークを構築して、FX予想してみましょう。
実行環境について
実際にPythonを書いていく前に、このチュートリアルで必要な環境についてです。ご自身のPCで実行する場合は、全てのライブラリのインストールが必要です。
環境構築が面倒であれんば、Google Colabがオススメです。機械学習に必要なライブラリのほぼ全てがインストールされており、ブラウザのみで実行が可能です。
・Python 3.6
・Pandas(大量のデータ効率的に扱うライブラリ)
・Numpy(行列の計算を簡単にしてくれるライブラリ)
・Scikit-learn(機械学習の様々な手法が詰まったライブラリ)
・TensorFlow(言わずもがな。今回の主役)
Macであればpip installで全て簡単にインストールが可能です。Windowsであれば、Anacondaの利用がオススメです。
また、私は便宜上、jupyter notebookを実行環境として使っています。Jupyter notebookとは、セルコーディングのツールで、Pythonを実行するときに非常に便利なツールです。厳密にいうとIDE(開発環境)ではありませんが、機械学習をやる方であればほぼ間違いなく利用する環境です。
STEP1 ライブラリとデータの読み込み
では、やって行きましょう!まずはニューラルネットワークの構築に必要なライブラリを読み込みます。
1 2 3 4 5 6 7 8 9 |
# ライブラリのインポート import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_absolute_error import tensorflow as tf |
次にデータを読み込みましょう。事前にOANDAのAPIでドル円の1日足を取得して扱いやすいように綺麗にしてから、CSVファイルに書き出しました。下記のURLからダウンロードして使ってください。(参考:OANDA API v1)
CSVファイルをローカルにダウロードできたら、下記のコードを実行して為替レートのデータを読み込んであげましょう。こちらですが、CSVファイルの保存先がJupyterの起動ディレクトリと異なる場合は、保存先のパスを指定する必要がありますので注意してください。
1 2 3 4 |
# CSVファイルから過去レートを読み込む df = pd.read_csv("usd_jpy_api.csv") |
では、早速データを確認してみます。
1 2 3 4 |
# データの最初の5行を表示 df.head() |
1 2 3 4 5 6 7 8 9 |
-- 出力 time close open high low volume 0 2016/08/19 06:00:00 100.256 99.919 100.471 99.887 30965 1 2016/08/22 06:00:00 100.335 100.832 100.944 100.221 32920 2 2016/08/23 06:00:00 100.253 100.339 100.405 99.950 26069 3 2016/08/24 06:00:00 100.460 100.270 100.619 100.104 22340 4 2016/08/25 06:00:00 100.546 100.464 100.627 100.314 17224 |
ご覧の通り2016年8月19日からドル円の終値(close)、始値(open)、高値(open)、安値(low)、取引量(volume)のデータとなります。
STEP2 データの前処理と正規化
データが無事に読み込まれましたので、ニューラルネットワークへ学習させるためにデータの前処理を行いましょう。
まずは、データの終値を1日ずらします。え?なんでそんなことするの?って思うかもしれませんが、非常に重要です。今回の予測は特徴量として昨日の始値、高値、安値、取引量のデータを使って、今日の終値を予測します。
つまり、終値を一日ずらすことで、前日の特徴量に対して当日の終値が教師データとして出来上がるわけです。説明よりも実際にやってみると解りやすいです。
まずはデータの最後尾を表示させます。
1 2 3 4 |
# データの最後尾を表示 df.tail() |
1 2 3 4 5 6 7 8 9 |
-- 出力 time close open high low volume 495 2018/07/17 06:00:00 112.908 112.320 112.933 112.231 19645 496 2018/07/18 06:00:00 112.866 112.914 113.144 112.723 17432 497 2018/07/19 06:00:00 112.501 112.887 113.187 112.072 26697 498 2018/07/20 06:00:00 111.474 112.504 112.631 111.401 33445 499 2018/07/23 06:00:00 111.164 111.420 111.523 110.760 16040 |
一番最後は7月23日の終値(111.164円)です。この終値を前日である7月20日の終値へ動かします。
1 2 3 4 5 6 7 8 |
# 終値を1日分移動させる df_shift = df.copy() df_shift.close = df_shift.close.shift(-1) # 改めてデータを確認 df_shift.tail() |
1 2 3 4 5 6 7 8 9 |
-- 出力 time close open high low volume 495 2018/07/17 06:00:00 112.866 112.320 112.933 112.231 19645 496 2018/07/18 06:00:00 112.501 112.914 113.144 112.723 17432 497 2018/07/19 06:00:00 111.474 112.887 113.187 112.072 26697 498 2018/07/20 06:00:00 111.164 112.504 112.631 111.401 33445 499 2018/07/23 06:00:00 NaN 111.420 111.523 110.760 16040 |
ご覧の通り23日の終値はNaN(非数)になっており、その代わりに20日の終値へ移動しています。最後の行とtime(時間)は不要ですので訓練データから落としましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 最後の行を除外 df_shift = df_shift[:-1] # 念のためデータをdf_2として新しいデータフレームへコピ− df_2 = df_shift.copy() # time(時間)を削除 del df_2['time'] # データセットのサイズを確認 print(df_2.shape[0]) print(df_2.shape[1]) |
1 2 3 4 5 |
-- 出力 499 5 |
もともと500行のデータでしたが、最後尾を削除したので499行5列のデータとなります。次にテストデータと訓練データへ分割しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# データセットの行数と列数を格納 n = df_2.shape[0] p = df_2.shape[1] # 訓練データとテストデータへ切り分け train_start = 0 train_end = int(np.floor(0.8*n)) test_start = train_end + 1 test_end = n data_train = df_2.loc[np.arange(train_start, train_end), :] data_test = df_2.loc[np.arange(test_start, test_end), :] # テストデータの最後2行を表示 data_test[97:99] |
1 2 3 4 5 |
-- 出力 array([[ 111.474, 112.887, 113.187, 112.072, 26697. ], [ 111.164, 112.504, 112.631, 111.401, 33445. ]]) |
今回は訓練データを全体の8割、テストデータを残り2割としています。また一つ大事な点として、訓練データ/テストデータへ分割する際はシャッフルしてはいけません。
通常の機械学習であれば、訓練/テストへ分ける際にデータをシャッフルしないとダメな手法もありますが、FXデータのような時系列のデータを扱う場合はシャッフルすることで弊害が生じます。
上記のコードでテストデータの最後の2行を表示させています。先ほど確認しましたが、元のデータセットの最後の2行となっているのが確認できます。(つまりシャッフルしていない)
1 2 3 4 5 |
-- 出力(元データの最後尾2列) 497 2018/07/19 06:00:00 111.474 112.887 113.187 112.072 26697 498 2018/07/20 06:00:00 111.164 112.504 112.631 111.401 33445 |
次に「正規化」を行います。今回はScikit-learnに組み込まれているMinMaxScaler()を使います。
1 2 3 4 5 6 7 |
# データの正規化 scaler = MinMaxScaler(feature_range=(-1, 1)) scaler.fit(data_train) data_train_norm = scaler.transform(data_train) data_test_norm = scaler.transform(data_test) |
最後に正規化したデータを特徴量(x)とターゲット(y)へ切り分けてあげましょう。
1 2 3 4 5 6 7 |
# 特徴量とターゲットへ切り分け X_train = data_train_norm[:, 1:] y_train = data_train_norm[:, 0] X_test = data_test_norm[:, 1:] y_test = data_test_norm[:, 0] |
参考までにですが、データは正規化されていますので、予測される値も正規化されます。実際にトレードの指標として使うには、元のレートのデータへ戻す必要があります。
練習としてやってみましょう。Scikit-learnのscaler.inverse_transform()を使うことで、正規化した値から元のレートへ戻せます。
1 2 3 4 5 6 |
# 正規化から通常の値へ戻す y_test = y_test.reshape(99, 1) test_inv = np.concatenate((y_test, X_test), axis=1) test_inv = scaler.inverse_transform(test_inv) |
確認してみましょう。data_testは正規化する前のテストデータで、test_invは正規化したものを上記のコードで元の値へ戻したものです。両方の一番最初のレコードを確認します。
1 2 3 4 5 6 7 8 9 10 |
# 正規化の前のテストデータ print(data_test.values[0]) # 正規化後のテストデータ print(y_test[0], X_test[0]) # 正規化から戻したデータ print(test_inv[0]) |
1 2 3 4 5 6 |
-- 出力 [ 106.099 106.232 106.47 105.863 29786. ] [-0.34859881] [-0.31148435 -0.3361064 -0.32056165 -0.79531038] [ 106.099 106.232 106.47 105.863 29786. ] |
ご覧の通り全て同じテストデータの一番最初の行ですが、正規化前と正規化から戻した値が一緒なのが確認できます。このように、正規化をしたら戻すという作業も初歩的な操作なので、覚えておくと良いかと思います。
STEP3 TensorFlowでニューラルネットワーク構築
さて、いよいよ本題です。TensorFlowを使ってシンプルなニューラルネットワークを設計しましょう。TensorFlowですが、使い方に少し癖があります。検索すれば、多数の初心者向けの使い方記事がありますので、基本的な使い方はそれらの記事をご参考ください。
ではやっていきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 訓練データの特徴量の数を取得 n_stocks = X_train.shape[1] # ニューロンの数を設定 n_neurons_1 = 256 n_neurons_2 = 128 # セッションの開始 net = tf.InteractiveSession() # プレースホルダーの作成 X = tf.placeholder(dtype=tf.float32, shape=[None, n_stocks]) Y = tf.placeholder(dtype=tf.float32, shape=[None]) # 初期化 sigma = 1 weight_initializer = tf.variance_scaling_initializer(mode="fan_avg", distribution="uniform", scale=sigma) bias_initializer = tf.zeros_initializer() |
ご覧の通り、今回のニューラルネットワークのモデルでは、ニューロンの数は256、128と指定しています。次に隠れ層の重み(Weights)を書きましょう。
1 2 3 4 5 6 7 |
# Hidden weights W_hidden_1 = tf.Variable(weight_initializer([n_stocks, n_neurons_1])) bias_hidden_1 = tf.Variable(bias_initializer([n_neurons_1])) W_hidden_2 = tf.Variable(weight_initializer([n_neurons_1, n_neurons_2])) bias_hidden_2 = tf.Variable(bias_initializer([n_neurons_2])) |
2層の非常にシンプルなニューラルネットワークです。上で指定したニューロンを各層で処理をします。次は出力( Output)の設定です。
1 2 3 4 5 |
# 出力の重み W_out = tf.Variable(weight_initializer([n_neurons_2, 1])) bias_out = tf.Variable(bias_initializer([1])) |
続いて隠れ層の構造を指定します。下記のコードをみるとわかりますが、一層目と二層目の活性化関数として「ReLU」が使われているのが確認できます。
1 2 3 4 5 6 7 8 |
# 隠れ層の設定(ReLU=活性化関数) hidden_1 = tf.nn.relu(tf.add(tf.matmul(X, W_hidden_1), bias_hidden_1)) hidden_2 = tf.nn.relu(tf.add(tf.matmul(hidden_1, W_hidden_2), bias_hidden_2)) # 出力層の設定 out = tf.transpose(tf.add(tf.matmul(hidden_2, W_out), bias_out)) |
次にコスト関数、最適化関数を指定しましょう。コスト関数とは、簡単に言えば予測した値と実際の値の誤差を計算するものです。ニューラルネットワークでは、この誤差を最小にするような処理が内部で行われます。
1 2 3 4 5 6 7 8 9 10 |
# コスト関数 mse = tf.reduce_mean(tf.squared_difference(out, Y)) # 最適化関数 opt = tf.train.AdamOptimizer().minimize(mse) # 初期化 net.run(tf.global_variables_initializer()) |
では、いよいよ訓練データをニューラルネットワークに学習させてみましょう。epochsというのは、ニューラルネットワークの反復計算回数です。
1 2 3 4 5 6 7 8 9 10 11 |
# ニューラルネットワークの設定 batch_size = 128 mse_train = [] mse_test = [] # 訓練開始!500回の反復処理 epochs = 500 for e in range(epochs): net.run(opt, feed_dict={X: X_train, Y: y_train}) |
データも全部で400件と非常に小さいので、すぐに計算が終わるかと思います。では、いよいよ・・テストデータを使って訓練したモデルから予測を出力してみましょう!(ドキドキ)
STEP4 テストデータから予測
機械学習をやっていて、一番ドキドキするタイミングですね(笑)。モデルは訓練データのみ「学習」していますので、テストデータは全く新しい見たことの無いデータな訳です。
復習ですが、テストデータには「終値」が含まれていません。各日にちの「高値」「安値」「始値」「取引量」のみです。それらを使って、翌日(次の日)の終値を予測するのが今回の目的です。
では、やってみましょう!
1 2 3 4 5 6 7 |
# テストデータで予測 pred_test = net.run(out, feed_dict={X: X_test}) # 予測データの最初の2つを表示 pred_test[0][0:2] |
1 2 3 4 |
-- 出力 array([-0.32251835, -0.35930118], dtype=float32) |
出ました!と言っても…正規化した値なので、全然意味がわかりません。先ほどもやりましたが、scaler.inverse_transform()を使って元の値へ復元してあげましょう。
1 2 3 4 5 |
# 予測値をテストデータに戻そう(値も正規化からインバース) pred_test = np.concatenate((pred_test.T, X_test), axis=1) pred_inv = scaler.inverse_transform(pred_test) |
予測が出ました!では、確認してみましょう。特徴量があっているかの確認を含めて、まずは元データの最後尾のデータを出してあげます。
1 2 3 4 |
# 元データの最後尾 df_shift.tail(1) |
1 2 3 4 5 |
-- 出力 time close open high low volume 498 2018/07/20 06:00:00 111.164 112.504 112.631 111.401 33445 |
ご覧の通り7月20日のドル円のデータです。ただ一つ注意しなくてはいけないのは、終値(close)は7月20日のものではありません。前処理で1日ずらしたので、これは21日の終値です。
では、今回訓練したニューラルネットワークは一体21日の終値をいくらで予測したのか確認して見ましょう!また正規化を戻しましたが、ちゃんと戻っているのか確認のためdata_testとtest_invも表示させます。
1 2 3 4 5 6 7 8 9 10 |
# テストデータの最後のデータ(正規化前) print(data_test.values[98]) # テストデータの最後のデータ(正規化を戻した後) print(test_inv[98]) # モデルが予測したデータ print(pred_inv[98]) |
1 2 3 4 5 6 |
-- 出力 [ 111.164 112.504 112.631 111.401 33445. ] [ 111.164 112.504 112.631 111.401 33445. ] [ 111.95067739 112.504 112.631 111.401 33445. ] |
出ました!実際の21日の終値は111.164円でしたが、20日の特徴量から予測した結果「111.950円」という予想結果です!実際のレートから89pip近くも外れて予測されています(笑)
でもがっかりしないで下さい。今回は「あえて」シンプルなニューラルネットワークを使って予測しました。まだまだ伸び代は腐る程あります!実際に私が最近トレードで使っているモデルは0.5pip程度の誤差で予測してくれます。
では予測したレートと実際のレートを簡単にチャートに落としてみましょう。
1 2 3 4 5 6 7 8 9 |
# 予測と実際のテストの終値のチャートをプロットしてみよう plt.ion() fig = plt.figure() ax1 = fig.add_subplot(111) line1, = ax1.plot(test_inv[:,0]) line2, = ax1.plot(pred_inv[:,0]) plt.show() |
非常に大きな値幅で予測は外れていましたが、このようにプロットしてみると、意外とそれなりにトレンドを読んで予測しているのがわかります。
グラフだけでは予想の評価として曖昧なので、MAE(平均絶対誤差)という指標を算出してあげましょう。MAEとは、予測した値と実際の値の誤差を指標化したものです。つまり値が小さければ誤差が少ない、値が大きければ誤差が大きいを意味します。
1 2 3 4 5 |
# MAEの計算 mae_test = mean_absolute_error(test_inv, pred_inv) print(mae_test) |
0.0800090272228
MAEは約0.08でした。モデルを改善するたびに、このようにMAEを算出することで、改善されたのか?悪くなったのか?を相対的に評価することができます。
まとめと次へのステップ
如何でしたでしょか?非常にボリュームのあるチュートリアルになってしまいましたが、これでニューラルネットワークの大枠の基本は全てカバーしたつもりです!
結果を見てもわかる通り、今回構築したモデルでFX予想をしても100%上手くいきません。ただし、これから改善をするのは非常に簡単です!
例えば特徴量。今回はたったの4つしか特徴量を使いませんでした。特徴量としてテクニカル指標(MACDや移動平均)などの値を追加することで、モデルの予測精度は劇的に改善します。(参考:Pythonでテクニカル指標)
色々と試行錯誤をして、機械学習トレードを一緒に頑張りましょう!
以上となります!ブログ読んでいただきありがとうございます!Twitterでも色々と発信しているので、是非フォローお願いします!
【人気記事】
ディスカッション
コメント一覧
こんにちは。
質問なのですが、
訓練データとテストデータに分けるところの
data_train = data[np.arange(train_start, train_end), :]
の data はどこから出てきたのでしょうか?
写経していたら、PyCharm先生に怒られてしまいました。
よろしくお願いします。
失礼しました・・完全に誤りです!
正しくはdf_2です!記事内のコードを更新しました。
ご指摘、ありがとうございます!
こんにちは。
初心者なのであまりよく分かってないのですが、コードについて2点、お聞きしたいです。
1つ目
データの終値を1日ずらした後、
NaNを含む列の削除をコードが消えているのではないでしょうか?
———————————————————————
# 念のためデータをdf_2として新しいデータフレームへコピ−
df_2 = df_shift.copy()
#NaNを含む列を削除
df_2=df_2.dropna(how=’any’)
# time(時間)を削除
del df_2[‘time’]
# データセットのサイズを確認
print(df_2.shape[0])
print(df_2.shape[1])
———————————————————————
2つ目
テストデータと訓練データを分けるところでどうしてもエラーが発生してしまいます。
エラー内容として
TypeError: unhashable type: ‘numpy.ndarray’
というのが出ます。
10,11行目の
data_train = df_2[np.arange(train_start, train_end), :]
data_test = df_2[np.arange(test_start, test_end), :]
を以下のように変更すると解決しました。
data_train = df_2.iloc[np.arange(train_start, train_end), :]
data_test = df_2.iloc[np.arange(test_start, test_end), :]
この解決策で問題ないでしょうか?
よろしくお願いいたします。
こちら、失礼しました!改めてコードが正常に動くよう記事を更新しました!対応が遅れてしまい申し訳ないです。。
こんにちは。
ほげげさんの修正方法でやってみましたが、STEP2の最後の正規化から戻した値を確認する時にエラーが発生しますね。
# 正規化の前のテストデータ
#print(data_test[0]) # これだとエラーになる
print(data_test.head()) # これなら先頭の5行が表示され、正規化から戻しても値が一致していることが確認出来るが、型が違う?
こちら、失礼しました!改めてコードが正常に動くよう記事を更新しました!対応が遅れてしまい申し訳ないです。。
更新ありがとうございます!
修正されたコードで動くことを確認しました。
ところで予測が実行毎にわずかに変わるのは、仕方のないことなのでしょうか?
(MAEで0.076~0.080になります。)
こんにちは。TensorFlowの実装参考のため、拝借させていただきました。
一連の実装をご記載いただき、助かります。
学習の指針としては「あくまで参考まで」ということで組まれているのかもしれませんが、気になったので一点挙げさせていただきます。
説明文から察するに「テストデータの始値・高値・安値・終値・出来高を入力とし、学習データより終値を予測する」という処理になっているのでしょうか?
始値以外の項目は、日足単位が確定した時点で初めて明示されるものですので、高値・安値・終値・出来高がわかっている前提での予測は実質不可能ではないでしょうか。
相関関係上、終値は安値~高値の値内に確実に収まるので、学習結果がそれを解釈しているのであれば、大きく外れることはあり得ないのかと思います。
入力は始値だけとし、他情報全てを予測するのが正しいのではないでしょうか。
いずれにしても、四本値だけでの学習ではチャート予測は困難なのでしょうね。
テクニカル分析結果を以てして、性能が向上するものなのでしょうかね。
今後の精度向上、頑張ってください。
こんにちは。PythonもTensorFlowもかじり始めたばかりですが、興味あるFXが題材だったため、モチベーションを維持して写経&動確でき、全体像が理解できました。
usd_jpy_api.csvが、コードのエラーで読み込め無かったのですが(Windowsだから?)、他の記事を参考にOANDAのAPIから取得してデータを繋げました。
前の方が、「始値以外の項目は、日足単位が確定した時点で初めて明示されるものですので、高値・安値・終値・出来高がわかっている前提での予測は実質不可能では」とコメントしていますが、前処理でデータの終値を1日ずらしているので(昨日のデータを使っている)、可能な予測になっている認識です。
為になる教材を提供頂き誠にありがとうございました。今後ともブログ・Twitter拝見させて頂きたいと思います。
他の記事も含め参考にさせて頂いております。有益な記事をありがとうございます。
本記事でMAEを算出されていますが、手元で試したところ、実力より良い値を出して
しまっているように見えたので、コメントさせていただきます。
mean_absolute_error(test_inv, pred_inv)
とされていますが、これだと予測していない始値、高値、安値も含めた誤差となるようです。
mean_absolute_error(test_inv[:,0], pred_inv[:,0])
ではないでしょうか?
はやりのディープラーニングでも、4本値だけから実用的な精度で予測させるのは
難しいのかなと少し落胆ですが、他記事を参考に次はLSTMも試してみようかなどと
思っております。