ChatGPTは、OpenAIによって提供されているチャット型AIです。EA開発に必要なプログラミングスキルも備えていることで知られています。
そこで今回は、FXの価格予測を行えるような機械学習モデルを作成してみたいと思います。機械学習の中でも、深層学習(ディープラーニング)を指定してみます。
今回は、
- ChatGPTに機械学習モデルのコード作成を依頼
- コードを実行した結果をChatGPTに渡して、コードを改善してもらう
- 改善されたコードを実行した結果を再び渡して、コードを改善してもらう
というプロセスを繰り返して、ChatGPT自身でモデルの検証・改善を続けることが出来るのかを少し検証してみようと思います。
ディープラーニングとは
ディープラーニング(深層学習)を用いてFXの価格予測を行うというのはどのようなことでしょうか。こういった概要をまとめてもらうのにもChatGPTは非常に有用です。
深層学習を用いたFXの価格予測は、過去の為替データや経済指標、ニュースなど様々な情報を基に、将来の為替価格を予測することを目的とした手法です。深層学習は、多層のニューラルネットワークを利用してデータから複雑な特徴やパターンを抽出し、予測モデルを構築します。
FXの価格予測には以下のような深層学習モデルがよく用いられます。
- LSTM(Long Short-Term Memory): 時系列データに適したリカレントニューラルネットワーク(RNN)の一種で、過去の情報を保持しながら新しい情報を学習することができます。
- CNN(Convolutional Neural Network): 通常、画像認識に用いられる畳み込みニューラルネットワークですが、時系列データに対しても適用可能で、局所的な特徴を抽出することができます。
- GRU(Gated Recurrent Unit): LSTMと同様にリカレントニューラルネットワークの一種で、時系列データの学習に適しています。LSTMと比較してパラメータが少なく、計算負荷が低いのが特徴です。
これらのモデルを用いて、過去の為替データやその他の経済指標を入力として、将来の為替価格を予測することができます。ただし、市場は多くの要因が絡み合っており、突発的な出来事や政治的な要因など、モデルに組み込みきれない要素も存在します。そのため、深層学習モデルを用いたFXの価格予測には限界があり、絶対的な予測は困難です。
EAの話をしてる時もそうですが、必ず、絶対的な、完全なものを難しいというお断りを添えてきますね。
深層学習を行う際のポイント
今回のChatGPTはGPT-4を用いているのですが、GPT-3.5と比較すると、少し聞いただけでも追加情報を次々と付加してくれる印象があります。
ChatGPTの話は続きます。
深層学習を用いたFXの価格予測を行う際は、その限界を理解し、予測結果に過度な期待を持たず、リスク管理を適切に行うことが重要です。また、モデルのパラメータや構造を調整することで、予測精度の向上が期待できることもありますが、根本的に市場の不確定性を排除することはできません。それでも、深層学習を用いたFXの価格予測は、他の予測手法と組み合わせることで効果的に活用できることがあります。以下は、深層学習を活用する際のポイントです。
- データの前処理: 為替データや経済指標を正規化や標準化などの前処理を行い、モデルが学習しやすい形に変換します。
- 特徴量の選択: 重要な特徴量を選択し、ノイズの多い不要な特徴量を除外することで、モデルの学習効率を向上させることができます。
- ハイパーパラメータのチューニング: モデルの学習率やバッチサイズ、エポック数などのハイパーパラメータを調整し、モデルの予測精度を向上させます。
- アンサンブル学習: 複数のモデルや手法を組み合わせることで、それぞれのモデルの長所を活かし、予測精度の向上が期待できます。
- 過学習の防止: モデルの複雑さを適切に制御し、正則化やドロップアウトを導入することで、過学習を防ぎ、未知のデータに対する予測精度を向上させることができます。
最後に、深層学習を用いたFXの価格予測はあくまで補助的なツールであり、完全な予測を期待することはできません。投資戦略の一環として深層学習を活用しつつ、リスク管理や資金管理を適切に行うことが、より重要なポイントとなります。市場の不確定性を理解し、慎重な判断を行いながら、深層学習モデルを利用することが望ましいです。
似たような質問をただ繰り返すだけでも、ディープラーニング入門という本を読んでいるような感覚で学ぶことが出来ます。ChatGPT学習というのもいずれ一般的になってくるのでしょうか。
Pythonでコードを書いてもらう
深層学習を用いたFXの価格予測のために、以下の手順でPythonコードを書いていきます。今回は、Kerasを使ったLSTMモデルを例にします。
- 必要なライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout
from keras.optimizers import Adam
- データの読み込みと前処理
# データの読み込み
data = pd.read_csv("your_data_file.csv")
# 必要なカラムの選択 (例: USD/JPYの終値)
data = data['USD_JPY_Close']
# データの正規化
scaler = MinMaxScaler(feature_range=(0, 1))
data = scaler.fit_transform(np.array(data).reshape(-1, 1))
# 学習データとテストデータに分割
train_size = int(len(data) * 0.8)
train_data = data[:train_size]
test_data = data[train_size:]
- データセットの作成
def create_dataset(data, look_back=1):
x_data, y_data = [], []
for i in range(len(data) - look_back - 1):
x_data.append(data[i:(i + look_back), 0])
y_data.append(data[i + look_back, 0])
return np.array(x_data), np.array(y_data)
look_back = 60
x_train, y_train = create_dataset(train_data, look_back)
x_test, y_test = create_dataset(test_data, look_back)
# LSTMへの入力形式に変換
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
- モデルの定義と学習
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(look_back, 1)))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50))
model.add(Dense(1))
# モデルのコンパイル
model.compile(optimizer=Adam(lr=0.001), loss='mean_squared_error')
# モデルの学習
history = model.fit(x_train, y_train, epochs=100, batch_size=64, validation_data=(x_test, y_test))
- 予測と評価
train_predict = model.predict(x_train)
test_predict = model.predict(x_test)
# 正規化の逆変換
train_predict = scaler.inverse_transform(train_predict)
y_train = scaler.inverse_transform([y_train])
test_predict = scaler.inverse_transform(test_predict)
y_test = scaler.inverse_transform([y_test])
# 評価 (RMSE)
train_rmse = np.sqrt(mean_squared_error(y_train[0], train_predict[:, 0]))
test_rmse = np.sqrt(mean_squared_error(y_test[0], test_predict[:, 0]))
print("学習データのRMSE: ", train_rmse)
print("テストデータのRMSE: ", test_rmse)
- 結果の可視化
plt.figure(figsize=(14, 5))
plt.plot(scaler.inverse_transform(data), label='実際の価格')
train_predicted = np.empty_like(data)
train_predicted[:, :] = np.nan
train_predicted[look_back:len(train_predict) + look_back, :] = train_predict
plt.plot(train_predicted, label='学習データの予測価格')
test_predicted = np.empty_like(data)
test_predicted[:, :] = np.nan
test_predicted[len(train_predict) + (look_back * 2) + 1:len(data) - 1, :] = test_predict
plt.plot(test_predicted, label='テストデータの予測価格')
plt.xlabel('時間')
plt.ylabel('価格')
plt.legend()
plt.show()
上記のコードによって、学習データとテストデータの予測結果を可視化できます。このモデルはあくまで一例であり、ハイパーパラメータやモデル構造の調整によって精度が変わる可能性があります。また、他の深層学習モデルや手法を試すことで、さらに精度を向上させることができるかもしれません。ただし、市場の変動は多くの要因によって影響を受けるため、どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
「インプットは、複数の通貨ペアの1分足~4時間足が用意可能です。」と言ってみたのですが、特にその部分は考慮されず、四本値(始値、高値、安値、終値)データの終値をインプットにすれば良い作りのようです。
インプットデータの指定
ChatGPTが書いてくれたコードでは、”your_data_file.csv”というファイルに、’USD_JPY_Close’というカラムが存在する必要があります。
そこで、その部分を以下のように少し修正します。
修正前
# データの読み込み
data = pd.read_csv("your_data_file.csv")
# 必要なカラムの選択 (例: USD/JPYの終値)
data = data['USD_JPY_Close']
修正後
# データの読み込み
data = pd.read_pickle('/content/drive/My Drive/backtest/bar/df_H4.pkl')
# 必要なカラムの選択
data = data['Close']
用意したインプットデータ
今回は、XMのGOLDの4時間足(2013年6月〜2023年3月)をインプットデータとしました。
用意されたモデルの実行結果
用意されたコードをそのまま実行すると、以下のような結果が出ました。
RMSE
学習データのRMSE: 14.73236547363949
テストデータのRMSE: 22.703382167670906
結果のグラフ
実行結果の分析
学習データのRMSE: 12.68107382309471
テストデータのRMSE: 21.30095528606679
結果からわかるように、学習データのRMSE(Root Mean Square Error)は約12.68で、テストデータのRMSEは約21.30となっています。RMSEは予測誤差の大きさを表しており、値が小さいほど予測精度が高いことを示します。
この結果から、学習データに対しては比較的良い予測ができている一方、テストデータに対しては予測精度が低くなっていることがわかります。これは、モデルが学習データに過学習している可能性があります。
過学習を防ぐためには、以下のような対策を検討することができます。
- モデルの複雑さを減らす: 層の数やユニット数を減らして、モデルをシンプルにすることで過学習を抑制できることがあります。
- 正則化を導入する: L1正則化やL2正則化を用いて、モデルのパラメータが大きな値をとらないように制約をかけることができます。
- ドロップアウトを調整する: ドロップアウトの割合を変更することで、モデルの過学習を抑制する効果が期待できます。
- データ量を増やす: データが十分でない場合、過学習が起こりやすくなります。可能であれば、より多くのデータを用意して学習を行うことで過学習を防ぐことができます。
また、ハイパーパラメータのチューニングや他のモデル・手法の試行によって、予測精度を向上させることができる可能性があります。ただし、どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
モデルの改善
学習を防ぐために、以下のようにモデルを改善してみました。ここでは、モデルの複雑さを減らす方法と、正則化を導入する方法を取り入れています。
- 必要なライブラリのインポートに正則化のためのライブラリを追加
from keras.regularizers import l1_l2
- モデルの定義と学習で、層の数やユニット数を調整し、正則化を導入
model = Sequential()
model.add(LSTM(32, return_sequences=True, input_shape=(look_back, 1), kernel_regularizer=l1_l2(l1=1e-5, l2=1e-4)))
model.add(Dropout(0.2))
model.add(LSTM(32, return_sequences=False, kernel_regularizer=l1_l2(l1=1e-5, l2=1e-4)))
model.add(Dropout(0.2))
model.add(Dense(1))
# モデルのコンパイル
model.compile(optimizer=Adam(lr=0.001), loss='mean_squared_error')
# モデルの学習
history = model.fit(x_train, y_train, epochs=100, batch_size=64, validation_data=(x_test, y_test))
上記のコードでは、LSTM層のユニット数を50から32に減らしてモデルの複雑さを抑え、正則化を導入しています。また、モデルの層数は2層に減らしています。
この改善したコードを試して、再度学習データとテストデータのRMSEを計算し、過学習が抑制されているか確認してみてください。ただし、市場の変動は多くの要因によって影響を受けるため、どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
モデル改善後の結果の分析
学習データのRMSE: 14.73236547363949
テストデータのRMSE: 22.703382167670906
改善したコードの結果から、学習データのRMSEは約14.73、テストデータのRMSEは約22.70となっています。この結果は、過学習が改善されているかどうかについては明確に示していません。学習データとテストデータのRMSEの差は若干小さくなっていますが、まだ改善の余地があると考えられます。
さらなる改善策として、以下の方法を試すことができます。
- ドロップアウトの割合を増やす: ドロップアウトを0.2から0.4や0.5に増やすことで、過学習を抑制する効果が期待できます。
- データのウィンドウサイズを変更:
look_back
の値を調整することで、モデルが学習するデータの期間を変えることができます。適切なウィンドウサイズによって、モデルの汎化性能が向上する可能性があります。 - 学習データと検証データの分割方法を変更: 時系列データの場合、一般的なデータ分割だけでなく、時系列クロスバリデーションといった手法を用いてデータを分割することで、モデルの汎化性能を向上させることができます。
- 他のモデルやアルゴリズムを試す: LSTM以外にも、GRUやCNNを用いたモデル、あるいはアンサンブル学習などのアルゴリズムを試してみることで、精度が向上する可能性があります。
最適なモデルを見つけるためには、これらの方法を試しながら繰り返し実験を行うことが重要です。ただし、市場の変動は多くの要因によって影響を受けるため、どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
さらにモデルを改善
さらに、ChatGPTが提案してきた改善内容を、ChatGPT自身にコードを改善してもらいます。これが可能なのがChatGPTの強みですね。自ら分析して改善案を提示して、その改善案を実行する。これを永遠に繰り返して精度を高めていくことが可能です。
上記の改善策を取り入れたコードを以下に示します。ドロップアウトの割合を増やし、データのウィンドウサイズを調整し、時系列クロスバリデーションを導入しています。また、モデルとしてはGRUを使用してみました。
- 必要なライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import TimeSeriesSplit
from keras.models import Sequential
from keras.layers import Dense, Dropout, GRU
from keras.optimizers import Adam
from keras.regularizers import l1_l2
- データの読み込みと前処理
# データの読み込み
data = # ここにデータを読み込むコードを記載
# データの正規化
scaler = MinMaxScaler(feature_range=(0, 1))
data = scaler.fit_transform(data)
# データ分割用関数
def create_dataset(dataset, look_back=1):
x, y = [], []
for i in range(len(dataset) - look_back - 1):
x.append(dataset[i:(i + look_back), 0])
y.append(dataset[i + look_back, 0])
return np.array(x), np.array(y)
# ウィンドウサイズの設定
look_back = 60
# 時系列クロスバリデーションの設定
tscv = TimeSeriesSplit(n_splits=5)
- モデルの定義、学習、評価
# 時系列クロスバリデーションでモデルを学習・評価
for train_index, test_index in tscv.split(data):
x_train, x_test = data[train_index], data[test_index]
x_train, y_train = create_dataset(x_train, look_back)
x_test, y_test = create_dataset(x_test, look_back)
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
model = Sequential()
model.add(GRU(32, return_sequences=True, input_shape=(look_back, 1), kernel_regularizer=l1_l2(l1=1e-5, l2=1e-4)))
model.add(Dropout(0.4))
model.add(GRU(32, return_sequences=False, kernel_regularizer=l1_l2(l1=1e-5, l2=1e-4)))
model.add(Dropout(0.4))
model.add(Dense(1))
model.compile(optimizer=Adam(lr=0.001), loss='mean_squared_error')
history = model.fit(x_train, y_train, epochs=100, batch_size=64, validation_data=(x_test, y_test))
train_predict = model.predict(x_train)
test_predict = model.predict(x_test)
train_rmse = np.sqrt(mean_squared_error(y_train, train_predict))
test_rmse = np.sqrt(mean_squared_error(y_test, test_predict))
print(f"学習データのRMSE: {train_rmse}")
print(f"テストデータのRMSE: {test_rmse}")
上記のコードでは、GRUを使用し、ドロップアウトの割合を0.4に増やし、ウィンドウサイズを60に設定しました。さらに、時系列クロスバリデーションを用いてデータを分割し、モデルの学習・評価を行っています。 このコードを試して、学習データとテストデータのRMSEを確認し、改善策が効果を発揮しているかどうかを検証してみてください。ただし、市場の変動は多くの要因によって影響を受けるため、どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
少し修正を加えてもらう
最初のコードで存在していた「# 正規化の逆変換」に該当するコードがなくなってしまったので、少し修正を提案してみます。
すみません、正規化の逆変換部分を追加しました。以下のコードで、正規化を逆変換してRMSEを計算できます。
# 正規化の逆変換
train_predict = scaler.inverse_transform(train_predict)
y_train = scaler.inverse_transform([y_train])
test_predict = scaler.inverse_transform(test_predict)
y_test = scaler.inverse_transform([y_test])
# RMSEの計算
train_rmse = np.sqrt(mean_squared_error(y_train[0], train_predict[:, 0]))
test_rmse = np.sqrt(mean_squared_error(y_test[0], test_predict[:, 0]))
print(f"学習データのRMSE: {train_rmse}")
print(f"テストデータのRMSE: {test_rmse}")
さらなる改善後の結果の分析
学習データのRMSE: 13.70486076472181
テストデータのRMSE: 20.398845630998892
結果から、学習データのRMSEは約13.70、テストデータのRMSEは約20.40となっています。改善策を適用する前の結果と比較すると、学習データとテストデータのRMSEの差が若干縮まっています。これは、過学習がいくらか抑制されていることを示しているかもしれません。
ただし、完全に過学習が解消されたとは言い切れません。さらなる改善策を試すことが必要です。また、FXの価格予測は非常に困難なタスクであり、多くの要因が影響しています。どのようなモデルでも絶対的な予測は難しいことを念頭に置いておくことが重要です。
さらなる改善策としては、以下の方法が考えられます。
- ハイパーパラメータの調整: モデルの学習率、バッチサイズ、エポック数、正則化の係数など、さまざまなハイパーパラメータを調整することで、モデルの性能が向上する可能性があります。
- 特徴量エンジニアリング: さらに多くの技術指標やファンダメンタル分析に基づく特徴量を追加することで、モデルがより多くの情報を学習できるようになります。
- アンサンブル学習: 複数のモデルを組み合わせることで、それぞれのモデルの弱点を補完し、全体としての性能を向上させることができます。
最適なモデルを見つけるためには、これらの方法を試しながら繰り返し実験を行うことが重要です。
ここまでの流れのまとめ
以下の流れをChatGPTと一緒に進めてきました。こちらとしては、返ってきたコードを実行して、結果をまた渡して、コードを改善してもらって、の繰り返しを行なっているだけですので、それほど労力はかかっていません。これだけのことが少しの指示だけで実現出来てしまうのがChatGPTの素晴らしさですね。
- ディープラーニング(深層学習)を指定して、FXの価格予測を依頼
- Kerasを使ったLSTMモデルを選択してコードを作成
- 用意されたコードを実行して得られたRMSE結果を提示して、改善を依頼
- LSTM層のユニット数を50から32に減らしてモデルの複雑さを抑え、正則化を導入、モデルの層数は2層に減らすという改善策を提案
- 改善されたコードを実行して得られたRMSE結果を提示して、さらに改善を依頼
- ドロップアウトの割合を増やし、データのウィンドウサイズを調整し、時系列クロスバリデーションを導入、モデルとしてはGRUを使用、という改善策を提案
- 改善されたコードを実行して得られたRMSE結果を提示して、改善策が効果を発揮しているかどうかを検証を依頼
以上、いかがでしたでしょうか。
少し指示しただけで、LSTMやGRUの学習用のサンプルコードをすぐに提供してもらえました。
これまでですと、機械学習モデルのサンプルコードを掲載しているようなサイトはすぐには見つからず、もし見つかったとしても自分の環境と少し異なるだけでエラーが出てしまい、そのエラーの解決のためにまたGoogle検索を行なって原因を調べる、、、というようなプロセスが必要になっていた人が多いと思います。
それが、ChatGPTであればサンプルコードを簡単に提示してもらえて、もしエラーが出た場合はそのエラーの内容を伝えればコードを修正してくれて、改善を指示すれば対応してくれるだけでなく、自ら改善策を提案してくれるという、非常に学習効率が上がっていることがわかります。
次の記事では、今回最後にChatGPTが提案してくれた改善策をさらに試していきたいと思います。