LSTMによる株価予測

機械学習は、ここ数年、多くの興味深い分野でその応用を見いだしている。 株式市場の制御もその一つです。 私は以前から、LSTM の知識を深めるために、LSTM を試してみようと思っていました。

Motivation and Target Audience

私は、一連のブログで私の経験について書きます。 この連載の目的は、LSTMや機械学習の概念の基本を説明することではありません。 したがって、読者は機械学習の旅を始めており、Python、SkLearn、Keras、LSTMなどの基本的な知識を持っていることを想定します。 なぜなら、「LSTMはどのように働くのか」といったトピックについては、その背後にある数学について説明する資格がある人たちによる優れた記事がすでにあるからです。 しかし、私は、背景知識が不足していると思われるところには、そのような記事へのリンクを共有するつもりです。 あるデータセットからどのように株価を予測するかという記事はたくさんありますが、ほとんどの著者はどのようにしてニューラルネットワークの特定の設定に至ったか、あるいはどのようにしてハイパーパラメータの特定のセットを選択したかを明らかにしていません。 そこで、この記事の本当の目的は、そのような手順、私の失敗、そして私が非常に役に立ったと思う手順を共有することです。

ここで見ていくのは、

  1. データの読み込みと分析です。 (Pandas)
  2. データを正規化する。 (SkLearn)
  3. データを時系列に変換し、教師あり学習問題を解く。
  4. モデルを作成する(Keras)
  5. モデルを微調整する(次回)
  6. 学習、予測、結果の可視化を行う。
  7. Tips &非常に役に立ったツール(連載最終回)

なお、この最初の記事では、LSTMの前処理ステップと用語について述べています。

Let’s begin!

データの読み込みと分析

この記事では、GEの過去の株価データを使用することにします。 データは、私のkaggleサイトのここにあります。 かなり前にダウンロードしたものなので、データの出所は覚えていません。

df_ge = pd.read_csv(os.path.join(INPUT_PATH, "us.ge.txt"), engine='python')
df_ge.tail()

ご覧のように約14060項目あり、それぞれがその企業の1日の株式市場の属性を表しています。

from matplotlib import pyplot as pltplt.figure()
plt.plot(df_ge)
plt.plot(df_ge)
plt.plot(df_ge)
plt.plot(df_ge)
plt.title('GE stock price history')
plt.ylabel('Price (USD)')
plt.xlabel('Days')
plt.legend(, loc='upper left')
plt.show()

Open, Close, Low, High は、時々 Low 価格がわずかに下がる以外は互いにあまり変化しないようですね。

さて、次は出来高のプロットを確認してみましょう :

plt.figure()
plt.plot(df_ge)
plt.title('GE stock volume history')
plt.ylabel('Volume')
plt.xlabel('Days')
plt.show()

ふむふむ。 何か面白いものでも見たんですか? タイムラインの12000日目あたりで取引数がかなり急増していますが、これは偶然にも株価の急落に重なります。 その特定の日付に戻り、古いニュース記事を掘り起こして、その原因を見つけることができるかもしれません。

さて、心配するような null/Nan 値があるかどうかを見てみましょう。 結論から言うと、NULL 値はありません。 素晴らしい!

print("checking if any null values are present\n", df_ge.isna().sum())

データの正規化

データは正規化しておらず、各列の範囲もバラバラ、特にVolumeは顕著です。 データを正規化することは、アルゴリズムの収束、すなわち、ローカル/グローバル最小値を効率的に見つけるのに役立ちます。 Sci-kit LearnのMinMaxScalerを使用します。 しかしその前に、データセットをトレーニング用とテスト用に分割する必要があります。 また、その過程でDataFrameをndarrayに変換します。

Converting data to time-series and supervised learning problem

これは非常に重要で、ややトリッキーです。 ここで、知識LSTMが必要になるのです。 ここで必要なキーコンセプトについて簡単に説明しますが、LSTMに関する最高のリソースの1つとされるAndre karpathyのブログはこちら、そしてこちらを読むことを強くお勧めします。

