学習コースLearn

時系列分析

時間とともに変化するデータの構造を読み解き、予測する技術を、概要から理論、そして実際に動かせるコードまで、順を追って学ぶモジュールです。各ステップは「概要 → 仕組み(座学)→ コードで動かす」の3層で進みます。ページ内には手を動かせるデモを3つ用意しました。

この教材は日本語のみで提供していますThis learning material is available in Japanese only.

はじめにIntroduction

このモジュールの全体像

時系列分析(time series analysis)とは、時間の順に並んだデータ(時系列)を対象に、その構造を読み解き、将来を予測する技術の総称です。毎月の売上、日々の気温、株価、サーバの負荷、そしてリポジトリへの週ごとのコミット数まで、時間とともに変化するあらゆるデータが対象になります。

時系列が特別なのは、観測の順序そのものに意味がある点です。行を並べ替えてはいけませんし、近い時点の値は互いに似る傾向(自己相関)があります。そこで多くの手法は、次のような流れをたどります。まず系列を成分に分け、必要なら定常な形に整え、モデルにあてはめ、将来を予測します。

時系列分析の基本パイプライン

時系列 Time series 成分分解 Decompose 定常化 Stationarize モデル化 Model 予測 Forecast トレンド・季節・残差 差分・ADF検定 ARIMA・指数平滑

このモジュールは、上のパイプラインを左から順にたどります。各ステップは次の3層で構成します。

  • 概要:その技術が何のためにあるのか、あらましをつかむ。
  • 仕組み(座学):背後にある理論・定義・式を、ていねいに理解する。
  • コードで動かす:Python の定番ライブラリや、ページ内デモで実際に動かして確かめる。

手を動かす題材には、実在の公開データセット(月次の航空旅客数 AirPassengers など、古典的な時系列)や、ページ内の小さなサンプル系列だけを使います。特別な環境がなくても、読みながら試せる構成です。

1

時系列分析とは

What is time series analysis

概要Overview

時系列とは、一定の間隔で時間順に記録された観測値の並びです。私たちは次のような場面で、すでにその分析の成果に触れています。

  • 需要予測:来月の売上や来客数、在庫の必要量を見積もる。
  • 異常検知:サーバの負荷やセンサの値が、いつもと違う動きをしたら気づく。
  • 景気・気象:経済指標や気温の推移を追い、先を見通す。
  • 開発活動の推移:リポジトリへの週ごとのコミット数や課題の増減から、プロジェクトの勢いを読む。

仕組みHow it works

時系列が、ふつうの表形式データ(各行が独立した1件のサンプル)と決定的に違うのは、観測の順序が情報を持つことです。ここから、いくつかの大切な性質が出てきます。

  • 自己相関:近い時点の値どうしは似る傾向があります。今日の気温は昨日の気温と近く、去年の同じ月とも近い。この「自分自身との相関」が時系列の分析と予測の土台です。
  • トレンドと季節性:長期的に上がる・下がるといった傾向(トレンド)や、1年・1週間などの周期で繰り返す動き(季節性)がしばしば含まれます。
  • 順序を崩せない:行をシャッフルすると意味が失われます。そのため、評価のためのデータ分割も「過去で学び、未来で試す」という時間の順序を必ず守ります。

また、時系列分析には大きく2つの目的があります。一つは予測(forecasting)、つまり将来の値を当てること。もう一つは理解、つまりトレンドや季節性、周期といった構造を取り出して説明することです。このモジュールの Step 2 以降は、この両方を少しずつ体験していきます。

この Step のまとめ

時系列は「時間順に並んだ観測値」。順序に意味があり、自己相関・トレンド・季節性という性質を持ちます。行を並べ替えてはいけない点が、ふつうの表データとの大きな違いです。次から「成分に分ける → 定常化する → モデルにかける」という流れを一つずつたどります。

2

成分に分けて眺める(分解)

Components & decomposition

概要Overview

時系列をいきなりモデルにかける前に、まず成分に分けて眺めると、データの正体がつかめます。多くの時系列は、長期の傾向・周期的な動き・その他の変動という、性質の違う成分の重ね合わせとして理解できます。

