畳庵〜tatamiya practice〜

機械学習・統計モデリング練習帳。読書・source code読みの記録や,実装など。

R経由で学ぶPythonの状態空間時系列モデリング#0: 状態空間モデルの概要

はじめに

内容

  • 状態空間時系列モデルの概要
    • 状態空間モデルとは何か?
    • 典型的なモデルの紹介
  • 今後の記事の執筆方針
    • 本記事あわせて全5本で構想中

背景

  • 状態空間モデルは時系列分析でよく用いられる手法の一つ
  • Pythonユーザーにとっては情報が少なくややとっつきにくい
    • Rと比べて書籍が圧倒的に少ない
    • ライブラリもRほど充実していない
    • ネットの情報も少ない
  • 理論の紹介 → Rでの実装例 → Pythonへの翻訳のステップを踏むことで、Pythonでも理論を理解したうえで状態空間モデリングを行えるようにしたい。
  • そのためにまずは、そもそも状態空間モデルとはどのようなもので、どのような実装方法があるかの全体像を把握する。

TL;DR

  • 状態空間モデルでは、現象の背後に状態を仮定し、観測値から状態の推定・予測を行う。
  • 状態空間時系列モデルは、トレンドや季節性といった構造を取り入れられ、解釈もしやすい。
  • 代表的なモデルとして、以下の3種類を挙げる
    • ローカルレベルモデル
    • 2次のトレンドモデル
    • ローカルレベル+季節成分モデル
  • 今後執筆予定の記事では、上記の3モデルの計算例とともに、下記の軸に沿って解説を行う
    • 状態推定手法: カルマンフィルタとベイズの比較
    • 実装方法: RからPythonへの翻訳

状態空間モデリングとは?

概要

状態空間モデルでは、観測され系列データy_tの背後に状態\alpha_tを仮定し、何かしらのルールで変化する\alpha_tを観察した結果がy_tである、と考えます。

このとき、観測\alpha_t \to y_tと状態変化\alpha_t \to \alpha_{t+1}は、マルコフ過程として描けるものと考えます:

{
\begin{aligned}
y_t &\sim h(y|\alpha_t)\\
\alpha_{t+1} &\sim q(\alpha|\alpha_t)
\end{aligned}
}

f:id:tatamiyatamiyatatatamiya:20201229201303p:plain
状態空間モデルの概念図

このようにある構造をもったデータ生成過程を仮定したうえで、観測データをもとに状態\alphaの推定・未来の予測を行うのが状態空間時系列モデリングです。

具体的には、以下のような量を計算します:

  • 全観測値Y_T = \lbrace y_t \rbrace_{t=1}^Tに基づく状態\alpha_tの推定値(平滑化状態):
    • \hat{\alpha}_t = E\lbrack \alpha_t|Y_T \rbrack \quad (0\le t \le T)
  • 未来の観測値y _ {T+i}や状態\alpha _ {T+i}の予測値
    • 観測予測値: \hat{y}_t = E\lbrack y _ {T+i}|Y_T\rbrack
    • 状態予測値: \hat{\alpha}_{T+i} = E\lbrack \alpha _ {T+i}|Y_T\rbrack

E\lbrack \cdot|X \rbrackXが与えられたもとでの条件付き期待値です。

また、状態推定の方法はカルマンフィルタとMCMCの2種類が代表的です。

線型ガウス状態空間モデルの例

状態空間モデルの中でも比較的計算が容易でよく用いられるのが、以下の形で書ける線型ガウス状態空間モデルと呼ばれる種類のものです:

{
\begin{aligned}
y_t &\sim N(Z\alpha_t, H)\\
\alpha_{t+1} &\sim N(T\alpha_t, RQR^T).
\end{aligned}
}

N(\mu, \Sigma)は期待値が\mu, 共分散行列が\Sigma正規分布を表します。 観測値y_tと状態\alpha_tはともにベクトルで表現しており、Z, H, T, Rはいずれも行列です。

同じ内容を、表現を変えて書くと以下のようになります:

{
\begin{aligned}
y_t &= Z\alpha_t + \varepsilon_t, \quad \varepsilon_t \sim N(0, H)\\
\alpha_{t+1} &= T\alpha_t + R\eta_t, \quad \eta_t \sim N(0, Q)
\end{aligned}\tag{1}\label{eq:dlm}
}

以下に3種類の線型ガウス状態空間モデルの代表的な例を、データへの適用例とともに紹介します。

なお、以下グラフでは、太い黒線は観測値y_tを、細い灰色線は状態推定値・予測値\hat{\alpha}_tを表しています。 推定値の周りの帯は、状態推定値の分散V_t={\rm Var}\lbrack \alpha_t|Y_T \rbrack をもとに算出した25~75%, 10~90%の区間です。

