AWS の AI で、とあるゲーム会社の株価を予測してみる

f:id:tercel_s:20210109134412p:plain:w300

今日は、CSV データを用意するだけで超お手軽に未来予測ができる Amazon Forecast を紹介するよ。

とりあえず AI を試してみたい(だけどどこから手をつけてよいか分からなくて困っている)人にはよさそう……?

でも具体的になにができるんだろ。

今日のテーマ

Amazon Forecast でスクウェア・エニックスの今後1ヶ月分の株価を予測してみよう。
※ この記事の内容によって生じたいかなる損失についても、筆者は責任を負いかねます。

ちょっと最初にやる気を出すために、完成品イメージを先に貼っておこう。

今年1月のスクエニの株価を Forecast で予測してみたよ。

f:id:tercel_s:20210109212058p:plain

これが僕にも作れるようになるのか……

実習の流れ

今回の手順は以下の 6手です。 ですが、そのうち 5つは超簡単で失敗のしようがないので*1、実質的な関門は CSV ファイルを用意するところだけとなります。

CSV ファイルを作る
CSV をアップロードするための S3エススリー バケットを作る(超簡単)
CSV を S3 にアップロードする(超簡単)
❹ S3 にアップロードした CSVForecastフォアキャスト にインポートする(超簡単)
そく (predictorプレディクタ) を作る(超簡単)
❻ 予測を行う(超簡単)

しかも、今回はその CSV データも本記事の最後の方に添付していますので、実質手間ゼロで手軽に Forecast を試すことができます。

CSV を作る

まずは、未来予測に必要な情報として、過去の実績データを CSV 形式で整形します。

Amazon Forecast には、さまざまな用途の時系列データを予測するためのデータセットドメインが用意されており、どれを選ぶかによって必要となる CSV 項目が少しずつ異なります。
参考: 事前定義済みのデータセットドメインとデータセットタイプ - Amazon Forecast

データセットドメイン 目的
RETAIL ドメイン 小売の需要予測
INVENTORY_PLANNING ドメイン サプライチェーンとインベントリの計画
EC2 CAPACITY ドメイン Amazon EC2 キャパシティの予測
WORK_FORCE ドメイン 従業員の計画
WEB_TRAFFIC ドメイン 今後のウェブトラフィックの見積もり
METRICS ドメイン 収益およびキャッシュフローなどの予測メトリクス
CUSTOM ドメイン その他すべての時系列予測のタイプ

今回は、上記のうち最も汎用性の高そうな CUSTOMカスタム ドメインを利用することにしましょう。

CUSTOM ドメインの場合、CSV には item_iddatetimetarget_value という 3つの項目が必要です。
参考: CUSTOM ドメイン - Amazon Forecast

また、予測したい評価項目が1つだけの場合、各行の item_id にはすべて同じ値を設定します。 あとで何を意味するデータだったのかが分かりやすいように、好きな文字列を設定しておきましょう(手順❻ で利用します)。

target_value には、各日のおわりを入れます。 すると、このような CSV が出来上がります(この記事の最後に、CSV データの完全版を掲載しています)。

f:id:tercel_s:20210109154722p:plain

取引のない土日祝日のデータが欠損しているけど(ピンクの矢印部分)、これはいいの?

大丈夫。

あとで予測子を作る際に補間するから問題ないよ。

ひとまずこれを 9684_2020.csv という名前で保存しました。

❷ S3 バケットを作る

続いて、Forecast が参照できるファイル置き場を用意する必要があります。

おなじみ Amazon Simple Storage Service(通称 S3エススリー)というサービスに「バケット」と呼ばれるファイル置き場を作ります。

AWS マネジメントコンソールにログインし、S3 のダッシュボードから「バケットを作成」をクリックします。

f:id:tercel_s:20210109160841p:plain

続いて、バケット名に一意の名前をつけて、「バケットを作成」をクリックします。

f:id:tercel_s:20210109161641p:plain
f:id:tercel_s:20210109162914p:plain

❸ S3 バケットCSV をアップロードする

先ほど作成した S3 バケットに、ローカルの CSV ファイルをアップロードします。

f:id:tercel_s:20210109204455p:plain