仕組みHow it works

3つの成分

古典的な分解では、時系列を次の3成分に分けます。

  • トレンド(trend):長期的に上がる・下がるという、ゆるやかな傾向。
  • 季節性(seasonal):1年・1週間・1日など、決まった周期で繰り返すパターン。
  • 残差(residual):トレンドと季節性で説明しきれない、残りの不規則な変動。

加法モデルと乗法モデル

成分の組み合わせ方には2通りあります。季節変動の大きさが水準によらずほぼ一定なら加法モデル、水準が上がるほど季節変動も大きくなるなら乗法モデルが向いています。

加法: y(t) = T(t) + S(t) + R(t)  乗法: y(t) = T(t) × S(t) × R(t) T: トレンド S: 季節成分 R: 残差
乗法モデルは、対数をとると log y = log T + log S + log R となり、加法モデルとして扱えます。

トレンドの取り出しには、周期の長さにそろえた移動平均(たとえば月次データなら幅12の移動平均)がよく使われます。移動平均で周期的な凸凹をならすと、なめらかなトレンドが浮かび上がります。トレンドを取り除いた残りから各周期位置の平均を求めれば、季節成分が得られます。

デモ 1Demo 1

時系列の成分分解

トレンド・季節・ノイズの大きさをスライダで変えると、それらを足し合わせた合成波形と、各成分を別々のグラフで表示します。加法モデル y(t) = トレンド + 季節 + ノイズ を、逆向きに「作って」体感するデモです。ノイズは再現できるよう固定パターンを使います。

コードで動かすRun the code

実データの分解は、statsmodels の seasonal_decompose が手軽です。ここでは古典的な公開データ AirPassengers(1949年から1960年の月次航空旅客数)を読み込み、乗法モデルで分解します。旅客数は年々増え、季節変動も水準とともに大きくなるので、乗法モデルが自然です。

Pythondecompose.py
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.seasonal import seasonal_decompose

# AirPassengers(月次・144点)を取得
data = sm.datasets.get_rdataset("AirPassengers").data
idx = pd.period_range("1949-01", periods=len(data), freq="M")
s = pd.Series(data["value"].values, index=idx.to_timestamp())

result = seasonal_decompose(s, model="multiplicative", period=12)
print(result.seasonal[:12].round(3).tolist())  # 12か月ぶんの季節指数
出力例 / Output
[0.91, 0.884, 1.007, 0.976, 0.981, 1.113,
 1.227, 1.22, 1.06, 0.922, 0.801, 0.899]

季節指数は、その月が年平均の何倍かを表します。7月・8月(1.22 前後)は夏の需要で平均より2割ほど多く、11月(0.80)は逆に2割ほど少ないことが読み取れます。result.trend、result.resid にはトレンドと残差が入っており、result.plot() で4段のグラフをまとめて描けます。

この Step のまとめ

時系列はトレンド・季節・残差の重ね合わせとして眺められます。季節変動が水準によらず一定なら加法モデル、水準に比例するなら乗法モデル。移動平均でトレンドをならし、seasonal_decompose で成分を取り出せます。次は、モデル化の前提となる「定常性」を見ます。

3

定常性と自己相関

Stationarity & autocorrelation

概要Overview

次の Step で扱う ARIMA をはじめ、多くの時系列モデルは定常性を前提にします。定常な系列に整え、その系列の自己相関を読むことが、モデルの次数を決める手がかりになります。

仕組みHow it works

定常性とは

定常(stationary)とは、時系列の統計的な性質が時間によって変わらないことを指します。実務では、平均と分散が一定で、2時点の関係(自己共分散)が時点の差だけで決まる、という弱定常を考えます。トレンドがある系列は平均が動くので非定常、季節性が強い系列も非定常です。

差分による定常化

非定常な系列は、差分をとると定常に近づくことがよくあります。差分とは、隣り合う値の引き算 Δy(t) = y(t) − y(t−1) です。1階差分でトレンドが消え、季節性には周期ぶんずらした季節差分 y(t) − y(t−12) が効きます。この「何階の差分が必要か」が、あとで出てくる ARIMA の d にあたります。