LSTM は 3 次元配列の形式で入力を受け取ります。

  • Batch Size は、重みを更新する前にニューラルネットに何サンプルの入力を表示させるかを指定します。 例えば、100個のサンプル(入力データセット)があり、NNが入力を見るたびに重みを更新したいとしましょう。 この場合、バッチサイズは 1 となり、バッチの総数は 100 となります。 同様に、ネットワークがすべてのサンプルを見た後に重みを更新したい場合は、バッチサイズは100、バッチ数は1になります。 バッチサイズが小さいと学習速度が低下し、逆にバッチサイズが大きすぎると(データセット全体のように)異なるデータに対するモデルの汎化能力が低下し、メモリ消費量も多くなります。 しかし、目的関数の最小値を見つけるためのステップ数は少なくなります。 そのため、データに対して様々な値を試し、スイートスポットを見つけなければなりません。 なかなか大きなテーマですね。 次回は、よりスマートな方法でこれらを検索する方法を見ていきます。
  • 時間ステップは、ネットワークに表示させたい時間の単位を定義します。 例えば、文字予測の問題に取り組んでいて、学習するテキスト・コーパスがあり、ネットワークに一度に6文字を与えると決めたとします。 この場合、時間ステップを60とする。つまり、2ヶ月分のデータを見て、翌日の価格を予測することになる。 詳細は後述します。
  • Featuresは、各タイムステップを表現するために使用される属性の数です。 上の文字予測の例で、各文字を表すためにサイズ100のワンホットエンコードベクトルを使うとする。

さて、用語の整理がある程度できたところで、ストックデータを適切な形式に変換してみましょう。 簡単のために時間ステップを3とします(ネットワークが3日分のデータを振り返って4日目の価格を予測したい)。するとデータセットは以下のようになります。

サンプル0から2が最初の入力、サンプル3の終値がその出力値となり、どちらも緑の四角で囲まれています。 同様に、サンプル1から3が2番目の入力で、サンプル4の終値が出力値となり、青色の長方形で囲まれます。 という具合です。 3は時間ステップ、5は特徴量の数です。 では、このような入出力ペアは、上の画像でいくつ考えられるでしょうか? 4.

これにバッチサイズも混ぜてみましょう。 バッチサイズを2とすると、入出力ペア1(緑の長方形)とペア2(青の長方形)がバッチ1を構成することになります。 という具合になる。 これを行うための Python コードスニペットです:

‘y_col_index’ は、出力列のインデックスです。 さて、上記のようにデータを教師あり学習形式に変換した後、トレーニングデータセットに41サンプルがあり、バッチサイズが20だとすると、トレーニングセットをトリミングして取り残された奇妙なサンプルを削除する必要があります。

さて、上記の関数を使って、訓練、検証、テストのデータセットを作成しましょう

x_t, y_t = build_timeseries(x_train, 3)
x_t = trim_dataset(x_t, BATCH_SIZE)
y_t = trim_dataset(y_t, BATCH_SIZE)
x_temp, y_temp = build_timeseries(x_test, 3)
x_val, x_test_t = np.split(trim_dataset(x_temp, BATCH_SIZE),2)
y_val, y_test_t = np.split(trim_dataset(y_temp, BATCH_SIZE),2)

さて、データの準備ができたので、モデルの構築に集中しましょう。 LSTM モデルの作成は次のように簡単です。

さて、モデルをコンパイルして、学習する準備ができたら、次のように学習します。 エポック数やバッチ サイズなどのパラメータにどのような値を使用するかについて悩んでいる場合、心配しないでください。

このモデルをトレーニングすると、(微調整したハイパーパラメータで)最高のエラー 3.27e-4 と最高の検証エラー 3.7e-4 になりました。 トレーニングの損失と検証の損失は以下のようになりました:

Training error vs Validation error

上記モデルでの予測はこのような感じとなりました。

prediction vs real data

この LSTM の設定は、(このデータセットで)私が100以上試した組み合わせの中で最もうまくいくことがわかっています!LSTM の設定と、このデータセットでの予測は同じです。 そこで問題は、ニューラルネットワークの完璧な (あるいは、ほとんどすべての場合において完璧に近い) アーキテクチャをどのように見つけるかです。 3266>

NOTE: 読者への謙虚なお願い – LinkedIn や Twitter で私とつながることは歓迎しますが、私のブログに関して質問がある場合は、個人のメッセージではなく、それぞれのブログのコメント セクションに投稿してください。 ただし、ブログとは関係ない問い合わせや、一般的な技術的な問い合わせは、個人的に私宛に送っていただいても結構です。 ありがとうございます 🙂

UPDATE 13/4/19

  1. この記事を書いてから、このブログに使用した私のモデルがオーバーフィットしていたかもしれないことを知りました。 確認したわけではありませんが、その可能性は高いです。 そのため、プロジェクトでこれを実装する際には注意してください。 より少ないエポック、より小さいネットワーク、より多くのドロップアウトなどを試すことができます。
  2. I have used Sigmoid activation for last layer which may suffer with limitation of not able to predict a price greater than ‘max’ price in dataset.これは、データセット内の価格を予測できない制限に苦しんでいます。
  3. 「データを時系列に変換する」セクションのタイプミスを修正しました。

これらを知らせてくれた読者に感謝します。

UPDATE 21/1/2020

コメントを残す

メールアドレスが公開されることはありません。