株価予想AIの作り方 AIプログラミング編
目次
はじめに
本記事では、株価を予想するAI(人工知能)の作り方を紹介しています。
今回は、AIの本体となるプログラムを行います。
プログラムの実行には、以下の過去記事で紹介しているデータが必要になりますので、必要に応じて参照ください。
また、対象としている方は、プログラムに馴染みのない方を想定しています。詳しい方にとっては、説明に正確性を欠くと感じる部分もあるかと思いますが、なるべく平易な書き方にしたいと考えたためですので、ご容赦ください。
mycrofton.hatenablog.com
mycrofton.hatenablog.com
プログラミング
それでは、さっそくAIをプログラミングしてみましょう。プログラムが全く分からない方向けに、プログラム全文を掲載しているので安心してください。
プログラムファイルを作成する
まずは、プログラムファイルを作成します。
株価データの収集用プログラムを作成したフォルダと同じフォルダに、好きな名前のプログラムファイルを作成してください。(株価データ収集用のプログラムとは別の名前にしてください)
ここでは、「stock_ai.py」というファイルを作成したこととして、以降説明していきます。
過去記事に記載のファイル名で作成していただいている方の場合、以下のようなファイルが生成されていることになります。
プログラミング
作成したプログラムファイルを開いて、以下のコードをコピー&ペーストしてください。
from keras import layers from keras import models from keras import optimizers from keras.callbacks import ModelCheckpoint from keras.preprocessing.image import ImageDataGenerator import matplotlib.pyplot as plt import os import math data_dir = 'data/chart' #データフォルダの名前 base_dir = "data/" #ログ出力用 def_batch_size = 1 #バッチサイズ #データの偏りを重みで表現 def weight(classes_name, dir_name): data_element_num = {} max_buf = 0 for class_name in classes_name: class_dir = dir_name + os.sep + class_name files = os.listdir(class_dir) data_element_num[class_name] = len(files) if max_buf < len(files): max_buf = len(files) weights = {} count = 0 for class_name in classes_name: weights[count] = round(float(math.pow(data_element_num[class_name]/max_buf, -1)), 2) count = count + 1 return weights #モデルの定義 model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(256, 256, 1))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.Conv2D(128, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Dropout(0.5)) model.add(layers.Conv2D(256, (3, 3), activation='relu')) model.add(layers.Conv2D(512, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Dropout(0.5)) model.add(layers.Conv2D(512, (3, 3), activation='relu')) model.add(layers.Flatten()) model.add(layers.Dense(512, activation='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer=optimizers.Adam(lr=1e-4), metrics=['acc']) #検証用データ(validation_split)を0.3で設定 datagen = ImageDataGenerator(validation_split=0.3, rescale=1./255) #学習用データ train_generator = datagen.flow_from_directory( data_dir, batch_size=def_batch_size, class_mode='binary', target_size=(256, 256), color_mode='grayscale', subset='training') #検証用データ validation_generator = datagen.flow_from_directory( data_dir, batch_size=def_batch_size, class_mode='binary', target_size=(256, 256), color_mode='grayscale', subset='validation') for data_batch, labels_batch in train_generator: print('data batch shape:', data_batch.shape) print('labels batch shape:', labels_batch.shape) break fpath = base_dir + 'chart.{epoch:02d}.h5' modelCheckpoint = ModelCheckpoint(filepath = fpath, monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='min', save_freq='epoch') class_weights = weight(classes_name = ['down', 'up'], dir_name = data_dir) print('class weight:', class_weights) history = model.fit( train_generator, steps_per_epoch=train_generator.samples // def_batch_size, validation_data = validation_generator, epochs = 100, validation_steps=validation_generator.samples // def_batch_size, class_weight=class_weights, callbacks=[modelCheckpoint]) acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(len(acc)) fig = plt.figure() plt.plot(epochs, acc, 'bo', label='Training acc') plt.plot(epochs, val_acc, 'b', label='Validation acc') plt.title('Training and validation accuracy') plt.legend() plt.savefig(base_dir + 'accuracy.png') plt.close() fig = plt.figure() plt.plot(epochs, loss, 'bo', label='Training loss') plt.plot(epochs, val_loss, 'b', label='Validation loss') plt.title('Training and validation loss') plt.legend() plt.savefig(base_dir + 'loss.png') plt.close()
プログラムを動かしてみる
プログラミングが終わったら、さっそくプログラムを動かしてみましょう。コマンドプロンプトを起動して、作業中のフォルダに移動し、「python stock_ai.py」で実行できます。コマンドプロンプトの起動方法がわからない方は、過去記事を参照してください。
どうでしょうか。過去記事を読んでいただいている方にはお馴染みですが、変なメッセージが表示されたと思います。
プログラムを動かすための準備が足りていないためです。
追加準備をしていきましょう。コマンドプロンプトで「pip install keras」と入力します。
続いて、同じくコマンドプロンプトで「pip install tensorflow」と入力します。こちらは先ほどの「pip install keras」よりも時間がかかるかもしれませんが、気長にお待ちください。コマンドプロンプトに文字が入力できるようになれば、終了です。
追加準備が終わったら、もう一度プログラムを実行してみてください。
(繰り返しになりますが)実行方法は、「python stock_ai.py」で実行です。
今度はうまくいくと思います。以下のような画面になったら、AIが学習を始めた証拠です。
ただし、このAIの学習は非常に時間がかかるのでご注意ください。収集したデータの数やお使いのパソコンのスペックによっても異なりますが、1銘柄のデータだけでも数時間かかる可能性がありますので、お時間に余裕があるときに実行することをお勧めします。
コマンドプロンプトに文字が入力できるようになったら、AIの学習は終わりました。
いかがでしたか?AIの学習自体は非常に簡単(だけれども、とても時間はかかる)ということがお分かりいただけたのではないでしょうか。
結果を確認してみる
AIの学習が終わったので、結果を確認してみましょう。
dataフォルダの中身をみてください。「chart.xx.h5」(xxには数字が入ります)というファイルができていると思います。このファイルがAI本体であり、学習した結果の知能がコンピュータ情報として格納されています。
このファイルの中身を説明すると難しい話になるので、今回の記事では割愛させていただきます。機会があれば別記事にまとめたいと思います。
そうはいっても、AIがちゃんと学習できたか気になりますよね。AIの学習状況については、グラフを出力するようにプログラムされているので安心してください。
学習状況を示すグラフは、「accuracy.png」です。横の軸は学習回数(右に行くほど学習回数が多い)、縦の軸は精度(上に行くほど精度が高い)ことを示しています。精度というのは、与えたデータを正しく分類できた(株価が上がるか・下がるか予想できた)ことを指します。
Training accとValidation accという2つのグラフがあるのは、AIを学習させるときに、収集したデータを以下のように2つにわけておき、それぞれの精度を出しているためです。
- 学習用データ(Training data):AIが繰り返し勉強する問題
- 検証用データ(Validation data):学習した結果、本当に理解しているか確認するための類似問題
上にあげた例のグラフの場合、学習用データ(すなわち、繰り返し勉強した問題)は正しく答えられるようになってきています(Training acc)が、検証用データ(勉強したことのある問題に類似した問題)は、正解率(Validation acc)が低いですね。
見たことのある問題と完全に同じであれば解けるけど、少し変えられたとたんに解けなくなる。
って、人間の勉強でもありがちですよね。上の例のAIはまさにそんな状態になっています。
では、どうするか、という点についてですが...
グラフを見ながら試行錯誤するのが一般的ですが、結果グラフの見方についても、詳細は難しい話になるので、今回の記事では割愛します。グラフを見ると学習の状態がわかるので、グラフを見ながらAIのプログラムを行ったりするのですが、紹介は別の機会とさせてください。
また、実はもう1つグラフ(loss.png)が作成されているのですが、このグラフについても難しい話になるので説明は割愛したいと思います。
次回に向けて
今回で、やっとAIを学習させることまではできました。次は、AIを使って実際に株価予想を行う方法について紹介したいと思います。
また、いままでの記事で紹介したプログラムを動かした方は感じているかもしれませんが、AIの学習やデータ収集に非常に時間がかかるという課題があります。
お使いのパソコンをAIのためだけに、終夜動かしておくのも電気代がかかったり、留守中に動かし続けるのも気になる、など、色々な点で気になると思いますので、AIを使った株価予想をまで紹介した後は、もう少し実用的にAIの学習やデータ収集を行うためのトピックスを紹介していきたいと思っています。