自己相関 ACF と偏自己相関 PACF

自己相関(ACF)は、系列を k 時点ずらした自分自身との相関です。ラグ k を横軸に ACF を並べた図(コレログラム)を見ると、周期やトレンドの名残がわかります。標準的な定義は次のとおりです。

r(k) = c(k) / c(0) , c(k) = (1/n) ∑ (y(t) − ȳ) (y(t+k) − ȳ) ȳ: 系列の平均 n: データ数 c(0): 分散
和は t = 1 から n−k まで。r(0) は必ず 1 になります。

偏自己相関(PACF)は、ラグ k の相関から、途中のラグを通じた間接的な影響を取り除いた「純粋な」相関です。ACF と PACF のどこで急に小さくなるか(裾切れ・減衰)を見て、AR や MA の次数の目安を立てます。

ADF検定

定常かどうかを数値で判定するのがADF検定(拡張ディッキー・フラー検定)です。帰無仮説は「単位根がある(=非定常)」で、p値が小さい(目安 0.05 未満)ときに帰無仮説を棄却し、定常とみなします。トレンドのある生の系列では p値が大きく、差分をとると小さくなる、という動きがよく見られます。

デモ 2Demo 2

自己相関(ACF)

数列を入力すると、各ラグの自己相関 r(k) を計算してバーで表示します(上の式と同じ、標準的な推定量)。周期のある系列はその周期でバーが大きく、トレンドのある系列は右へゆっくり減衰します。破線は目安の信頼区間 ±1.96/√n です。

例

コードで動かすRun the code

statsmodels には、ACF・PACF・ADF検定がそろっています。AirPassengers の生の系列と、その1階差分で、定常性がどう変わるかを見ます。

Pythonstationarity.py
import statsmodels.api as sm
from statsmodels.tsa.stattools import acf, pacf, adfuller

data = sm.datasets.get_rdataset("AirPassengers").data
s = data["value"]

# 生の系列(トレンドあり)と1階差分でADF検定
print("level: stat=%.3f p=%.4f" % adfuller(s)[:2])
print("diff : stat=%.3f p=%.4f" % adfuller(s.diff().dropna())[:2])

# 自己相関・偏自己相関(ラグ0から6)
print(acf(s, nlags=6).round(3).tolist())
print(pacf(s, nlags=6).round(3).tolist())
出力例 / Output
level: stat=0.815 p=0.9919
diff : stat=-2.829 p=0.0542
[1.0, 0.948, 0.876, 0.807, 0.753, 0.714, 0.682]
[1.0, 0.955, -0.265, 0.055, 0.109, 0.081, 0.004]

生の系列は p値 0.99 で、単位根の帰無仮説を棄却できず非定常。1階差分をとると p値が 0.05 近くまで下がり、定常に近づきます(この系列は季節性が強いので、実務では季節差分も併用します)。ACF はゆっくり減衰し、PACF はラグ1で大きく、ラグ2以降で小さい、という典型的な形が読み取れます。

この Step のまとめ

定常とは統計的性質が時間で変わらないこと。差分でトレンドや季節性を取り除いて定常化します。ACF と PACF は次数選びの手がかり、ADF検定は定常性の数値的な判定(p値が小さいほど定常)。この準備が、次の ARIMA に直結します。

4

予測モデル(ARIMA)

Forecasting models

概要Overview

定常化まで来たら、いよいよ予測です。時系列予測の古典的な主役が ARIMA です。名前は Auto-Regressive(自己回帰)、Integrated(差分)、Moving Average(移動平均)の頭文字で、これまで見てきた道具が一つにまとまったモデルです。

仕組みHow it works

AR・MA・ARMA

まず定常な系列を表す2つの部品があります。

  • AR(p)(自己回帰):現在の値を、過去の値の線形結合で説明する。
  • MA(q)(移動平均):現在の値を、過去の予測誤差の線形結合で説明する。