1. ローカルレベルモデル

ローカルレベルモデルは、状態空間モデルの中でも最もシンプルなモデルです。

{
\begin{aligned}
y_t &= \alpha_t + \varepsilon_t, \quad \varepsilon_t \sim N(0, \sigma_\varepsilon^2)\\
\alpha_{t+1} &= \alpha_t + \eta_t, \quad \eta_t \sim N(0,\sigma_\eta^2)
\end{aligned}
}

ブラウン運動する状態\alpha_tに、観測ノイズ\varepsilon_tが乗る、と解釈ができます。

サンプルとして、以下のような架空の売り上げデータ(馬場2019)に適用しました:

f:id:tatamiyatamiyatatatamiya:20210212211017p:plain:w400
ローカルレベルモデルによる架空の売り上げデータの状態推定・予測結果(太黒線: y_t、細灰線: \hat{\alpha}_t、データの出典:馬場2019)

2. 2次のトレンドモデル

前述のローカルレベルモデルで状態の式を

{
\begin{aligned}
\Delta \alpha_{t+1} \equiv \alpha_{t+1} - \alpha_t \sim N(0, \sigma_\eta^2)
\end{aligned}
}

のように書き直すと、変化の期待値が常に0、つまり平均的なトレンドのない系列、として解釈できます。

これに対して、時系列が明確なトレンドを持つと仮定する場合は、以下のようなモデルを考えます:

{
\begin{aligned}
y_t &= \mu_t + \varepsilon_t, \quad \varepsilon_t \sim N(0, \sigma_\varepsilon^2)\\
\mu_{t+1} &= 2 \mu_t - \mu_{t-1} +  \eta_t, \quad \eta_t \sim N(0, \sigma_\mu^2)
\end{aligned}
}

線型ガウスモデルの一般式(\ref{eq:dlm})とは、 \alpha _ t \equiv (\mu _ t, \mu _ {t-1}) ^ Tとおくと対応します。

今度は

{
\begin{aligned}
\Delta \mu_{t+1} &= \Delta \mu_t + \eta_t, \quad \eta_t \sim N(0, \sigma_\mu^2)
\end{aligned}
}

と書き換えられますので、トレンドがブラウン運動にしたがって少しずつ変化している、と解釈することができます。

先ほどと同じデータについて、このモデルにしたがって状態推定・予測を行うと次のようになります:

f:id:tatamiyatamiyatatatamiya:20210212211108p:plain:w400
2次のトレンドモデルによる架空の売り上げデータの状態推定・予測結果(太黒線: y_t、細灰線: \hat{\mu}_t、データの出典:馬場2019)

ローカルレベルモデルと比べて滑らかな状態推定値\hat{\mu}_tが得られ、また予測値も直前までの傾きを外挿するように伸びています。

3. ローカルレベル+季節成分モデル

実世界のデータはトレンドに加えて、日・週・月・年といった何かしらの周期性を持っていることがよくあります。

そのような場合は、時系列y_tを以下のようにトレンド成分\mu_t・季節成分\gamma_t・ノイズ\varepsilon_tの和に分解して表現します:

{
\begin{aligned}
y_t = \mu_t + \gamma_t + \varepsilon_t
\end{aligned}
}

季節成分\gamma_tは以下のように1周期分の和が平均的に0になるダミー変数として扱います1

{
\begin{aligned}
\sum_{i=1}^{s}\gamma_{t+i} \sim N(0, \sigma_\gamma^2)
\end{aligned}
}

上記では周期をsとしています。

以下に示すのは、ローカルレベルモデルに4半期周期成分を加えたモデルです:

{
\begin{aligned}
y_t &= \mu_t + \gamma_t + \varepsilon_t, \quad \varepsilon_t \sim N(0, \sigma_\varepsilon^2)\\

\mu_{t+1} &= \mu_t + \eta^{(\mu)}_t, \quad \eta^{(\mu)}_t \sim N(0, \sigma_{\mu}^2)\\ 

\gamma_{t+1} &= - \gamma_{t} - \gamma_{t-1}- \gamma_{t-2} + \eta^{(\gamma)}_t,\quad \eta^{(\gamma)}_t \sim N(0, \sigma_\gamma^2)
\end{aligned}
}

こちらも\alpha _ t \equiv (\mu _ t, \gamma _ t, \gamma _ {t-1}, \gamma _ {t-2}) ^ Tとおくと線型ガウスモデルの一般式(\ref{eq:dlm})と対応します。

