見出し画像

Facebookが開発した時系列データ分析ツール「Prophet」を使って東京都新規感染者数の予測をしてみよう

データ分析の醍醐味でもあり目的ともいうべき「予測」にトライする

先に言っておくと、個人的には今回のやり方での予測はあまりあてにできないと思っている。というのも、データ分析のアプローチ方法はいくつもあるのだが、こと「時系列データ」の分析に関しては、どちらかというと「Machine Learningアプローチ」よりもトラディショナルな「統計学アプローチ」の方が精度が高いのではないかという説が、最近気になっている。 おそらくMachine Learningの本業はClassification(つまりクラス分け)であって、ファイナンスデータなどの時系列データを予測するには、トラディショナルな統計学アプローチの方が最短ルートなのではないだろうか。
ということで、今回行うのはMLアプローチなので、あまり精度が高くないと思っている。

予測するのは東京都新規感染者数

また、今回予測するのは東京都の新規感染者数だ。ランダムウォークする株価などとは性質が異なるデータだ。
データが正規分布にもとづいているのか、定常性条件を満たしているのかは検証せずに、生きた時系列データを用いて将来を予測する。

Facebookが開発したお手軽時系列データ分析・予測ツール「Prophet」を使用する。 当然、R派もPython派もプロもアマも使える便利仕様だ。
コードを描く前に是非ともコマンドで `pip install fbprophet `を叩いて準備しておいてもらいたい。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="darkgrid")
import pandas as pd
import numpy as np
import statistics
import pprint
import datetime
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('ggplot')


row_data = pd.read_csv('https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients.csv')
by_day = row_data.groupby('公表_年月日')


dates = []
counts = []
for bd in by_day:
   dates.append(bd[0])
   counts.append(len(bd[1]))
   
# column名を指定する必要があるのに注意
daily_cases = pd.DataFrame({
   'ds':dates,
   'y':counts
})

# 日付をdatetimeに変換する
datetimes = []
for d in daily_cases.ds.values:
   datetimes.append(datetime.datetime.strptime(d, '%Y-%m-%d'))
daily_cases.ds = datetimes

# Prophetを利用した予測
from fbprophet import Prophet
from fbprophet.plot import add_changepoints_to_plot

# ここは本日の数字がまだ反映されてない場合のみ
# 今日の日付と感染者数だけ変える
# case_today = pd.DataFrame([['2020-07-04'], [131]]).T
# case_today.columns = daily_cases.columns
# daily_cases.append(case_today, ignore_index=True)

# Prophetを利用した予測

from fbprophet import Prophet
from fbprophet.plot import add_changepoints_to_plot

# MLでお馴染みパラメータチューニング次第で分析の精度が変わる
# トレンドが変化するタイミングを調整することができる
model = Prophet(
   changepoint_range=1,
   changepoint_prior_scale=20,
   daily_seasonality=False,
   weekly_seasonality=True,
   yearly_seasonality=False
)
model.fit(daily_cases)

# 7日間の予測をしてみる
future_df = model.make_future_dataframe(7, freq='D')
forecast_df = model.predict(future_df)

# プロットする
model.plot(forecast_df)
plt.show()​


スクリーンショット 2020-07-04 21.32.23

1週間以内にピークを超える予測が出た。

# パラメータチューニングで調整した「トレンドの転換点」を表す
fig = model.plot(forecast_df)
a = add_changepoints_to_plot(fig.gca(), model, forecast_df)

スクリーンショット 2020-07-04 21.34.06

# 全体のトレンドと曜日によるトレンドに分解したものを図示
model.plot_components(forecast_df)

スクリーンショット 2020-07-04 21.35.00

結局明日は何人報告される予測なのか

直近10日の予測データをのぞいてみよう。

forecast_df[-10:]

予測値である最終column、"yhat"の値は126.211193人とのこと。

スクリーンショット 2020-07-04 21.37.39

一方 columns[['yhat_lower', 'yhat_upper']] から予測値の95%信頼区間も示されており、103.783513人〜149.193671 人だそう。ただし、足元で東京都の新規感染者数の推移は急増トレンドに入ったとみられる。Prophetはあくまでも「現在のトレンドが明日以降も継続した場合」の予測しか出せないので、予防線を張るわけではないがこのタイミングではブレが出やすいだろう。

いずれにせよ、この自分が作ったモデルが合っているか、答え合わせは随時行う必要がある。 また、今回はファイナンスデータではないデータを用いたが、これがファイナンスデータ(夢はもちろん株価ですね)に応用できるか、日々チェックが必要になりそうである。
先に予想しておくと、先述の通りMLアプローチは統計学アプローチとの比較で株価予測には向いておらず、先人たちが幾度と試みて挫折してきた歴史をみても、多分「ランダムウォーク」するデータの予測は不可能と思われる。
株価の予測は何かしらの多変量分析に定性情報となるイベント情報を組み合わせて、伝統的なテクニカル分析を組み合わせるしかないと思われ、しかも都度都度人の手でパラメータチューニングを行う必要がありそうではあるが...
果たしていかに。

この記事が気に入ったらサポートをしてみませんか?