「アップロード」ボタン、もしくはファイルを直接ドラッグアンドドロップでアップロードが可能です。

f:id:tercel_s:20210109164729p:plain

アップロードが完了したら、CSV ファイル名のリンクをクリックして、「S3 URI」を確認しておきましょう。

f:id:tercel_s:20210109203902p:plain

CSV を Forecast にインポートする

AWS マネジメントコンソールから、Forecastダッシュボードを開き、「Create dataset group」をクリックします。

f:id:tercel_s:20210109165108p:plain

Dataset group name に任意の名前(ただし「-(ハイフン)」は使用不可)を、Forecasting DomainCustom をそれぞれ設定し、「Next」をクリックします。

f:id:tercel_s:20210109165929p:plain

さらに、Dataset name にも任意の名前を設定します。 ひとまず、スクエニの2020年の株価の推移データを取り込むので、square_enix_stock_2020 を指定しました。

Frequency of your data には、CSV の時系列データがどのくらいの間隔で記録されているかを指定します。 今回は、毎日の終値を記録したデータを用いますので、デフォルトの 1 day になります。

f:id:tercel_s:20210109170623p:plain

少しスクロールすると、データセットスキーマの設定を行うところがあります。 Timestamp format を、CSV に合わせて yyyy-MM-dd に変更しましょう。

f:id:tercel_s:20210109171352p:plain

さらにスクロールすると、Dataset import nameData locations を設定するところがあります。

Dataset import name には任意の名前を、Data locations には、手順❸ の最後で確認した「S3 URI」をそれぞれ設定します。

なお、タイムゾーンは利用しませんので、Select time zone はデフォルトの Do not use timezone のままとします。

f:id:tercel_s:20210109172107p:plain

IAM ロールの作成

さらに、Forecast から S3 へのアクセス権(IAMアイアム ロール)を設定します。

IAM ロールは、新規に作成することも、既存のものを利用することもできます。 今回は新規に作成しましょう。

IAM role のドロップダウンから Create a new role を選択します。

f:id:tercel_s:20210109172626p:plain

ここで、AWS アカウント内の全ての S3 バケットに対してアクセス権を付与するか、特定のバケットに対してのみアクセス権を付与するかどちらかを選ぶことができます。

今回は、手順❷ で作成したバケットに対するアクセス権のみを与えることにしました。

Create an IAM roleというモーダルダイアログボックスが起動しますので、ラジオボタンSpecific S3 buckets を選択し、テキストボックスに S3 のバケット名( tercel-square-enix-stock )を入力し、「Create role」ボタンを押してダイアログを閉じます。

f:id:tercel_s:20210109173247p:plain

すると、元の画面に IAM role が自動的に反映されますので、このまま「Start import」をクリックしましょう。 データのインポートが始まりますので、このまましばらく待ちましょう。

f:id:tercel_s:20210109173908p:plain

❺ 予測子を作る

データセットのインポートが終わると、ダッシュボードの Import your data - Target time series data のステータスが「 Active」に変わります。

さらに、Training a predictor - Predictor training にオレンジ色の「Start」ボタンが出現しますので、クリックします。

f:id:tercel_s:20210109175829p:plain

ここから、予測子の作成に必要な設定をしていきます。 まず、Predictor name には好きな名前を入れてください。

次に、予測の周期 (Forecast frequency) と期間 (Forecast horizon) を設定します。

たとえば、Forecast frequency1 day の場合は、1日単位で予測が行われます。

Forecast horizon には、その周期を何回くりかえすかを設定します。

よって、もしForecast frequency1 dayForecast horizon30 と設定した場合は、おおよそ1ヵ月分、毎日の株価予想が得られることになります。

f:id:tercel_s:20210109181110p:plain

予測アルゴリズムの選択

少しスクロールすると、詳細の設定項目が現れます。

Algorithm selection では、Automatic (AutoML)Manual のいずれかを選べます。 Manual を選択した場合、さらに具体的な予測アルゴリズムを選択することになります。

デフォルト値である Automatic (AutoML) は、Forecast が各アルゴリズムを評価した上で最適なものを自動選択してくれますので、通常はこちらを選んでおけばまず問題はないでしょう。

f:id:tercel_s:20210109182041p:plain

欠損データの補間設定

