体系 › 時系列データ系
·無料·12分で読めます

時系列予測を1から解説 — 古典手法から基盤モデルまで

時系列予測が普通の回帰と決定的に違うのは、行が独立でないことと、テストが必ず未来側にあることです。自己相関と定常性から入り、ARIMAの直感、季節とトレンドの分解、深層モデルと時系列基盤モデルの位置づけまで。最後に、実務で最も事故が多い「評価」——ランダム分割の禁止、バックテストの作法、MAPEの罠を厚く扱います。

対象timeseriesタスクforecasting

普通の回帰と、どこが違うのか

「明日の売上を、今日までの売上から当てる」。一見ただの回帰問題で、学習ライブラリに投げれば数字は出ます。しかし出てきた検証スコアは、ほぼ確実に本番より良く出ます。時系列には、普通の教師あり学習が前提にしている性質が4つとも欠けているからです。

行が独立でない。 通常の学習は「サンプルは互いに独立で同じ分布から来る」を前提にします。時系列では隣り合う2点がほとんど同じ情報を持つ。今日の気温を知っていれば、明日の気温はもう半分わかっています。

順序に意味がある。 行をシャッフルしても画像分類なら何も失われませんが、時系列では情報そのものが消えます。

分布が動く。 平均も分散も時間とともに変わります。去年の需要水準は、今年の需要水準ではありません。

未来が簡単に混入する。 「7日移動平均」のような特徴量を1本作った瞬間、予測時点では知り得ない値が入り込む余地が生まれます。この事故は最後の節で詳しく扱います。

自己相関: 過去の自分が、最強の特徴量

系列を kk ステップずらして自分自身と比べたときの相関を、ラグ kk の自己相関と呼びます。

ρk=Cov(yt, yt−k)Var(yt)\rho_k = \frac{\mathrm{Cov}(y_t,\ y_{t-k})}{\mathrm{Var}(y_t)}
(1)

yty_t は時刻 tt の値、Cov\mathrm{Cov} は共分散(2つが一緒に動く度合い)、Var\mathrm{Var} は分散です。ρk\rho_k が1に近ければ「kk ステップ前を見れば今がだいたいわかる」。つまりこの式は「今と kk ステップ前が、どれくらい一緒に上下したか」を、その系列自身の振れ幅で割って目盛りを揃えただけのものです。0に近ければ、kk ステップ前は今について何も語っていません。

これを k=1,2,3,…k=1,2,3,\dots と並べたグラフがACF(自己相関プロット)で、時系列の仕事はほぼここから始まります。日次の小売データなら k=7k=7 に山が立ち(曜日の周期)、月次なら k=12k=12 に立つ。周期の正体が一目でわかります。

定常性: 「同じルールが続く」という賭け

古典的な手法はどれも定常性——平均・分散・自己相関の構造が時間によらず一定、という性質を前提にします。モデルは過去から法則を推定して未来に当てはめるので、法則が途中で変わるなら推定そのものに意味がないからです。

現実の系列はまず定常ではありません。トレンドがあれば平均が動くので、差分を取ります。

Δyt=yt−yt−1\Delta y_t = y_t - y_{t-1}
(2)

「値そのもの」を「前日からの変化量」に置き換えるだけです。要するに Δyt\Delta y_t は「1つ前の時点より、いくつ増えたか」だけを並べ直した新しい系列で、「どれくらい高い水準にいるか」という話が「どちらへどれだけ動いたか」という話に入れ替わります。直線的なトレンドはこれ1回で消え、曲がったトレンドなら2回。1年周期なら yt−yt−12y_t - y_{t-12} という季節差分を使います。

ただし取りすぎてはいけません。本来の信号まで削り、残ったノイズを増幅します。「定常になる最小回数だけ」が原則です。

FIG 1次数を上げると訓練点は完璧に通るのに、少し外に出た途端に暴れる。時系列ではこの「少し外」が必ず未来側にあり、しかも訓練区間の終わりの直後から始まる。過去への当てはまりの良さは、将来の当たりやすさを何ひとつ保証しない

ARIMA: 3つの部品でできている

ARIMAは名前が3つの部品の頭文字になっているだけの、素直なモデルです。

AR(自己回帰) は、過去の自分の線形和で今を説明します。

yt=c+ϕ1yt−1+⋯+ϕpyt−p+εty_t = c + \phi_1 y_{t-1} + \cdots + \phi_p y_{t-p} + \varepsilon_t
(3)

