Pythonでデータ分析:Prophetを使ってビットコインの予測(笑)をやってみる
導入
直近、これといって緊急の業務がなく、「自分の時間だ何勉強しようかなー」とPyStanとかをいじっていた矢先、「暇なら技術調査やってよ、Deep Learning的な何かとか」というお達しがきました。あいにく私は天邪鬼なので、2つ返事をして気になっていたけど触っていなかったProphetを調べることにしたのでした。
注:仕事はちゃんとしました(Seq2Seqの論文や書籍見て簡単な実装をしました)。
Prophet
Facebookが出した時系列予測のツールです。
facebook.github.io
すでに様々な方が紹介をしたり、Contributeしていたりするので、釈迦に説法感がありますが、このツールの良い点は、簡単に(分析の専門知識がなくても)ある程度それらしい予測値を出してくれるところです。ビジネス側でデータを活用したい場合や、分析者でもいったん簡単にデータから言えることを見てみる、といった場合に便利そうです。
というわけで、分析者としても抑えておきたいと前々から思っていたので、いい機会だと思って少し動かしてみました。一通りサンプルを見たあと、題材として何かあるかなと思って探していたところ、ビットコインのデータをPythonから取得できるライブラリを見つけたので、ビットコインを題材とすることにしました。
参考
- Giihub(メソッドの引数とか見るのに使った)
- ホクソエムさんの資料(最初に超見た)
データ取得
以下のコードを使います。
github.com
インストール方法はサイトに書かれています。pipが使えるなら
$ pip install https://github.com/s4w3d0ff/python-poloniex/archive/v0.4.6.zip
とすれば使用できる状態になるはずです。
データですが、以下のコードを実行すると、ビットコイン(US)のデータ(日次)を過去500日分取得してくれます。ざくっと紹介すると、polo.returnChartDataでデータを辞書型で取得しています。periodでどれくらいの間隔のデータかを指定(5分足なども指定できます)しています。ただ、時間がUNIX timeからの経過時間(秒)になっているので、後でよしなに変換しています。
# numpyやpandas import numpy as np import pandas as pd from pandas import DataFrame, Series # APIに関係するライブラリ import poloniex import time import datetime def getDataPoloniex(): polo = poloniex.Poloniex() polo.timeout = 2 chartUSDT_BTC = polo.returnChartData('USDT_BTC', period=polo.DAY, start=time.time() - polo.DAY * 500, end=time.time()) tmpDate = [chartUSDT_BTC[i]['date'] for i in range(len(chartUSDT_BTC))] date = [datetime.datetime.fromtimestamp(tmpDate[i]).date() for i in range(len(tmpDate))] data = [float(chartUSDT_BTC[i]['open']) for i in range(len(chartUSDT_BTC))] return [date, data] # データ取得 dat = getDataPoloniex() # DataFrameへ格納 df = DataFrame(dat).T df.columns = ['ds', 'y']
ちなみに、プロットすると以下のようになっています。
import matplotlib.pyplot as plt %matplotlib inline df.plot(x = df.columns[0], figsize = (15, 8))
途中で下落したりすれど、急成長しているような系列になっています。
Prophetによるモデル作成
ProphetはPythonの場合はpipで導入することができます。
pip install fbprophet
PyStanとか色々依存ライブラリがあるようなんですが、そういったものたちは先に入れとくといいのかもしれません。自分はすべて先に入っていたので比較ができませんが。
モデル構築はsklearnライクにできます。
mod = Prophet() mod.fit(df)
非線形トレンドを入れたり、変化点を考慮したりといろいろオプションはあるのですが、ここではよしなにできる感を演出するのに何も指定しないでおきます。線形トレンド以上の成長をしていそうな系列なので、ホントはちゃんと処理したいですけどね。
予測に関しては、make_future_dataframeとpredictで新たに生成した系列(100日分)に予測値を格納します。
future_df = mod.make_future_dataframe(periods = 100)
forecast_df = mod.predict(future_df)
簡単なプロットはProphetじたいにplotというメソッドがあり、それでよしなな図が見れます。
mod.plot(forecast_df) plt.show()
まあ、線形トレンド的な予測がされています。もっと長期まで予測しようと思ったら大まかな傾向(指数的)とは異なってくるとは思いますが、おおかなに上昇していきそうというのが捉えられている、としましょう。
もう少し細かい成分でプロットする機能もあります。
mod.plot_components(forecast_df)
週の上下している感を見ると
- 火曜日は上がり調子
- 水曜、木曜にかけて下がる
というホントかな、、という傾向が見られます。ちょっとこれは期間を変えて検証を繰り返す、とかしないと正確なことは何も言えません。ちなみに、他の記事では学習期間を変えると週の振る舞いは変わると言っているものもありますので、やはりこれから何かを主張するのは難しいのかもしれません。
感想
データがあるときに、チャチャッと分析をするのに便利です。これからは割りと使用するかもしれない、そう思われるツールでした。ただ、やはり適用限界はありそうなので、100%頼るというよりはできそうなところまで使ってみる、という付き合い方になるかなと思います。