この2つを合わせたのが ARMA(p, q) です。式で書くと次のようになります(ε は白色雑音、φ・θ は係数)。

AR(p): y(t) = c + φ1 y(t−1) + … + φp y(t−p) + ε(t)
MA(q): y(t) = μ + ε(t) + θ1 ε(t−1) + … + θq ε(t−q) φ: 自己回帰係数 θ: 移動平均係数 ε: 予測誤差(白色雑音) c, μ: 定数

ARIMA と SARIMA

ARIMA(p, d, q) は、d 階の差分をとって定常にした系列に ARMA(p, q) をあてはめるモデルです。3つの次数の意味は次のとおりです。

  • p:自己回帰の次数(いくつ前までの値を使うか)。PACF の裾切れが目安。
  • d:差分の階数(定常化に必要な差分の回数)。Step 3 の ADF検定が目安。
  • q:移動平均の次数(いくつ前までの誤差を使うか)。ACF の裾切れが目安。

季節性がある場合は、季節ぶんの自己回帰・差分・移動平均を加えた SARIMA(p, d, q)(P, D, Q)m(m は周期)を使います。次数は、ACF・PACF の形と、モデルの当てはまりの良さを表す AIC(小さいほど良い)を見比べて決めるのが基本です。

デモ 3Demo 3

単純な予測(移動平均・指数平滑)

系列を入力し、移動平均(直近の窓幅ぶんの平均)と指数平滑(新しい値を重く見る加重平均)で、数期先を予測します。窓幅と平滑係数 α のスライダを動かすと、予測線が更新されます。ARIMA より素朴ですが、予測の考え方の土台になる方法です。

例

コードで動かすRun the code

本格的な ARIMA は statsmodels の ARIMA クラスで、fit で学習し forecast で先を予測します。AirPassengers に ARIMA(2, 1, 2) をあてはめ、次の3か月を予測してみます。

Pythonarima_forecast.py
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.arima.model import ARIMA

data = sm.datasets.get_rdataset("AirPassengers").data
idx = pd.period_range("1949-01", periods=len(data), freq="M")
s = pd.Series(data["value"].values, index=idx)

model = ARIMA(s, order=(2, 1, 2))  # (p, d, q)
res = model.fit()
print("AIC = %.1f" % res.aic)
print(res.forecast(steps=3).round(1).tolist())  # 次の3か月
出力例 / Output
AIC = 1353.3
[439.9, 465.3, 500.7]

※ AIC の値は statsmodels のバージョンによって変わります(上は statsmodels 0.15 で実行した結果)。

次の3か月の旅客数が予測できました。季節性を明示的に扱うなら ARIMA(s, order=(2,1,1), seasonal_order=(0,1,1,12)) のように季節次数を加えます。次数選びを自動化したいときは、AIC を最小にする組み合わせを探す pmdarima の auto_arima が便利です。

この Step のまとめ

ARIMA(p, d, q) は、自己回帰(AR)・差分(I)・移動平均(MA)を一つにまとめた古典的な予測モデル。p は過去の値、q は過去の誤差、d は差分の階数で、ACF・PACF・AIC を手がかりに決めます。季節性には SARIMA。fit と forecast で予測が作れます。次は、その予測の良さをどう測るかです。

5

評価と実践

Evaluation & practice

概要Overview

予測モデルを作ったら、その良さを正しく測る必要があります。時系列の評価には、ふつうの機械学習とは違う大原則があります。それは「時間を守る」ことです。

仕組みHow it works

時間を守ったデータ分割

時系列では、データをランダムに分けてはいけません。未来の情報を学習に混ぜてはならないからです。過去の区間を学習用(train)、その後の区間を検証用(test)にします。これを破って未来のデータで学習してしまうことをデータリークと呼び、評価を実力より甘くしてしまいます。

予測誤差の指標

予測値と実測値のずれは、次の3つでよく測ります。いずれも小さいほど良い指標です。

  • MAE(平均絶対誤差):誤差の絶対値の平均。単位が元データと同じで直感的。
  • RMSE(二乗平均平方根誤差):誤差を二乗して平均し平方根をとる。大きな外れを重く見る。
  • MAPE(平均絶対百分率誤差):誤差を実測値で割った割合の平均。スケールの違う系列を比べやすいが、実測値が0に近いと不安定。