ϕi\phi_i は ii ステップ前の値にかける重み、pp は何ステップ前まで見るか、εt\varepsilon_t は誤差、cc は定数です。言い換えれば「今日の値=基準になる値+1つ前の値の何割か+2つ前の値の何割か+…+その日だけの運」と読める式です。直感は慣性——「昨日高かったから今日も高い」。

MA(移動平均) は、過去の誤差の線形和です。

yt=μ+εt+θ1εt−1+⋯+θqεt−qy_t = \mu + \varepsilon_t + \theta_1 \varepsilon_{t-1} + \cdots + \theta_q \varepsilon_{t-q}
(4)

μ\mu は平均、θj\theta_j は jj ステップ前の誤差にかける重み。つまり「今日の値=いつもの平均+今日ぶんの運+昨日の運の何割かが尾を引いた分+…」ということ。ここでの誤差は、モデルが説明しきれなかった予想外のぶんを指します。直感はショックの残り香——「先週の予想外の落ち込みが、まだ尾を引いている」。名前は紛らわしいのですが、平滑化の移動平均とは別物です。

I(和分) が、さきほどの差分です。dd 回差分してからARとMAを当てる、というだけ。これで ARIMA(p,d,q)\mathrm{ARIMA}(p,d,q) が揃います。季節成分を別枠で持たせたものが SARIMA(p,d,q)(P,D,Q)s\mathrm{SARIMA}(p,d,q)(P,D,Q)_s、ss は周期です。

分解: トレンド・季節・残差に割る

もう1つの基本動作が分解です。

yt=Tt+St+Rty_t = T_t + S_t + R_t
(5)

TtT_t はトレンド(長期の水準)、StS_t は季節成分、RtR_t は残差。要するに「観測された値は、ゆっくり動く地力と、毎年決まって繰り返す上下と、そのどちらでも説明できない残りの、3つを足したもの」と見なす約束です。掛け算の形 yt=Tt×St×Rty_t = T_t \times S_t \times R_t もあり、季節変動の幅が水準に比例するなら乗法を選びます。対数を取れば乗法は加法になるので、実務では「まず対数変換」がよく効きます。

主な使い道は予測より診断です。残差に明らかな周期が残っていれば季節を取りきれていない。特定の期間だけ残差が大きければ、そこで何かが起きている(キャンペーン、障害、欠損)。STLはその道具です。

深層モデルと基盤モデルの位置づけ

古典手法は「1つの系列に1つのモデル」という設計で、店舗が1万あれば1万個を推定します。深層モデルが持ち込んだ最大の転換はグローバルモデル——全系列をまとめて1つのモデルで学習し、系列ごとの違いは埋め込みや共変量で表す考え方です。履歴の短い系列が、似た系列から学べます。

DeepAR系は再帰型ネットワークで次の1点の分布のパラメータを出すので、サンプリングを繰り返せば予測区間が得られます。N-BEATS系は再帰を使わず、全結合ブロックを積んで残差を次へ渡します。ただし系列数が少なく履歴が短ければ、深層モデルは古典手法やナイーブ法に普通に負けます。 利点が「多数の系列」から来る以上、系列が1本なら前提が成立していません。

その延長が時系列基盤モデルです。大量かつ異種の時系列で事前学習した1つのモデルに、未見の系列をそのまま食わせる。価値は精度より立ち上げの速さで、データを渡せば数分でゼロショットのベースラインが出ます。ただし粒度や外生変数の設計は依然として自前です。

評価: ここで一番事故が起きる

時系列の失敗のほとんどは、モデル選択ではなく評価設計で起きます。

ランダム分割は禁止

KK-fold交差検証でランダムに分けると、「未来の点で訓練して過去の点を予測する」組み合わせが必ず生まれます。本番では絶対に起こらない状況です。しかも自己相関があるので、ほぼ同じ情報を持つ隣接点という双子が訓練側と検証側に分かれる。検証スコアは本番より必ず良く出ます。過学習と評価設計で扱った漏洩の、時系列固有で最悪の形です。

正しいのは時間順の前進検証

expanding window(原点を進めながら訓練区間を伸ばす)か rolling window(幅を固定してずらす)で、常に「訓練区間 → その直後の検証区間」の向きだけを使う。これがバックテストです。1回の分割で決めないこと。起点をずらして平均と散らばりの両方を見ます。

漏洩を塞ぐ2箇所

7日移動平均を特徴量に使うなら、訓練区間の最終日の特徴量が検証区間の値を参照しかねません。訓練の終わりと検証の始まりの間に、窓幅と予測ホライズンぶんのギャップを空けます。もう1つは前処理。標準化の平均・標準偏差を全期間で計算するのは気付かれにくい漏洩で、スケーラは各分割の訓練区間でfitします。