こちらをもとに、松浦2015のデータで状態推定・予測を行った結果がこちらです:

f:id:tatamiyatamiyatatatamiya:20201229202214p:plain:w400
ローカルレベル+季節成分モデルによる四半期ごとの売り上げデータの状態推定・予測結果(太黒線: y_t、 細灰線: \hat{\mu} _ t + \hat{\gamma} _ t、データの出典:松浦2015)

予測値も4半期に合わせて変動していることがわかります。

また、成分ごとに見てみると、トレンド成分推定値\hat{\mu}_tから時系列の「上昇具合」が見て取れます。

f:id:tatamiyatamiyatatatamiya:20201229202510p:plain:w400
トレンド成分推定・予測値(太黒線: y_t、細灰線: \hat{\mu}_t

f:id:tatamiyatamiyatatatamiya:20201229202544p:plain:w400
季節成分推定値(細灰線: \hat{\gamma}_t

まとめと今後の執筆方針

今回の記事では状態空間時系列モデルの概要と代表的な例を紹介しました。

状態空間時系列モデリングでは、モデルの構造に周期性などの仮定を入れやすく、柔軟かつ解釈のしやすいモデルを作ることができます。

特に、トレンド・季節性の分離は利用するシーンが多いのではないかと思います。

今後の記事では状態推定方法とライブラリを用いた実行方法を焦点に掘り下げていき、最終的にはPythonモデリングできるようになることを目指します。

現段階での記事構想

調べてみるとすぐにわかるのですが、Pythonを用いた時系列モデリングは、本2・ライブラリ3・Web記事4ともに情報がかなり少ないです。

一方で、Rについては参考になる本も多く、ライブラリもカルマンフィルタならKFAS5かdlm6ベイズ推定ならRStan7が定番として挙げられます。

したがって、まずはRを動かしながら理論の適用方法を理解し、Pythonに翻訳して使えるようになる、という進め方をするのが良いように思います。

具体的には、前章で紹介した3種類のモデルを共通の例に、R -> Python, カルマンフィルタ VS MCMCの軸で一つずつ紹介していきます。

  1. カルマンフィルタによる状態推定とRによる実装方法の紹介(KFAS)
  2. Pythonを用いたカルマンフィルタによる状態推定(statsmodels)
  3. MCMCによる状態推定とRによる実装方法の紹介(RStan)
  4. Pythonを用いてMCMCで状態推定(PyMC3)

f:id:tatamiyatamiyatatatamiya:20210212211513p:plain:w400
今後の執筆構想

今回の一連の記事では扱わないこと

状態空間時系列モデリングに関連する話のうち、以下については今回は触れない予定です。

ARIMAモデル

古典的な時系列モデルである自己回帰(AR)モデルや移動平均(MA)モデルは、状態空間モデルに含まれるのでそのうち別で扱うかもしれません。

PyStan

RStanと使い方はほぼ一緒なので、特別触れません。

もし知りたい場合、公式ドキュメントか以下のUdemyの動画を参照してください。

www.udemy.com

細かい式の導出

カルマンフィルタについてはそのうち別枠で導出を行うかもしれません。とりあえず現時点では、参考文献の野村2016といった書籍か、こちらの記事を参照してください。

ベイズ推定についてはPRMLなどの書籍をご参照ください。

おっと、こんなところに良さげな本がkindle unlimitedで...(ステマ

非線形や非ガウスの状態空間モデル

粒子フィルタ、非線形カルマンフィルタなどなどといった計算手法はありますが、今回は範囲外とします。

ただし、観測値がイベント回数などの場合に使える一般化動的線型モデルについては、KFASでも実行できるので、ベイズとの比較も含めて今後解説するかもしれません。

また、カルマンフィルタの導出で触れた以下のブログでも、粒子フィルタの実装が紹介されています:

learning-with-machine.hatenablog.com

参考資料

データの出典

書籍


  1. ダミー変数を使う他に、三角関数で周期成分を表現することもありますが、今回は割愛します。野村2016を参照してください。

  2. 著者はこれくらいしか知りません:島田直希、時系列解析: 自己回帰型モデル・状態空間モデル・異常検知 (Advanced Python)、共立出版(2019)

  3. 代表的なものとしてstatsmodelsがあるものの、使い勝手が良いとは言い難く、ドキュメントも読みにくいです。

  4. 馬場2019の著者のブログにある程度まとまった情報が載っています:https://logics-of-blue.com/

  5. KFAS:https://cran.r-project.org/web/packages/KFAS/index.html

  6. dlm:https://cran.r-project.org/web/packages/dlm/index.html

  7. RStan:https://mc-stan.org/users/interfaces/rstan