さらに、折り畳まれている Advanced configurations を展開します。

ここで、元の CSV データには土日祝や年末年始など、取引が行われなかった日のデータが欠損していたことを思い出してください。

これらの欠損データは、デフォルトでは「0」として扱われてしまいます。

とはいえ取引が行われないからといって、実際に株価が暴落しているわけではないため、欠損データをその前後の実績で適当にならしてやる必要があります。

今回は、JSONmiddlefill, backfill いずれにも、mean を設定しました。

より詳細な解説は、以下の公式記事を参照してください。
参考: Amazon Forecast がサポートする自動補完機能による、ターゲットおよび関連データセット内での欠落した値の管理 | Amazon Web Services ブログ

f:id:tercel_s:20210109183059p:plain

一番下までスクロールして「Train predictor」をクリックしましょう。 予測子の作成が始まります。

f:id:tercel_s:20210109184348p:plain

ちなみに、予測子の作成には数十分〜数時間かかることもあるよ。

おぉぅ…

なので、CSV データは随時更新するけど、予測子は一度運用が始まったら、そうそう作り直したりはしない。

作り直すのはどんなとき?

予測に使えるパラメータが増えたり減ったりしたときとか、実際運用してみたらあまりにも予測精度が悪すぎて使い物にならなかったりしたときは見直すかもね。

なるほど。

参考: Amazon Forecastでオプションのデータセットを追加して時系列予測を改善する

❻ 予測を行う

予測子の作成が完了すると、データセットのインポートが終わると、ダッシュボードの Train a predictor - Predict training のステータスが「 Active」に変わります。

さらに、Generate forecasts - Forecast generation にオレンジ色の「Start」ボタンが出現しますので、クリックします。

f:id:tercel_s:20210109194112p:plain

Create a forecast 画面が表示されますので、Forecast name に適当な予測の名前(square_enix_stock_forecast)、Predictor には使用する予測子として先ほど作成した square_enix_stock_predictor をそれぞれ設定します。

Forecast typesは任意項目で、分位点回帰を指定します。 株価は突然こうとうしたり暴落したりしますので、おおよそ「このくらいの範囲で変動するだろう」という予測範囲の両裾を指定できるのです。

Forecast はデフォルトで 0.5(中央)および 0.1, 0.9 が指定されており、下振れした値から上振れした値まであたりをつけることができます。 今回はデフォルトのまま(何も入力せず)「Create new forecast」をクリックし、しばらく待ちます。

f:id:tercel_s:20210109201505p:plain

すると画面が切り替わり、ダッシュボードに「Lookup forecast」ボタンが出現しますのでクリックします。

f:id:tercel_s:20210109210619p:plain

Forecast に、先ほど作成した予測の名前(square_enix_stock_forecast)、Start dateEnd date に表示期間の範囲、そして Choose the keys you want to use to filter your forecasts. - Value に、手順❶ の CSVitem_id に設定した値を入力し、「Get Forecast」をクリックします。

f:id:tercel_s:20210109211114p:plain

ちなみに、Start dateEnd date に指定できる日付は、予測子を作成するときに指定した周期と期間によって決まります。

今回は 2020-12-30 までのデータを使い、周期を 1日、期間を 30に設定しましたので、 2021-01-29 まで予測できることになります。

万事うまくいくと、株価の予測グラフが表示されます。おめでとうございます。

f:id:tercel_s:20210109211750p:plain

はい、おしまい。

すごい、プログラムを1行も書かず機械学習を試食できた……

これ、センサーから収集した時系列データとかを食わせたら楽しそうだよね。

現状をグラフ化するだけじゃなくて、未来予知までできたら次のアクションも自動化できそう。

夢が広がるね。

おまけ