ホライズンを揃え、ベースラインを置く

1ステップ先のモデルを24回回して24時間先を作ると、自分の誤差を自分に食わせ続けて誤差が累積します。ホライズンごとに別モデルを学習するか多出力にして、学習時と本番でホライズンを揃えること。そのうえで、直前の値を使うナイーブ予測、1周期前を使う季節ナイーブ、単純平均を必ず並べます。これに勝てない深層モデルは珍しくありません。

MAPEの罠

現場で最も使われ、最も誤解されている指標です。

MAPE=100n∑t=1n∣yt−y^tyt∣\mathrm{MAPE} = \frac{100}{n}\sum_{t=1}^{n}\left|\frac{y_t - \hat{y}_t}{y_t}\right|
(6)

y^t\hat{y}_t は予測値、nn は評価点数。言い換えれば、各時点で「実測の何割ぶん外したか」を出し、それを全時点で平均して100倍しただけ——「平均して何%ずれるか」です。落とし穴が4つ。第一に、実測が0だと定義できません。売れない日がある間欠需要では致命的です。第二に、実測が小さいほど誤差が過大評価されます。売上1個の日に1個外せば100%、1000個の日に10個外しても1%。第三に、非対称です。過小予測は最大100%で頭打ちなのに過大予測には上限がなく、最適化するとモデルは低めへ寄ります。第四に、水準の違う系列を混ぜると平均が壊れます(後述)。

代替として広く使われるのがMASEです。

MASE=1n∑t∣yt−y^t∣1n−s∑t=s+1n∣yt−yt−s∣\mathrm{MASE} = \frac{\frac{1}{n}\sum_t |y_t - \hat{y}_t|}{\frac{1}{n-s}\sum_{t=s+1}^{n} |y_t - y_{t-s}|}
(7)

分母は「ss 周期前の値をそのまま使うナイーブ予測」の平均誤差です。分子は、自分の予測が平均していくつ外したか。つまりMASEはナイーブの何倍の誤差かを表し、1未満なら勝ち。スケールに依存しないので系列間で足せ、実測0でも壊れません。

集約の仕方まで決める

系列ごとの指標を単純平均すると、小さい系列が全体を支配します。金額で効くのは大きい系列。何で平均するかは技術ではなく事業の選択です。

現場ではこう使う

時系列予測を実際に組むのは、小売・製造の需要予測、インフラのキャパシティプランニング、電力・交通の需要予測、広告予算の配分をやる人たちです。共通するのは、予測値がそのまま「いくつ発注するか」になること。

触る道具はおおむね決まっています。古典側はstatsmodelsの SARIMAX(order=(p,d,q), seasonal_order=(P,D,Q,s)) と STL(period=...)。検証は scikit-learn の TimeSeriesSplit(n_splits=..., gap=..., max_train_size=...) で、この gap が前述の空白です。Prophetなら changepoint_prior_scale(トレンドの折れやすさ)、seasonality_mode='multiplicative'、holidays。深層側はdartsやGluonTSの context_length、prediction_length、freq。特徴量はラグ、ローリング統計、フーリエ項、祝日フラグが定番です。

欠測を0で埋める。 「売れなかった」と「店が閉まっていた」は別の事象です。0で埋めた瞬間、存在しない需要の落ち込みを学習します。

祝日・キャンペーン・価格変更を外生変数に入れない。 毎年同じ日に同じ方向へ外し続け、その失敗が季節成分に吸収されて見えにくくなります。

販売実績をそのまま需要とみなす。 売り切れた日の販売数は需要ではなく在庫の量です。需要として学習すると過小評価し、発注を減らし、また売り切れる。予測が自分でデータを汚します。

点予測しか出さない。 在庫の適正量は平均的な需要ではなく、欠品コストと過剰在庫コストの比で決まる分位点です。

面接や設計レビューで問われるのは、だいたい3つ。「なぜランダムな KK-fold を使ってはいけないか」——未来から過去を予測する組み合わせが生まれ、自己相関で双子が分かれて入るから。「MAPEの問題点を挙げよ」——0除算、小実測での過大評価、非対称性。「深層モデルとARIMA、どちらから試すか」——まず季節ナイーブ、次に古典、系列数が多ければ深層。この順番を言えることが、そのまま設計力の説明になります。

まとめ

次は、同じ「系列を読む」問題を音声で解く側——波形からテキストへ、音声認識の中身を見ていきます。

運営: TechAthletes · 編集方針 · 出典の付け方 · 訂正の記録

コメント

コメントにはログインが必要です