MAE = (1/n) ∑ |y − ŷ| , RMSE = √( (1/n) ∑ (y − ŷ)² ) , MAPE = (100/n) ∑ |(y − ŷ) / y| y: 実測値 ŷ: 予測値 n: 検証データ数 MAPE は百分率(%)

ローリング予測と指数平滑法

1回の分割では評価がぶれることがあります。そこで、学習区間を1歩ずつ前に伸ばしながら予測と評価を繰り返すローリング予測(walk-forward validation)で、安定した評価を得ます。また、実務で強い定番が指数平滑法で、レベル・トレンド・季節を指数的な加重平均で更新します。3成分をまとめて扱う Holt-Winters 法は、季節性のある系列で ARIMA に匹敵する精度を、少ない手間で出せます。

コードで動かすRun the code

AirPassengers の最後の1年を検証用に取り分け、残りで Holt-Winters を学習して予測し、3つの指標で評価します。分割は必ず時間順です。

Pythonevaluate.py
import numpy as np, pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.holtwinters import ExponentialSmoothing

data = sm.datasets.get_rdataset("AirPassengers").data
idx = pd.period_range("1949-01", periods=len(data), freq="M")
s = pd.Series(data["value"].values, index=idx.to_timestamp())

train, test = s[:-12], s[-12:]  # 最後の1年を検証に(時間順)
fit = ExponentialSmoothing(train, trend="add",
        seasonal="mul", seasonal_periods=12).fit()
pred = fit.forecast(12).values
y = test.values

mae  = np.mean(np.abs(y - pred))
rmse = np.sqrt(np.mean((y - pred) ** 2))
mape = np.mean(np.abs((y - pred) / y)) * 100
print("MAE=%.2f RMSE=%.2f MAPE=%.2f%%" % (mae, rmse, mape))
出力例 / Output
MAE=10.30 RMSE=15.81 MAPE=2.21%

MAPE 2.21% は、平均して実測値の約2%しか外していないという意味で、月次数百のスケールに対しては良好な予測です。RMSE が MAE より大きいのは、二乗が効いて一部の大きな外れを重く見ているためです。指標は必ず検証用(未来)データで計算し、学習に使っていないことを確認します。

この Step のまとめ

時系列の評価は「時間を守る」が鉄則。未来を学習に混ぜない分割で、MAE・RMSE・MAPE を見ます。ローリング予測で評価を安定させ、Holt-Winters のような指数平滑法は少ない手間で高い精度を出します。

6

これからの時系列分析

What comes next

概要Overview

ARIMA や指数平滑法は今も現役の強力な道具ですが、時系列の世界はここから大きく広がります。より柔軟なモデルや、機械学習・深層学習を取り込んだ手法が、現代の時系列分析を形づくっています。

仕組みHow it works

柔軟なモデルと状態空間

Prophet(Meta が公開)は、トレンド・季節性・祝日効果を加法的に組み合わせる実務向けのモデルで、欠測や外れ値に強く、設定が少なくて済みます。より一般的な枠組みが状態空間モデルで、目に見えない「状態」の時間変化と、それを観測する仕組みを分けて記述します。状態を逐次的に推定するカルマンフィルタは、その代表的な計算法です。

機械学習・深層学習による時系列

近年は、機械学習・深層学習を時系列に応用する流れが盛んです。系列を扱う RNN・LSTM や、注意機構にもとづく Transformer は、長期の依存関係や複雑なパターンを捉えられます。勾配ブースティングに時系列の特徴量(ラグ・移動統計など)を与える実務的な手法も広く使われます。

多変量への広がり

ここまでは1本の系列(単変量)を扱いましたが、複数の系列が互いに影響し合う多変量時系列もあります。相互に自己回帰させる VAR(ベクトル自己回帰)などが基本で、経済や気象のように連動する指標の分析に使われます。

この Step のまとめ