昨年1年間のスクウェア・エニックス(銘柄コード: 9684)の株価(おわりCSVデータ

item_value,datetime,target_value
square_enix,2020-01-06,5270
square_enix,2020-01-07,5440
square_enix,2020-01-08,5370
square_enix,2020-01-09,5500
square_enix,2020-01-10,5670
square_enix,2020-01-14,5680
square_enix,2020-01-15,5430
square_enix,2020-01-16,5460
square_enix,2020-01-17,5480
square_enix,2020-01-20,5560
square_enix,2020-01-21,5520
square_enix,2020-01-22,5550
square_enix,2020-01-23,5540
square_enix,2020-01-24,5570
square_enix,2020-01-27,5520
square_enix,2020-01-28,5400
square_enix,2020-01-29,5420
square_enix,2020-01-30,5280
square_enix,2020-01-31,5380
square_enix,2020-02-03,5410
square_enix,2020-02-04,5490
square_enix,2020-02-05,5610
square_enix,2020-02-06,5200
square_enix,2020-02-07,5160
square_enix,2020-02-10,5200
square_enix,2020-02-12,5000
square_enix,2020-02-13,5040
square_enix,2020-02-14,5030
square_enix,2020-02-17,5010
square_enix,2020-02-18,4910
square_enix,2020-02-19,4975
square_enix,2020-02-20,4960
square_enix,2020-02-21,4945
square_enix,2020-02-25,4725
square_enix,2020-02-26,4660
square_enix,2020-02-27,4490
square_enix,2020-02-28,4350
square_enix,2020-03-02,4505
square_enix,2020-03-03,4530
square_enix,2020-03-04,4685
square_enix,2020-03-05,4680
square_enix,2020-03-06,4665
square_enix,2020-03-09,4395
square_enix,2020-03-10,4465
square_enix,2020-03-11,4260
square_enix,2020-03-12,4130
square_enix,2020-03-13,3920
square_enix,2020-03-16,3935
square_enix,2020-03-17,4225
square_enix,2020-03-18,4475
square_enix,2020-03-19,4760
square_enix,2020-03-23,4260
square_enix,2020-03-24,4680
square_enix,2020-03-25,4570
square_enix,2020-03-26,4570
square_enix,2020-03-27,4600
square_enix,2020-03-30,4845
square_enix,2020-03-31,4825
square_enix,2020-04-01,4800
square_enix,2020-04-02,4955
square_enix,2020-04-03,4965
square_enix,2020-04-06,5060
square_enix,2020-04-07,5000
square_enix,2020-04-08,4945
square_enix,2020-04-09,4930
square_enix,2020-04-10,4895
square_enix,2020-04-13,4950
square_enix,2020-04-14,4970
square_enix,2020-04-15,5130
square_enix,2020-04-16,5130
square_enix,2020-04-17,4995
square_enix,2020-04-20,4815
square_enix,2020-04-21,4695
square_enix,2020-04-22,4425
square_enix,2020-04-23,4525
square_enix,2020-04-24,4490
square_enix,2020-04-27,4530
square_enix,2020-04-28,4625
square_enix,2020-04-30,4405
square_enix,2020-05-01,4420
square_enix,2020-05-07,4535
square_enix,2020-05-08,4545
square_enix,2020-05-11,4675
square_enix,2020-05-12,4835
square_enix,2020-05-13,4950
square_enix,2020-05-14,4720
square_enix,2020-05-15,4770
square_enix,2020-05-18,4705
square_enix,2020-05-19,4740
square_enix,2020-05-20,4820
square_enix,2020-05-21,4875
square_enix,2020-05-22,4955
square_enix,2020-05-25,5060
square_enix,2020-05-26,5000
square_enix,2020-05-27,5140
square_enix,2020-05-28,5230
square_enix,2020-05-29,5230
square_enix,2020-06-01,5240
square_enix,2020-06-02,5300
square_enix,2020-06-03,5270
square_enix,2020-06-04,5270
square_enix,2020-06-05,5300
square_enix,2020-06-08,5310
square_enix,2020-06-09,5270
square_enix,2020-06-10,5460
square_enix,2020-06-11,5590
square_enix,2020-06-12,5450
square_enix,2020-06-15,5440
square_enix,2020-06-16,5530
square_enix,2020-06-17,5580
square_enix,2020-06-18,5640
square_enix,2020-06-19,5610
square_enix,2020-06-22,5610
square_enix,2020-06-23,5530
square_enix,2020-06-24,5500
square_enix,2020-06-25,5450
square_enix,2020-06-26,5510
square_enix,2020-06-29,5450
square_enix,2020-06-30,5440
square_enix,2020-07-01,5400
square_enix,2020-07-02,5450
square_enix,2020-07-03,5490
square_enix,2020-07-06,5500
square_enix,2020-07-07,5570
square_enix,2020-07-08,5490
square_enix,2020-07-09,5810
square_enix,2020-07-10,5520
square_enix,2020-07-13,5550
square_enix,2020-07-14,5450
square_enix,2020-07-15,5640
square_enix,2020-07-16,5450
square_enix,2020-07-17,5540
square_enix,2020-07-20,5760
square_enix,2020-07-21,5880
square_enix,2020-07-22,5870
square_enix,2020-07-27,5820
square_enix,2020-07-28,5780
square_enix,2020-07-29,5740
square_enix,2020-07-30,5670
square_enix,2020-07-31,5640
square_enix,2020-08-03,5700
square_enix,2020-08-04,5990
square_enix,2020-08-05,6050
square_enix,2020-08-06,6130
square_enix,2020-08-07,6890
square_enix,2020-08-11,6450
square_enix,2020-08-12,6430
square_enix,2020-08-13,6530
square_enix,2020-08-14,6740
square_enix,2020-08-17,6750
square_enix,2020-08-18,6920
square_enix,2020-08-19,6940
square_enix,2020-08-20,6940
square_enix,2020-08-21,6940
square_enix,2020-08-24,7150
square_enix,2020-08-25,7030
square_enix,2020-08-26,6980
square_enix,2020-08-27,7060
square_enix,2020-08-28,6850
square_enix,2020-08-31,6990
square_enix,2020-09-01,7120
square_enix,2020-09-02,7210
square_enix,2020-09-03,7320
square_enix,2020-09-04,7240
square_enix,2020-09-07,6900
square_enix,2020-09-08,6690
square_enix,2020-09-09,6710
square_enix,2020-09-10,6770
square_enix,2020-09-11,6670
square_enix,2020-09-14,6670
square_enix,2020-09-15,6750
square_enix,2020-09-16,6990
square_enix,2020-09-17,6860
square_enix,2020-09-18,6840
square_enix,2020-09-23,6910
square_enix,2020-09-24,6810
square_enix,2020-09-25,6990
square_enix,2020-09-28,6930
square_enix,2020-09-29,7010
square_enix,2020-09-30,6960
square_enix,2020-10-02,6890
square_enix,2020-10-19,6620
square_enix,2020-10-20,6470
square_enix,2020-10-21,6280
square_enix,2020-10-22,6440
square_enix,2020-10-23,6190
square_enix,2020-10-26,6080
square_enix,2020-10-27,6210
square_enix,2020-10-28,6230
square_enix,2020-10-29,6470
square_enix,2020-10-30,6120
square_enix,2020-11-02,6120
square_enix,2020-11-04,6200
square_enix,2020-11-05,6470
square_enix,2020-11-06,6470
square_enix,2020-11-09,5560
square_enix,2020-11-10,5150
square_enix,2020-11-11,5270
square_enix,2020-11-12,5520
square_enix,2020-11-13,5610
square_enix,2020-11-16,5490
square_enix,2020-11-17,5350
square_enix,2020-11-18,5340
square_enix,2020-11-20,5360
square_enix,2020-11-24,5630
square_enix,2020-11-25,5790
square_enix,2020-11-26,6020
square_enix,2020-11-27,6160
square_enix,2020-11-30,6410
square_enix,2020-12-01,6350
square_enix,2020-12-02,6300
square_enix,2020-12-03,6170
square_enix,2020-12-04,6350
square_enix,2020-12-07,6270
square_enix,2020-12-08,6460
square_enix,2020-12-09,6430
square_enix,2020-12-10,6330
square_enix,2020-12-11,6490
square_enix,2020-12-14,6440
square_enix,2020-12-15,6420
square_enix,2020-12-16,6450
square_enix,2020-12-17,6650
square_enix,2020-12-18,6590
square_enix,2020-12-21,6470
square_enix,2020-12-22,6060
square_enix,2020-12-24,6220
square_enix,2020-12-25,6150
square_enix,2020-12-28,6160
square_enix,2020-12-30,6260

*1:その代わり、待ち時間がめちゃくちゃ長い。

Copyright (c) 2012 @tercel_s, @iTercel, @pi_cro_s.