はじめに
今回の記事では、2017年にFacebookから発表された「Forecasting at Scale」という論文を紹介します。この論文では、Prophetと呼ばれる汎用的な時系列予測モデルと実際の現場で様々な関係者とモデルを改善していくための枠組みを提案しています。Prophetはオープンソースソフトウェアとして公開されており、2020年12月現在PythonとR言語で利用することができます (GitHub)。公式のチュートリアルが充実しているため、今回はライブラリの使い方ではなく、仕組みについて紹介していきたいと思います。
目次
- 概要
- モデリング
- モデルの評価
- Analyst-in-the-Loop Modeling
- まとめ
1. 概要
時系列予測は、サービスの目標設定や在庫管理のような組織の重要な意思決定を支援するタスクの一つとしてあげられます。しかし、精度が高く、運用コストが小さい時系列予測モデルを作ることは分析者が行う仕事の中でも比較的難易度が高いです。そのため、現場からの予測モデルに関する需要がアナリストが作成できる予測モデルのペースをはるかに上回ってしまうといった事態が多く発生してしまいます。
そこで、ビジネスの分野で発生する時系列予測のタスク用に最適化させたProphetが提案されました。Prophetで解決するタスクには、以下のいずれかの特徴があります。Prophetはデフォルトの設定で熟練のアナリストが作成した予測モデルと同じくらい正確な予測を行えるモデルを少ない労力で作成することができることが確認されています。
- hourly、daily、weeklyで観測されている過去のデータが最低でも数ヶ月分ある。
- 曜日や時期といった複数の季節性が存在する。
- 事前にわかっている不規則な間隔で発生するイベントがある (クリスマスなど)。
- 欠損値や外れ値が許容できる数である。
- 新機能のリリースやログの変更などのように過去の傾向と変化する点がある。
- 非線形に成長するトレンドがあり、そのトレンドには限界値が存在する。
この論文では、Facebook上で作成されるイベント数に関する時系列データを用いて提案手法の検証を行っています (図1)。グラフは横軸に日付、縦軸にその日作成されたイベント数がプロットされており、各サンプルは曜日毎に色分けされています。グラフを確認すると、一般的な時系列データと同様に周期性 (weekly、yearly)や外れ値があることがわかります。また、クリスマスと新年の前後に縦軸の値が大きく落ち込むイベント効果や2016年以降にトレンドが変化していることが確認できます。
まず、図1のデータに対して時系列予測で一般的に利用されているモデルを適用した結果を図2に示します。この結果から、ビジネスの分野で得られる時系列データを予測することは難しいタスクであることが改めて確認できます。
- auto.arima:Automatic ARIMA Model
- ets:Exponential Smoothing State Space Model
- snaive:Naive And Random Walk Forecasts
- tbats:TBATS Model
2. モデリング
Prophetは、Trend、Seasonality、Holidayの3つ要素で構成される加法モデルとして定義されます (式1)。
各項は、それぞれ以下のようになっています。
g(t):時系列データの非周期的な変化を表すトレンド関数
s(t):周期的な変化 (weekly、yearlyなど)を表す関数
h(t):1日以上に渡って影響を与える不規則なイベントを表す関数
ε:正規分布を仮定した誤差項
Prophetは加法モデルとして表現することで、新しいSeasonalityやHolidayを容易に追加できるだけでなく、予測結果を個別の要素に分解して解釈することができるといった利点があります。また、ARIMAモデルなどとは異なり時系列データの観測値が一定間隔である必要がないため、欠損値補完や外れ値を除く作業が必要なく前処理の手間を省くことができます。
では、次にモデルを構成する各関数の定義について確認していきます。
2.1 Trend Model
トレンドを表現するモデルとして、対象の飽和状態を表現するSaturating Growth Modelと区分線形関数を用いたpicewise linear modelの二つが実装されています。
Saturating Growth Modelは、ロジスティック関数を用いて以下のように定義されます (式2)。このモデルでは、予測対象の飽和状態を表現します。例えばFacebookの場合であれば、アクティブユーザー数を指標とする場合には全世界のインターネット利用人口が上限となります。
ここで各変数の定義は以下のようになっています。
C:carrying capacity
k:growth rate
m:offset parameter
しかし、実際には多くの時系列データがcarrying capacity (C)とgrowth rate (k)が定数ではなく、時間に依存するため式2では十分に表現することができません。そこで、carrying capacityに関しては時刻tに依存する関数C(t)として表現し、growth rateに関しては変化点を表すベクトルaを定義します。
ここで全部でS個の変化点を定義し、その時刻をsⱼ, j=1, … Sとします。そして、各変化点でのgrowth rateの変化量をベクトルδ、ベースとなるgrowth rateをkとすると、ある時刻でのgrowth rateはk+a(t)^{T}δ (a(t)^{T}は、a(t)の転置ベクトル)と表すことができます。growth rateが更新されていた場合には、offeset parameterであるmも更新する必要があります。具体的には、変化点jに対して以下の式4のγを計算することでmを調整することができます。
以上をふまえて、piecewise logistic modelは以下のg(t)で定義できます。
式2で定義したロジスティック関数から、Carrying capacityが時刻tに依存する関数として定義され、分母の指数部分が複数の変化点を考慮できるようになっています。
ここまでは、トレンド関数g(t)が非線形でcarrying capatityが存在する場合について考えてきました。次にcarrying capatityが存在せず変化点で分割された区間ごとに線形なトレンドを持っていると仮定した場合のトレンド関数g(t)を考えます。この場合も非線形の時と同様に考え、以下の式で定義できることがわかります。この式では、0または1の値をとるa(t)によって各区間を表現していることになります。
変化点の検出
変化点sⱼは、新機能のリリースのように既知の日付を利用者が指定することもできますが、自動で選択するようにすることもできます。
2.2 Seasonality
ビジネスの現場で取得される時系列データは人間の行動が反映されることが多いため、複数の周期性を持ちます。例えば、平日5日で休日2日という生活様式はweeklyの周期性を持ち、学生が長期休暇に入る時期やお盆、正月はyearlyの周期性を持ちます。時系列データの予測を行う際には、これらの周期性をモデルに組み込む必要があります。
そこで、Seasonalityを表す関数s(t)をフーリエ級数を用いて表現します (式7)。ここでPは周期を表し、weeklyであればP=7、yearlyであればP=365.25 (閏年を考慮してるため小数の値となっています)のように設定します。
β=[a₁, b₁, …., aₙ, bₙ]で表される2N個のパラメータを推定する必要があります。βはNormal(0, σ²)から生成される値とします。Nの大小はローパスフィルターとしての働きに影響を与えます。例えば、Nの値を大きくするとSeasonalityの変化に迅速に対応することができますが、overfittingしやすくなってしまうといった問題が発生します。論文中では、yearlyの場合はN=10、weeklyの場合はN=3に設定することで多くの問題設定でうまくいくと書かれています。また、これらのパラメータの選択はAICなどを用いることで自動化することも可能です。
2.3 Holiday and Events
休日やイベントは時系列で追っているビジネス指標に大きな影響を与えるが、周期的ではありません。また、そのイベント発生前後にも影響を与えることが多くあります。ここでは特定のイベントが時系列に与える影響は各繰り返しで同程度だと仮定し予測モデルに組み込みます。
休日やイベントの効果を表す関数h(t)は次のように定義することができます。各休日やイベントをiで表し、その影響範囲を表す日付の集合をDᵢとします。そうすることで以下の式Z(t)のように時刻tがどのイベントに含まれるかを表すフラグを表現することができます。そして、各イベントiに対して予測への影響度を表す変数κᵢを定義します。κの事前分布はNormal(0, ν²)を仮定しています。
※ モデルに組み込むイベントは、予測したい未来の日付に関しても事前にわかっている必要があります。
Fitting
式(1)で定義されるモデルは、StanのL-BFGSアルゴリズムを用いてMAP推定を行います。モデル自体も比較的シンプルなため、stanで記述されたコードも理解しやすくなっています。
実際に図1のデータに対してFittingを行った結果を図3に示します。
結果を見ると、weeklyやyearlyの周期性が捉えられているだけでなく、年末に大きく数字が落ち込むといったイベント効果や2016年後半からのトレンドの変化に対しても対応できていることが確認できます。
Prophetでは、モデルをTrend、Seasonality、Holidayの3つに分け、加法モデルとして表現しています。そのため、それぞれを個別の要素に分解して解釈することも可能となります。分解した結果を見ると、2016年以降にトレンドが上昇している様子や曜日の周期性などが捉えられていることが確認できます (図4)。
3. モデル評価
継続的にモデルを改善するために、どのようにモデルを評価するかという点について論文中では4つの方法が紹介されています。ベースラインの設定や過去のデータを用いた精度検証などについて述べられていますが、一般的なモデルの評価と大きく変わらないため、この記事では結果だけ紹介し詳細な説明は省略します。興味のある方は、論文のSection 4を確認してみてください。図5は、図1の時系列データに対して横軸の日数だけ先を予測した場合のMean Absolute Precentage Errorを他の手法と比較した結果です。この結果から、Prophetは予測する日数が延びても安定して高い精度が出ていることがわかります。
4. Analyst-in-the-Loop Modeling
Prophetでは、データ分析を主としないが対象ドメインに関して深い知識を持っている人が容易にモデルを変更できるように設計されています。ドメイン知識をモデルに反映することで、より高品質な時系列モデルを作成することができます。論文中では、以下のドメイン知識をモデルに反映すると良いと紹介されています。
Capacites:対象の市場全体のサイズに関する情報
Change points:製品のリリースなど、既知の日付 (将来の日付も含む)に関する情報
Holiday and Seasonality:どの休日やイベントが、どの地域に、どの程度の影響を与えるのかという情報
Smoothing parameters:平滑化パラメータに関する情報 (この情報を考慮することで、過去の季節変動をどの程度将来の予測に反映するかといったことを調整することができます。)
これらのドメイン知識を効率的に発見し、モデルに反映するためにモデルの適合度を可視化して確認することが重要です。Prophetのライブラリにもデフォルトで変化点やトレンドの可視化などを行うメソッドが用意されています。これらをうまく活用することで、現場のドメイン知識をモデルに反映し、改善を行うサイクルをうまく回せるようになるかもしれません (図6)。
5. まとめ
今回は時系列予測モデルであるProphetを紹介しました。Prophetはドメイン知識を容易にモデルに反映し、改善のループを回せるように意識して設計されています。そのため、複雑なモデリングを専門としない方や比較的組織の規模が小さく開発に多くのリソースがさけない場合に活用できるのではないかと思います。また、熟練のサイエンティストの方でも、解きたい課題がどの程度現実的な問題設定なのかを判断するベースラインモデルとしても活用できると思います。