ARIMA の先には、実務向けの Prophet、一般的な状態空間モデルとカルマンフィルタ、そして LSTM や Transformer による深層学習、複数系列を扱う多変量時系列(VAR)があります。ここで身につけた「成分・定常性・自己相関・予測誤差」という基礎は、そのどれを学ぶうえでも土台になります。

まとめWrap-up

学びの振り返りと、さらに学ぶために

このモジュールでは、時間順のデータを扱う基本の道具を、パイプラインに沿って順に手に入れました。

  • 成分と分解:時系列をトレンド・季節・残差に分けて眺める。
  • 定常性と自己相関:差分で定常化し、ACF・PACF・ADF検定で系列の性質を読む。
  • 予測モデル:ARIMA(p, d, q) と SARIMA で将来を予測する。
  • 評価と実践:時間を守った分割で、MAE・RMSE・MAPE により予測を評価する。
  • これから:Prophet・状態空間モデル・深層学習・多変量へと広がる。

次に進むなら、下の道具と資料が役に立ちます。

公開データセット

  • AirPassengers:1949年から1960年の月次航空旅客数。トレンドと季節性を持つ、時系列分析の定番。
  • Sunspots:太陽黒点数の年次データ。周期性の例として有名(statsmodels に内蔵)。
  • Mauna Loa CO2:大気中二酸化炭素濃度の観測。強いトレンドと季節性(statsmodels に内蔵)。

ライブラリ

  • statsmodels:ARIMA・分解・ACF/PACF・検定の定番。
  • pandas:日付インデックス・リサンプリング・移動統計。
  • Prophet:トレンド・季節・祝日を扱う実務向け予測。
  • sktime:時系列向けの統一的な機械学習インタフェース。
  • pmdarima:AIC最小の次数を自動探索する auto_arima。

参考書

  • 沖本竜義『経済・ファイナンスデータの計量時系列分析』朝倉書店
  • Rob J. Hyndman, George Athanasopoulos『Forecasting: Principles and Practice』(無料オンライン版あり)

次のモジュールへ

おつかれさまでした

ここで学んだ「成分に分ける → 定常化する → モデルにかけて予測する → 時間を守って評価する」という流れは、時間の順序を持つデータを扱う多くの場面で共通の考え方です。手元のサンプル系列を書き換えて、3つのデモをもう一度動かしてみてください。値がどう変わるかを確かめると、理解がぐっと深まります。

発展トピックBeyond this module

このコースでは扱わない、関係する発展トピック

このモジュールでは、時系列を成分に分け、定常化し、ARIMA や指数平滑法で予測する「基礎の流れ」を扱いました。いっぽうで近年の時系列分析は、状態空間モデルや深層学習を軸に急速に広がっています。ここでは、このコースでは踏み込まないものの、知っておくと視野が広がる発展的なトピックを、特に近年の主流を中心に紹介します。深掘りは各自の興味に合わせてどうぞ。

状態空間モデルと確率的手法

  • 状態空間モデルとカルマンフィルタ:見えない状態の時間変化と観測を分けて記述し、逐次的に推定する一般的な枠組み。
  • ベイズ的時系列:不確実性を分布として扱い、予測区間を自然に得る。

機械学習・深層学習による時系列

  • LSTM・Transformer による予測:長期の依存関係や複雑なパターンを捉える深層学習モデル。
  • 勾配ブースティングと特徴量:ラグや移動統計を特徴量にして、汎用の機械学習で予測する実務的な手法。

実務向けツールと多変量

  • Prophet:トレンド・季節・祝日効果を加法的に組み合わせる、設定の少ない実務向けモデル。
  • 多変量時系列(VAR):複数の系列を相互に自己回帰させ、連動する指標を分析する。
  • 需要予測の実務:多数の系列を一括で扱う、階層的な予測や在庫最適化との接続。

異常検知とその先

  • 時系列の異常検知:いつもと違う動きを見つける。予測との差や、分布の変化点検出を使う。
  • 変化点検出:系列の性質が切り替わる時点を推定し、構造の変化をとらえる。