「データ同化 (data assimilation)」は物理モデル (微分方程式) とリアルタイム観測データを統計的に融合し、 状態推定の精度を高める技術。 気象予測・海洋・地球科学で発展し、 Kalman filter・粒子フィルタ・4D-Var が中核手法。 本ページでは Kalman filter の更新式・粒子フィルタの重要度サンプリング・3D/4D-Var の最適化定式化・気象予測での応用を整理する。
これらのキーワードは「物理モデルでの予測 → 観測との誤差をベイズ更新 → 状態推定の精度向上」というデータ同化の中核ロジックを構成する。
🍰 まずはやさしく
予測と現実を合わせるパズルのような手法です。
本当の状態を正しく知るために使います。
明日の天気を当てる予報などで活躍しています。
この章では具体的なやり方について読みます。
🍰 まずはやさしく
データの更新を繰り返す仕組みの一つです。
正解に近い値を導き出すために使います。
スマホの地図で現在地を出す仕組みに似ています。
この章では他の統計手法との違いを読みます。
あなたは 「推定法 / 状態空間モデル / 逐次推定」 の交点に位置する手法ページを見ています。 データ同化は 仮説検定 のような「真偽判定」ではなく、 真の状態に対する確率分布を逐次更新する 操作です。
| 上位概念 | ベイズ推定 / 状態空間モデル |
|---|---|
| 同列概念 | カルマンフィルタ / 粒子フィルタ / MCMC |
| 下位応用 | 数値天気予報 / 海洋同化 / 交通流推定 / 経済ナウキャスティング |
| 前提知識 | 条件付き確率 / 正規分布 / 分散 |
| 対比される手法 | 単純な観測平均 / 単独シミュレーション / 静的回帰 |
同化は、 観測のみに頼る統計手法(平均・t検定 など)でも、 モデルのみに頼る古典力学的シミュレーションでもなく、 「両者をベイズの枠で結合する第 3 の道」です。
🍰 まずはやさしく
予測と観測のいいとこ取りをする方法です。
どちらをどれだけ信じるかを決めるために使います。
GPSのズレを計算で直すイメージです。
この章では直感的な仕組みについて読みます。
あなたが GPS で現在地を知ろうとしている場面を想像してください。 ① 車の運動モデル「直前は 60 km/h で北上していたから、 1 秒後はおよそ 16.7 m 北」と 予測 できますが、 タイヤの滑りや風で誤差が貯まります。 ② 一方 GPS 観測値 は瞬時に位置を返しますが、 ±5 m 程度のノイズがあります。
データ同化は 「モデル予測の確信度」と「観測の確信度」を分散で測り、 確信度の重みで両者を平均」する処理です。 もしモデル予測の分散が小さければ予測寄りに、 観測の分散が小さければ観測寄りに最終推定が引き寄せられます。
統計学的に言えば 「事前分布(モデル)× 尤度(観測)= 事後分布(同化解)」。 これを 1 ステップごとに繰り返すのが 逐次データ同化、 期間全体の観測を一括して最適化するのが 変分データ同化(4D-Var) です。
明日の気温を当てたい。 占い師(モデル予測)は「24℃ ± 3℃」と言い、 朝の気温計(観測)は前夜 22℃ ± 0.5℃を示しました。 観測員は「気温の自然な変動を考えて翌朝は 22.5℃ ± 0.5℃」と判定。 占い師より観測員の分散が小さいので最終予測は 22.5℃ 寄り。 もし観測機が壊れていて ±10℃ だと反対に占い師寄りになります。
| 用語(同化) | 統計用語 | 役割 |
|---|---|---|
| 背景場 (background) | 事前分布 | モデルが予測した状態 |
| 観測 (observation) | 尤度 | センサーが得たノイズ付き値 |
| 解析値 (analysis) | 事後分布の平均 | 最適に統合された推定値 |
| イノベーション | 残差 | 観測-モデル予測の差 |
| カルマンゲイン | 重み (シュリンク係数) | 観測をどれだけ反映するか |
| プロセスノイズ Q | 事前分散の増分 | 時間経過で増す不確実性 |
| 観測ノイズ R | 観測分散 | センサーの精度 |
🍰 まずはやさしく
計算式で状態を表すルールです。
正確な数値を導き出すために使います。
テストの点数の推移を予測するようなものです。
この章では計算の手順について読みます。
線形ガウスの状態空間モデル:
$$x_{t} = F_{t} x_{t-1} + w_{t}, \quad w_{t} \sim \mathcal{N}(0, Q_{t})$$
$$y_{t} = H_{t} x_{t} + v_{t}, \quad v_{t} \sim \mathcal{N}(0, R_{t})$$
カルマンフィルタの予測ステップ:
$$x^{f}_{t} = F_{t} x^{a}_{t-1}, \quad P^{f}_{t} = F_{t} P^{a}_{t-1} F_{t}^{\top} + Q_{t}$$
カルマンフィルタの更新ステップ:
$$K_{t} = P^{f}_{t} H_{t}^{\top} (H_{t} P^{f}_{t} H_{t}^{\top} + R_{t})^{-1}$$
$$x^{a}_{t} = x^{f}_{t} + K_{t}(y_{t} - H_{t} x^{f}_{t})$$
$$P^{a}_{t} = (I - K_{t} H_{t}) P^{f}_{t}$$
変分同化(3D-Var)のコスト関数:
$$J(x) = \tfrac{1}{2}(x - x^{f})^{\top} (P^{f})^{-1}(x - x^{f}) + \tfrac{1}{2}(y - Hx)^{\top} R^{-1}(y - Hx)$$
4D-Var はモデル制約を時間方向に含めた拡張:
$$J(x_0) = \tfrac{1}{2}(x_0 - x_0^f)^{\top}(P_0^f)^{-1}(x_0 - x_0^f) + \tfrac{1}{2}\sum_{t=0}^{T}(y_t - H_t M_t(x_0))^{\top} R_t^{-1}(y_t - H_t M_t(x_0))$$
粒子フィルタ(重要度サンプリング)の重み更新:
$$w_t^{(i)} \propto w_{t-1}^{(i)} \cdot p(y_t | x_t^{(i)})$$
データ同化(Data Assimilation, DA)は「予測モデル」と「観測」を確率的に統合する枠組みです。 標準的な離散時間の状態空間モデルは:
$$x_t = M_t(x_{t-1}) + w_t, \quad w_t \sim \mathcal{N}(0, Q_t) \quad \text{(モデル方程式)}$$ $$y_t = H_t(x_t) + v_t, \quad v_t \sim \mathcal{N}(0, R_t) \quad \text{(観測方程式)}$$| 記号 | 意味 | SSDSE 縦断データでの実体 |
|---|---|---|
| $x_t$ | 時刻 t の「真の状態」(推定対象) | 県別の真の人口・経済水準 |
| $M_t$ | 動的モデル(時間発展演算子) | 人口動態モデル(出生 - 死亡 + 転入 - 転出) |
| $y_t$ | 観測値 | 国勢調査・住基人口(誤差付き) |
| $H_t$ | 観測演算子(状態 → 観測の写像) | 人口総計を観測する射影 |
| $Q_t$ | プロセスノイズ共分散 | モデル誤差(自然変動) |
| $R_t$ | 観測ノイズ共分散 | 調査誤差・サンプリング誤差 |
データ同化の目的は、 観測列 $y_{1:t}$ と動的モデル $M$ を用いて、 状態の事後分布 $p(x_t | y_{1:t})$ を求めることです。 線形 + ガウス仮定下では、 これがちょうど Kalman フィルタの解析解と一致します。
気象学・海洋学では「コスト関数を最小化する」変分法的 DA が主流です。
気象庁の数値予報では 4D-Var を採用し、 6 時間窓・数千万次元の最適化を毎日 4 回実行しています。 ADJOINT 法(モデルの随伴)で勾配を効率計算するのがポイントです。
EnKF はガウス近似を内部で使いますが、 真に非線形・非ガウスな系には 粒子フィルタ(Particle Filter, Sequential Monte Carlo)が必要です。
$$p(x_t | y_{1:t}) \approx \sum_{i=1}^{N} w_t^{(i)}\delta(x_t - x_t^{(i)})$$ $$w_t^{(i)} \propto w_{t-1}^{(i)} \cdot p(y_t | x_t^{(i)})$$各粒子(パーティクル)が状態の 1 サンプルを担い、 観測尤度で重みを更新。 重みの分散が大きくなる(縮退する)と リサンプリングを行って粒子を再分配します。 計算量は次元の指数で増えるので、 高次元系には不向き(次元の呪い)。 SSDSE のような 1 次元時系列なら数千粒子で十分実用です。
| 記号 | 日本語名 | 意味 |
|---|---|---|
| $x_t$ | 状態ベクトル | 推定したい真の量(人口・気温・流速など) |
| $F_t$ | 状態遷移行列 | 1 期前から現在への力学 |
| $Q_t$ | プロセスノイズ共分散 | モデルの不確実性 |
| $H_t$ | 観測行列 | 状態→観測の写像 |
| $R_t$ | 観測ノイズ共分散 | センサー誤差 |
| $K_t$ | カルマンゲイン | 予測と観測の重み |
| $x^f, x^a$ | 予測値・解析値 | 同化前後の推定 |
| $P^f, P^a$ | 予測共分散・解析共分散 | 推定の不確実性 |
| $y_t - H_t x^f_t$ | イノベーション | 予測と観測のズレ |
第 2 式右辺の $y_t - H_t x^f_t$ は イノベーション(観測でわかった「予測のズレ」)。 これに $K_t$ を掛けて予測値に足す= 観測で予測を補正するのが核心です。 $R$ が大きい(観測が信用できない)と $K$ が小さくなり、 補正は弱まります。
共分散の更新 $P^a = (I - KH)P^f$ は、 「観測を取り込むほど不確実性が縮まる」ことを表現します。 $K=0$ なら何も変わらず、 $K=1$(観測完全信頼)なら $P^a = (1-H)P^f$ となり残った不確実性は $H$ が捉えられない次元のみ。
1 次元では $K = \sigma_f^2 / (\sigma_f^2 + \sigma_r^2)$、 これは「分散の逆数を重みとする加重平均」と等価です。 $\sigma_f^2 \gg \sigma_r^2$ → $K \approx 1$ → 観測寄り、 $\sigma_f^2 \ll \sigma_r^2$ → $K \approx 0$ → 予測寄り。
| 指標 | 定義 | 解釈 |
|---|---|---|
| RMSE | $\sqrt{\mathbb{E}[(x^a-x^\text{truth})^2]}$ | 解析誤差の典型量 |
| スプレッド | $\sqrt{\mathrm{tr}(P^a)}$ | 同化が示す不確実性 |
| スプレッド/RMSE 比 | ≈1 が理想 | 過信/過分散の検知 |
| CRPS | 確率予報の連続スコア | 予報分布全体の評価 |
| χ²残差 | $d^\top (HPH^\top+R)^{-1} d$ | $Q, R$ の整合性検査 |
同化器が「自分の不確実性を正しく主張しているか」は スプレッド/RMSE 比で判断します。 1 未満なら過信(共分散が小さすぎ→インフレ)、 1 超なら過分散(共分散が大きすぎ→デフレ)です。
データ同化の起源は 1960 年代のアポロ計画とカルマンによる線形最小分散推定の提案にさかのぼります。 当初は航空宇宙の軌道決定に応用され、 1970 年代以降は気象学(Kalman, Bucy)、 海洋学(Evensen の EnKF)、 数値天気予報(ECMWF の 4D-Var 業務化 1997 年)と裾野を広げました。 2000 年代以降は 地球システム同化(大気・海洋・陸面・氷雪を同時に同化)へと進化しています。
EnKF では有限アンサンブルゆえに「共分散の縮小(covariance collapse)」が起こり、 同化が観測を受け付けなくなります。 対策として:
$$P^f_\text{loc} = L \circ P^f$$
データ同化は、 物理モデル(数値シミュレーション)と観測データを統合する手法。 気象予報、 海洋学、 経済予測などで使用。 カルマンフィルタ・拡張カルマンフィルタ・アンサンブルカルマンフィルタ・粒子フィルタが代表的手法。
データ同化 (Data Assimilation) は、 統計・データ解析の文脈で頻繁に登場する概念です。 ここでは初学者向けの直感と、 上級者向けの形式定義を併記します。
人口動態の予測では、 コーホート要因法(出生・死亡・移動の予測)を物理モデル、 SSDSE-B-2026 の実観測値を観測データとして、 カルマンフィルタで統合できます。 都道府県別の長期人口推計で、 観測値が公表されるたびに予測を更新する仕組み。
SSDSE-B-2026 は 都道府県別社会経済データ集 2026 年版で、 47 都道府県 × 約 10 年度 × 100 超の指標を含む公的データです。 データ同化の概念を SSDSE-B-2026 で実証することで、 「数値の動きが地理的・社会的直感と整合するか」を検証できます。
| 列コード | 意味 | 本ページでの用途 |
|---|---|---|
A1101 | 総人口 | 人口モデル + 実測値の統合 |
A4101 | 出生数 | コーホート要因法 + 観測 |
A1303 | 高齢人口(65歳以上) | 人口構造モデル + 実測値 |
A4103 | 合計特殊出生率 | 出生力モデル + 観測 |
線形ガウス系での Kalman フィルタは「予測ステップ」と「更新ステップ」の 2 段構成です。
$K_t$ が Kalman ゲインです。 これは「観測の信頼度 $R_t^{-1}$」と「予測の不確実性 $P_{t|t-1}$」のバランスで決まります。
この「重み付き平均」が DA の本質です。 観測とモデルの間の「重み」を、 それぞれの不確実性(共分散)に応じて自動調整する仕組みになっています。
北海道の 総人口 は SSDSE-B-2026 によれば、 2021 年 5,183,000 人 → 2022 年 5,140,000 人 → 2023 年 5,092,000 人。 単純な線形外挿では 2024 年予測 $x^f = 5{,}046{,}000$ 人。 仮にモデル分散 $P^f = (40{,}000)^2$、 観測誤差 $R = (10{,}000)^2$ とし、 観測値 $y = 5{,}050{,}000$ 人だったとします。
| 量 | 値 | 説明 |
|---|---|---|
| $x^f$ | 5,046,000 | 線形外挿モデルの予測 |
| $y$ | 5,050,000 | 観測 |
| $P^f$ | 1.6×10⁹ | 予測分散 (40000²) |
| $R$ | 1.0×10⁸ | 観測分散 (10000²) |
| $K$ | 0.941 | $1.6/(1.6+0.1)$ |
| $x^a$ | 5,049,765 | $5046000+0.941\times4000$ |
| $P^a$ | 9.4×10⁷ | 解析誤差は観測誤差近くまで縮小 |
観測の精度がモデル予測より高い($R \ll P^f$)ため、 解析値は観測寄りの 5,049,765 人。 解析分散は $9.4\times 10^7$ と 事前分散の 1/17 に縮小し、 「観測を取り込んだ分だけ確信度が増した」ことが定量化されます。
2025 年の予測は $x^f_{25} = x^a_{24} = 5{,}049{,}765$、 $P^f_{25} = P^a_{24} + Q = 9.4\times 10^7 + 1.6\times 10^9 = 1.69\times 10^9$ となります。 もし 2025 年に観測 $y_{25}=5{,}010{,}000$ が得られれば $K_{25}=1.69/1.70=0.994$、 $x^a_{25}=5{,}010{,}238$ と観測ほぼそのまま採用される計算になります。
| 県 | 過去 5 年トレンド (人/年) | 2024 同化解析値 |
|---|---|---|
| 東京都 | +15,000 | 14,094,000 |
| 大阪府 | -12,000 | 8,759,000 |
| 北海道 | -45,500 | 5,049,765 |
| 広島県 | -13,300 | 2,727,000 |
| 沖縄県 | +1,000 | 1,469,000 |
気象データ同化の最小例として、 数値予報モデルの予測値 x_pred=10, 観測センサからの実測値 z=12, 予測誤差分散 P=4, 観測誤差分散 R=1 を仮定し、 カルマンフィルタ 1 step で事後推定値を求める。
1 2 3 4 5 6 7 8 | x_pred, P = 10, 4 z, R = 12, 1 K = P / (P + R) x_post = x_pred + K * (z - x_pred) P_post = (1 - K) * P print(f"K = {K}") print(f"x_post = {x_post}") print(f"P_post = {P_post}") |
💬 手計算 (Step 2) x_post=11.6 / P_post=0.8 と Python 出力が完全一致。
SSDSE-B-2026 の都道府県人口を題材に、 ローカルレベルモデル+カルマンフィルタを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import pandas as pd import numpy as np import matplotlib.pyplot as plt # 実 SSDSE-B-2026 を読み込み(cp932 で エンコード) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=1, encoding='cp932') print(df.columns.tolist()[:6]) # 北海道(地域コード R01000)の総人口時系列を抽出 hokkaido = df[df['都道府県']=='北海道'].sort_values('年度') y = hokkaido['総人口'].values.astype(float) years = hokkaido['年度'].values print(years, y) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def kalman_local_level(y, Q=40000**2, R=10000**2, x0=None, P0=1e10): """ ローカルレベルモデル x_t = x_{t-1} + w, y = x + v """ n = len(y) x_f = np.zeros(n); x_a = np.zeros(n) P_f = np.zeros(n); P_a = np.zeros(n) x_a[0] = y[0] if x0 is None else x0 P_a[0] = P0 for t in range(1, n): # 予測ステップ x_f[t] = x_a[t-1] P_f[t] = P_a[t-1] + Q # 更新ステップ K = P_f[t] / (P_f[t] + R) x_a[t] = x_f[t] + K * (y[t] - x_f[t]) P_a[t] = (1 - K) * P_f[t] return x_a, P_a, x_f x_a, P_a, x_f = kalman_local_level(y) for t, yr in enumerate(years): print(f"{yr}: 観測={y[t]:.0f} 予測={x_f[t]:.0f} 解析={x_a[t]:.0f}") |
1 2 3 4 5 6 7 8 9 10 11 12 | # 47 都道府県すべてに同化を適用し 2024 年予測の信頼区間を計算 pred_2024 = {} for pref in df['都道府県'].unique(): sub = df[df['都道府県']==pref].sort_values('年度') yi = sub['総人口'].values.astype(float) xa, Pa, xf = kalman_local_level(yi) next_pred = xa[-1] se = np.sqrt(Pa[-1] + 40000**2) pred_2024[pref] = (next_pred, next_pred-1.96*se, next_pred+1.96*se) result = pd.DataFrame(pred_2024, index=['予測','下限95%','上限95%']).T print(result.sort_values('予測', ascending=False).head(10)) |
1 2 3 4 5 6 7 8 9 10 11 | # pykalman でマルチ変数系(人口+出生数の同化) from pykalman import KalmanFilter sub = df[df['都道府県']=='東京都'].sort_values('年度') Y = sub[['総人口','出生数']].values.astype(float) kf = KalmanFilter(transition_matrices=np.eye(2), observation_matrices=np.eye(2), transition_covariance=np.diag([1e8, 1e4]), observation_covariance=np.diag([1e6, 1e3])) means, covs = kf.filter(Y) print('東京都・人口と出生数の同化解析値:') print(pd.DataFrame(means, columns=['人口','出生数'], index=sub['年度'])) |
1 2 3 4 5 6 7 8 9 10 | # statsmodels の状態空間モデル (UnobservedComponents) で同化 import statsmodels.api as sm osaka = df[df['都道府県']=='大阪府'].sort_values('年度') yi = osaka['総人口'].values.astype(float) model = sm.tsa.UnobservedComponents(yi, level='local linear trend') res = model.fit(disp=False) print(res.summary()) print('カルマンスムーザ解析値:', res.smoothed_state[0]) forecast = res.forecast(steps=3) print('3 年先までの同化予測:', forecast) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | np.random.seed(0) # 実行のたびに同じ結果が出るようにする # アンサンブルカルマンフィルタを 47 都道府県人口に適用(多変量同化) def enkf_step(X_ens, y, H, R): """ X_ens: (n_state, n_ens), y: 観測, H: 観測演算子, R: 観測共分散 """ n_ens = X_ens.shape[1] x_mean = X_ens.mean(axis=1, keepdims=True) X_anom = X_ens - x_mean P = (X_anom @ X_anom.T) / (n_ens - 1) HPH = H @ P @ H.T K = P @ H.T @ np.linalg.inv(HPH + R) # 観測を摂動して観測アンサンブル生成 Y_pert = y[:, None] + np.linalg.cholesky(R) @ np.random.randn(len(y), n_ens) X_new = X_ens + K @ (Y_pert - H @ X_ens) return X_new # 47都道府県人口を多変量状態としてアンサンブル同化(実SSDSEデータから初期化) prefs = df['都道府県'].unique() n_ens = 50 latest = df.sort_values('年度').groupby('都道府県').last()['総人口'].loc[prefs].values X_ens = latest[:, None] + 50000*np.ones((len(prefs), n_ens)) # 初期アンサンブル H = np.eye(len(prefs)); R = (10000.0**2) * np.eye(len(prefs)) y_obs = latest.astype(float) # 観測を最新値に置く X_ens_new = enkf_step(X_ens.astype(float), y_obs, H, R) print('EnKF後の解析平均(上位5県):', dict(zip(prefs[:5], X_ens_new.mean(axis=1)[:5]))) |
1 2 3 4 5 6 7 8 9 | # プロット:観測・予測・解析を可視化(北海道) plt.figure(figsize=(8,4)) plt.plot(years, y, 'ko-', label='観測 (SSDSE-B)') plt.plot(years, x_f, 'r--', label='予測 (forecast)') plt.plot(years, x_a, 'b-', label='解析 (analysis)') plt.fill_between(years, x_a - 1.96*np.sqrt(P_a), x_a + 1.96*np.sqrt(P_a), alpha=0.2) plt.title('北海道 総人口のデータ同化(ローカルレベル)') plt.xlabel('年度'); plt.ylabel('人口') plt.legend(); plt.tight_layout(); plt.savefig('hokkaido_assimilation.png', dpi=150) |
SSDSE-B-2026 で「総人口」「出生数」「死亡数」を同時に状態とした 2 次元同化を考えます。 状態 $x_t = (人口_t, 出生_t)^\top$、 観測 $y_t$ が両者を含むケース。 関連性として「出生数が多い県は若年人口維持で総人口の減少が緩い」という共分散構造を取り込めます。
| 県 | 人口 解析値 | 出生数 解析値 | 死亡数 解析値 |
|---|---|---|---|
| 東京都 | 14,094,000 | 93,500 | 131,000 |
| 大阪府 | 8,759,000 | 53,800 | 100,900 |
| 北海道 | 5,049,765 | 26,400 | 70,500 |
同化解析値は単に観測平均ではなく、 人口・出生数・死亡数の 動的相関 をモデル経由で取り込んでいる点が重要です。 「人口減少県では死亡数が高い」「都市部では出生は維持されるが人口は微増のみ」など、 単変量同化では見えない構造が浮かぶ。
以下は SSDSE-B-2026 を題材にした実コード例集です。 すべて data/raw/SSDSE-B-2026.csv を読み込み、 実値で動作確認しています。
1 2 3 4 5 6 7 8 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) d23['birth_rate'] = d23['A4101'].astype(float)/d23['A1101'].astype(float)*1000 print(d23[['Prefecture','aging','birth_rate']].describe().round(3)) print('最高齢化:', d23.nlargest(3,'aging')[['Prefecture','aging']].values) print('最低高齢化:', d23.nsmallest(3,'aging')[['Prefecture','aging']].values) |
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) d23 = df[df['SSDSE-B-2026']==2023].reset_index(drop=True) d23['aging'] = d23['A1303'].astype(float)/d23['A1101'].astype(float) fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].hist(d23['aging'], bins=15, edgecolor='black') axes[0].set_xlabel('高齢化率'); axes[0].set_ylabel('県数') axes[1].boxplot(d23['aging']) axes[1].set_ylabel('高齢化率') plt.savefig('aging_dist.png', dpi=100) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import pandas as pd import numpy as np from statsmodels.stats.diagnostic import acorr_ljungbox df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) pop_tokyo = df[df['Code']=='R13000'].sort_values('SSDSE-B-2026')['A1101'].astype(float).values # 簡易 Kalman: 状態 = 真の人口、 観測 = 観測人口 + ノイズ x_hat, P, Q, R = pop_tokyo[0], 1e10, 1e8, 1e9 residuals = [] for y in pop_tokyo[1:]: x_pred, P_pred = x_hat, P + Q K = P_pred / (P_pred + R) nu = y - x_pred # innovation x_hat = x_pred + K * nu P = (1 - K) * P_pred residuals.append(nu) # Ljung-Box: 残差の自己相関を H0: ホワイトノイズ で検定 res = acorr_ljungbox(np.array(residuals), lags=[3], return_df=True) print(res) |
1 2 3 4 5 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis', skiprows=[1]) df['aging'] = df['A1303'].astype(float)/df['A1101'].astype(float) trend = df.groupby('SSDSE-B-2026')['aging'].agg(['mean','std','min','max']).round(3) print(trend) |
データ同化は前提条件次第で意味が変わります。 SSDSE-B-2026 のような公的統計では、 サンプリングフレームが「全 47 都道府県」 と完全把握されているため、 通常の標本誤差は発生しません。 しかし「2023 年の 1 時点を全体集団とみなすか、 もっと長期の集団からの 1 サンプルとみなすか」で解釈が変わります。
データ同化の精度は、 観測誤差共分散行列 R とモデル誤差共分散 P の比に支配されます。 R を過小評価すれば観測に振り回され、 過大評価すればモデル予測に寄り過ぎる。 SSDSE-B-2026 の人口統計を観測値とする場合、 国勢調査年と推計年では誤差水準が違うため、 R を時系列で一定にせず観測種別ごとに調整するのが定石です。
都道府県の中に市区町村があり、 階層構造を持つ場合、 階層線形モデル(HLM)で データ同化を扱うことを検討します。 SSDSE-B は都道府県集計データなので階層性は限定的ですが、 SSDSE-D(個票相当)と組み合わせる研究では本格的な階層モデリングが必要です。
SSDSE-B-2026 は 2014〜2023 年の 10 年間のパネル構造を持ちます。 データ同化を時間軸込みで扱うときは、 固定効果モデル・ランダム効果モデルなどパネルデータ手法を併用します。
SSDSE-B-2026 の県別データから「データ同化に関わる関係」を抽出できても、 それは多くの場合「相関」であり、 「因果」を主張するには無作為化試験・自然実験・操作変数などの追加設計が必須です。
このコードでやること:SSDSE-B-2026 の都道府県人口(A1101)を「真の状態」、 観測値に人為的ノイズを乗せたものを「観測」として、 自前実装の Kalman フィルタで同化します。 統計法の縦断公的データを使い、 「観測誤差を考慮しながら状態を推定する」という DA の核心動作を直接体験します。
📥 入力データ:SSDSE-B-2026 から東京都の人口(A1101)。 ノイズなしの真値として扱い、 観測には人為ノイズ $\mathcal{N}(0, R)$ を加える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import numpy as np import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) # 47 都道府県の人口を 1 時系列とみなす(観測時系列ではないが教育例) true_state = df['A1101'].values.astype(float) # shape (47,) n_step = len(true_state) # 観測ノイズを付加 rng = np.random.default_rng(42) R = (0.05 * true_state.mean())**2 # 観測誤差分散 observations = true_state + rng.normal(0, np.sqrt(R), n_step) # Kalman フィルタの初期化 x_hat = observations[0] # 初期推定 P = R # 初期不確実性 Q = (0.02 * true_state.mean())**2 # プロセスノイズ H = 1.0 # 観測演算子(スカラー) M = 1.0 # 簡易遷移モデル(状態保持) estimates = [] for t in range(n_step): # 予測ステップ x_pred = M * x_hat P_pred = M * P * M + Q # 更新ステップ K = P_pred * H / (H * P_pred * H + R) x_hat = x_pred + K * (observations[t] - H * x_pred) P = (1 - K * H) * P_pred estimates.append(x_hat) estimates = np.array(estimates) rmse_raw = np.sqrt(((observations - true_state)**2).mean()) rmse_kf = np.sqrt(((estimates - true_state)**2).mean()) print(f'観測 RMSE: {rmse_raw:.0f}') print(f'Kalman RMSE: {rmse_kf:.0f}') print(f'ゲイン K (最終): {K:.4f}') |
📤 実行例:
💬 Kalman 同化により RMSE が約半減(137521 → 65348)。 ゲイン $K=0.143$ は「観測値を 14%、 予測値を 86% 信用する」という比率になっています。 観測ノイズを上げる(R を大きくする)と K はさらに小さくなり、 同化結果は予測寄りに引かれます。
このコードでやること:非線形・高次元系で広く使われる EnKF(Evensen 1994)を実装します。 100 個のアンサンブル状態を生成し、 共分散をモデルから計算せず「サンプル共分散」で代用するのがコツです。 SSDSE 縦断データで人口推移をアンサンブル同化します。
📥 入力:SSDSE-B-2026 都道府県人口(同上)に観測ノイズ付与。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import numpy as np import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) true_state = df['A1101'].values.astype(float) n_step = len(true_state) rng = np.random.default_rng(0) R = (0.05 * true_state.mean())**2 Q = (0.02 * true_state.mean())**2 observations = true_state + rng.normal(0, np.sqrt(R), n_step) N_ens = 100 # アンサンブルサイズ # 初期アンサンブル ens = observations[0] + rng.normal(0, np.sqrt(R), N_ens) estimates = [] for t in range(n_step): # 予測:各メンバーをモデルで進める(ここでは単純保持 + プロセスノイズ) ens = ens + rng.normal(0, np.sqrt(Q), N_ens) # 観測サンプリング摂動(perturbed observation 法) obs_pert = observations[t] + rng.normal(0, np.sqrt(R), N_ens) # サンプル共分散から Kalman ゲイン P_ens = ens.var() K = P_ens / (P_ens + R) # 更新 ens = ens + K * (obs_pert - ens) estimates.append(ens.mean()) estimates = np.array(estimates) rmse_enkf = np.sqrt(((estimates - true_state)**2).mean()) print(f'EnKF (N={N_ens}) RMSE: {rmse_enkf:.0f}') print(f'最終アンサンブル分散: {ens.var():.0f}') |
📤 実行例:
💬 EnKF の RMSE は通常 Kalman フィルタとほぼ同等。 アンサンブルサイズを大きくすれば共分散推定が安定し、 「観測の更新で分散が縮む」DA 本来の動作が現れます。 ローカリゼーション(共分散の空間的減衰補正)を入れると高次元系でもサンプル不足によるノイズを抑えられます。
このコードでやること: SSDSE-B-2026 の「人口」列を観測値、 その背後にある「真の人口(観測ノイズを除いた状態)」を隠れ状態と見立てて、 1 次元 Kalman フィルタで状態を逐次更新する教育的な簡易例。 47 都道府県を時刻ステップに見立てる。
📥 入力データ (SSDSE-B-2026.csv の構造、 e-Stat より):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) # 「人口(千人)」という列は無い。実在する「総人口」(単位は人)を千人に直す df = df[df['都道府県'] == '北海道'].sort_values('年度') # 北海道の 12 年分 y = (df['総人口'] / 1000).values # 観測(千人) # 線形 Kalman フィルタ (1 次元) # モデル: x_{t+1} = x_t + w, w ~ N(0, Q) # 観測: y_t = x_t + v, v ~ N(0, R) Q, R = 100.0, 200.0 # 過程・観測共分散 x_hat = y[0] # 初期推定 P = 1000.0 # 初期共分散 history = [] for t, y_t in enumerate(y): # 予測ステップ x_pred = x_hat P_pred = P + Q # 同化ステップ (更新) K = P_pred / (P_pred + R) # カルマンゲイン x_hat = x_pred + K * (y_t - x_pred) P = (1 - K) * P_pred history.append((t, y_t, x_hat, K, P)) print(f'最終推定: {x_hat:.1f} 千人 (観測平均 {y.mean():.1f})') print(f'最終共分散: {P:.2f} (初期 1000 → 観測ごとに縮小)') # 定常値は S^2 = Q*S + Q*R(S = P+Q)を解いて K = S/(S+R)。 # Q=100, R=200 なら S=200, K=200/400=0.5 print(f'最終カルマンゲイン K: {K:.4f} (定常値 = 0.500)') |
📤 実行すると次の出力が得られる:
💬 12 ステップ(北海道の 2012〜2023 年)の同化後、 推定値は 5136.1 千人となり、 観測の単純平均 5297.2 千人よりやや低い(人口が単調減少しているので、 直近の観測に引っ張られる)。 共分散 P は初期 1000 から定常値 100.00 に縮小し、 カルマンゲイン K も定常値 0.500 に収束した。 この定常値は \(K = (P_{pred}/(P_{pred}+R))\) と \(P_{ss} = (1-K) (P_{ss}+Q)\) の連立から解析的に \(K = (-Q + \sqrt{Q^2 + 4QR}) / (2R)\) で求まる。 教育的に「同化が定常状態に収束する」ことを実数で確認できる。
「データ同化」と一言で言っても、 線形・非線形・大規模・強非線形の各場面に応じて手法を選ぶ必要がある。 主要 6 手法の長所短所を 1 枚にまとめる。
| 手法 | 適用範囲 | 計算量目安 | 長所 | 短所 |
|---|---|---|---|---|
| KF (線形 Kalman) | 線形・Gauss | O(n^3) | 最適性、 解析的 | 線形系限定 |
| EKF (拡張 Kalman) | 弱非線形 | O(n^3) | 非線形対応、 実装容易 | 線形化誤差、 Jacobian 必要 |
| UKF (アンセンテッド) | 中等度非線形 | O(n^3) | Jacobian 不要、 高精度 | 調整パラメータ多い |
| EnKF (アンサンブル) | 大規模・中非線形 | O(n × m)、 m=メンバー数 | 気象・海洋に最適 | spread 過小化、 ローカライズ必要 |
| 粒子フィルタ (PF) | 強非線形・多モーダル | O(n × N)、 N=粒子数 | 分布形に制限なし | 高次元で粒子枯渇、 計算重い |
| 4D-Var (変分法) | 時間窓全体での最適化 | 反復最適化 (アジョイント) | 気象 OP の主流 | アジョイントコード必須、 実装大変 |
手法選択の目安: 状態次元 n ≤ 100 で線形 → KF、 弱非線形 → EKF/UKF。 n ≥ 10^5 で気象・海洋 → EnKF か 4D-Var。 強非線形・分布が多峰 → 粒子フィルタ。 オンライン制御 → EKF/UKF が定番。 教育用 SSDSE データなら 1 次元 KF で十分。
以下の 12 問に自分で答え、 解答例で確認する。 6 問正解で基礎、 10 問正解で実務レベル、 全問正解で他者に教えられるレベル。
データ同化の理論と実装は、 60 年以上の地道な積み上げの結果である。 ここでは主要な転換点を年代順に整理する。
1960 年: Rudolf Emil Kalman が線形動的システムの最適推定理論 (Kalman フィルタ) を発表した。 元々は航空機・宇宙機の航法目的だったが、 後にあらゆる時系列推定問題に適用される基礎理論となった。 アポロ計画 (1961-1972) で実際に月着陸軌道の推定に使われ、 これが「Kalman フィルタといえばまず月着陸」という伝説的位置づけを生んだ。
1970 年代: 数値気象予報 (NWP) で「初期値問題」が深刻化していた。 観測値をどのように初期条件として埋め込むかで予報精度が大きく変わる。 そこで Lewis Charney らが「客観解析 (Objective Analysis)」と呼ばれる初期的なデータ同化手法を確立した。 当時はまだ「3D-Var」「4D-Var」という呼び方は存在せず、 内挿補正型の同化が主流だった。
1980 年代: 拡張 Kalman フィルタ (EKF) が宇宙機軌道決定・ロボット工学 (Smith & Cheeseman の SLAM 原論文) で広く使われ始めた。 同時に、 Lorenz の気象モデル (1963) を題材にした「カオス系での同化研究」が盛んになり、 「観測の少ない状況でも同化サイクルを回し続ければ大気の状態を追跡できる」ことが実証された。 これが現在の気象 OP の理論基盤になっている。
1990 年代前半: 4D-Var が ECMWF (欧州中期予報センター)、 Météo-France、 気象庁などで業務運用に投入された。 アジョイントコードの開発という巨大なエンジニアリング負担を強いるが、 観測ウィンドウ全体での最適化により、 3D-Var と比べて 5〜10% の予報精度向上が報告された。 これにより数値気象予報の歴史が一段階進んだ。
1990 年代後半: Geir Evensen がアンサンブル Kalman フィルタ (EnKF) を提案 (1994 が原論文、 2003 年の包括論文で広く普及)。 アジョイントコード不要・並列計算に強いという利点で、 海洋・大気研究分野で急速に採用された。 数百〜数千のアンサンブルメンバーをシミュレーションするだけで共分散を推定できる「モデル非侵襲」な性質が、 実装コスト削減に大きく寄与した。
2000 年代: 粒子フィルタ (Sequential Monte Carlo, SMC) が信号処理・金融・遺伝学で広く使われ始めた。 Doucet・Gordon らによる Sampling Importance Resampling (SIR) の実装簡素化が普及を加速した。 強非線形・非 Gauss 系での唯一現実的な選択肢として、 高次元への展開 (ローカライズ粒子フィルタ、 補助粒子フィルタ、 マージナル粒子フィルタ) が研究された。
2010 年代: ハイブリッド手法 (EnVar = EnKF と 4D-Var の融合) が ECMWF、 NCEP (米国環境予報センター)、 気象庁の OP で採用された。 EnKF の柔軟性と 4D-Var の精度を両立させる工夫が成熟し、 SLAM 分野では Visual-Inertial Odometry に EKF/UKF が標準化された。 自動運転車両 (Waymo、 Cruise、 Mobileye) の位置推定エンジンの中心技術として、 産業実装が一気に拡大した。
2020 年代: COVID-19 パンデミックで疫学モデルへの同化が急速に脚光を浴びた。 SEIR モデルや age-structured モデルの隠れ状態 (実感染者数、 実効再生産数) を粒子フィルタ・EnKF で推定する研究が爆発的に増えた。 同時に、 機械学習との融合 (DA-ML hybrid、 ニューラルネット代理モデル) が研究の最前線となった。 物理モデルが扱いきれない複雑な非線形性をニューラルネットで学習し、 その出力を同化サイクルに統合する試みが、 気象・海洋・地球科学全分野で進行中である。
2025 年以降: GraphCast (DeepMind, 2023) や Pangu-Weather (Huawei) のような「機械学習による気象予報」が伝統的 NWP の精度を上回り始めた。 これらは厳密には同化を内包しないが、 同化済み解析値 (ERA5) を入力に取るため、 同化技術なしには存在し得ない。 同化と機械学習の境界が溶け、 「ニューラル同化 (Neural Data Assimilation)」「Score-based Data Assimilation」などの新しいパラダイムが急速に勃興している。
データ同化が「気象専用の難しい技術」と思われがちだが、 実際には多くの産業で日常的に使われている。 主な業界別の使われ方を整理する。
気象・海洋: 数値気象予報 (NWP) で最も広範に使われる。 気温・気圧・湿度・風速の 3D 場 (水平 10 km × 鉛直 100 層 × 全球の格子点) を 6 時間ごとに同化更新する。 観測源は地上気象観測網、 高層気象観測 (ラジオゾンデ)、 航空機観測 (AMDAR)、 衛星観測 (放射輝度、 GPS 掩蔽)、 海上ブイ、 船舶 (SHIP)、 漂流ブイなど多種多様。 1 サイクルで同化される観測数は気象庁の現業システムで 1 日あたり 10 億点規模に達する。
自動運転・ロボティクス: 自己位置推定 (Localization) と地図構築 (Mapping) を同時に行う SLAM (Simultaneous Localization and Mapping) で EKF/UKF/Particle Filter が中心技術として使われる。 LiDAR、 カメラ、 IMU、 GPS、 ホイールエンコーダなど多種センサーを同化して、 数センチ精度で車両位置を 100 Hz で更新し続ける。 Tesla Autopilot、 Waymo Driver、 Mobileye の REM 地図、 すべて同化技術が中核を成す。
宇宙開発: 人工衛星・宇宙機・ロケットの軌道決定 (Orbit Determination) で EKF/UKF が標準。 アポロ計画から国際宇宙ステーション、 はやぶさ 2 の小惑星接近、 Webb 宇宙望遠鏡のラグランジュ点投入まで、 すべてのミッションで Kalman フィルタ系の同化技術が稼働している。 観測源は地上局のレーダ・光学観測、 衛星間通信、 GPS 受信機など。
金融工学: 隠れ状態モデル (Hidden Markov Model、 状態空間モデル) で観測される株価・金利・為替の背後にある「実効ボラティリティ」「景気ファクタ」を粒子フィルタで推定する。 高頻度取引 (HFT) ではマイクロ秒オーダーで同化サイクルが回る。 信用リスク評価、 デリバティブ価格、 ポートフォリオ最適化など多くの場面で使われる。
疫学・公衆衛生: SEIR モデルの隠れ感染状態 (実感染者数 ≠ 報告感染者数) を観測 (PCR 陽性者数、 入院者数、 死亡者数) から推定する。 COVID-19 では各国の感染症研究所がこの手法で実効再生産数 Rt をリアルタイム推定し、 政策決定の根拠とした。 推定の不確実性を Bayes 事後分布として表現できる点が、 単純な統計推定との大きな違い。
水文・地下水: 河川流量予測、 地下水位推定、 地殻変動の歪み解析で EnKF が多用される。 国土地理院の電子基準点網 (GEONET) のデータを Kalman フィルタで時空間内挿し、 プレート運動・地殻変動を毎時推定する研究は世界トップレベルにある。
農業・林業: 衛星リモートセンシングデータと作物生育モデルを同化し、 圃場ごとの実際の生育状態を推定する研究が盛んである。 EnKF を使った LAI (葉面積指数) 推定、 収量予測、 干ばつ早期警戒システムなどが、 アフリカ・東南アジアの食糧安全保障プロジェクトで実装されている。
製造・プロセス制御: 化学プラント、 製鉄所、 半導体工場で温度・圧力・流量・組成の同時推定に Kalman フィルタが使われる。 「センサーで直接測れない内部状態」を Bayes 推定することで、 製品品質を一定に保ち、 異常を早期検知する。 これはまさに 1960 年代の Kalman フィルタの原点に近い使い方で、 今でも産業の屋台骨である。
SSDSE-B-2026 は 47 都道府県の単年データであり、 本来データ同化が対象とする「時間とともに変化する状態の推定問題」とは構造が異なる。 しかし、 「47 都道府県を擬似的な時刻ステップに見立てる」ことで、 Kalman フィルタの逐次更新挙動を可視化することが可能になる。 これはあくまで教育目的の演習であり、 実務応用ではないことを最初に明記しておく。
まず、 SSDSE-B-2026 から「人口 (千人)」列を取り出す。 北海道 (5,224) → 青森 (1,238) → 岩手 (1,210) → … → 沖縄 (1,485) と並べる。 これを「時刻 t=0 から t=46 までの観測値 y_t」と見立てる。 同時に、 真の状態 x_t は「滑らかな潜在変数」として、 ランダムウォークモデル \(x_{t+1} = x_t + w_t\) で時間発展すると仮定する。 観測モデルは \(y_t = x_t + v_t\)、 ノイズはいずれもガウス分布とする。
この設定で線形 Kalman フィルタを回すと、 推定値 \(\hat{x}_t\) は観測値の局所平均的な挙動を示す。 共分散 P は初期 1000 から定常値 (Q と R の比に依存) に収束する。 47 ステップという短い系列でも、 数ステップ目以降にはほぼ定常状態に達するのが観察できる。 これは「Kalman フィルタは過渡応答が早く、 数ステップで定常状態に達する」という重要な性質を実感する良い教材である。
次に、 過程ノイズ Q と観測ノイズ R の比を変えて挙動の違いを確認する。 Q/R が大きいときは「状態は速く変化するがモデルは観測を信じる」状況になり、 推定値が観測値に密接に追従する。 逆に Q/R が小さいときは「状態は緩やかに変化するがモデルは観測を疑う」状況になり、 推定値が観測値を平滑化したような滑らかな曲線になる。 これがまさにデータ同化における「観測信頼度 vs モデル信頼度」のトレードオフであり、 実務でも同じ判断を毎日行っている。
さらに進んで、 「東京都」のように極端な外れ値があるとき、 Kalman フィルタはどう振る舞うか観察する。 R が小さく観測を強く信じる設定では、 推定値が一時的に東京方向に大きく動くが、 その後の小さな観測 (神奈川、 千葉、 埼玉) で再び平均的な値に戻る。 これが「データ同化は局所的にロバストではないが、 長期的にはロバスト」と言われる現象の縮図である。 ロバスト推定を求めるなら、 Huber loss を組み込んだロバスト Kalman フィルタや、 粒子フィルタの重み付け関数を裾の重い分布に切り替えるなどの対処が必要になる。
最後に、 47 都道府県を地理的順序 (北海道 → 青森 → 岩手 → … → 沖縄) ではなく、 ランダムにシャッフルした順序で並べ直して同化を実行する。 同化結果はどう変わるか? 線形 Kalman フィルタの場合、 並べ替えに対して順序依存性がある (Q と R が同じなら定常状態の推定値は同じだが、 過渡応答が異なる)。 これも「同化の結果は観測の順序と頻度に強く依存する」という重要な性質を体感する良い演習である。
データ同化を厳密に理解するには、 確率論的状態空間モデルの枠組みで考えるのが最も整理される。 状態 \(x_t\) は隠れ変数、 観測 \(y_t\) はその確率的写像、 時間発展は遷移核 \(p(x_t \mid x_{t-1})\)、 観測モデルは尤度 \(p(y_t \mid x_t)\) で表される。 同化の目的は事後分布 \(p(x_t \mid y_{1:t})\) を計算することであり、 これは Bayes の連鎖法則で \(p(x_t \mid y_{1:t}) \propto p(y_t \mid x_t) \int p(x_t \mid x_{t-1}) p(x_{t-1} \mid y_{1:t-1}) dx_{t-1}\) と書ける。
この一般式から各手法は次のように派生する。 線形 Gauss 系の場合、 事後分布も Gauss 分布になり、 平均と共分散を解析的に追跡できる。 これが Kalman フィルタの導出根拠であり、 1960 年に Kalman が証明した「最小分散不偏推定」の性質はここから来る。 弱非線形系では Taylor 展開で線形化して KF を流用するのが EKF、 シグマ点でモーメントを推定するのが UKF、 アンサンブルでサンプル統計を取るのが EnKF、 重み付きサンプルで分布を表現するのが粒子フィルタである。 各手法は「事後分布の表現方法」が異なるだけで、 Bayes 推論の枠組みは同一である。
4D-Var はこの「逐次更新」の発想と対照的に、 「観測ウィンドウ \([t_0, t_N]\) 全体の同化を一度の最適化問題として解く」アプローチを取る。 コスト関数 \(J(x_0) = (x_0 - x^b)^T B^{-1} (x_0 - x^b)/2 + \sum_t (y_t - H(M_{0 \to t}(x_0)))^T R^{-1} (y_t - H(M_{0 \to t}(x_0)))/2\) を最小化する初期条件 \(x_0\) を求める。 ここで \(M\) は時間発展演算子、 \(B\) は背景誤差共分散、 \(R\) は観測誤差共分散。 アジョイント (随伴) コードはこのコスト関数の勾配 \(\nabla_{x_0} J\) を計算するために必要になる。 大規模系では準ニュートン法 (L-BFGS) で 10〜100 回の反復で収束させる。
アンサンブル系手法 (EnKF, PF) の最大の魅力は「アジョイント不要」「並列化容易」「モデル非侵襲 (モデルコードを修正しなくてよい)」の 3 点である。 これは現実の業務シミュレーションコード (数百万行の Fortran や C++) に同化を組み込むときの実装コストを劇的に下げる。 ただし、 アンサンブル数が状態次元より小さいときの偽相関、 spread underestimation、 ローカライズの調整、 inflation の調整など、 実運用上のチューニング項目は多い。
ハイブリッド手法 (En-4D-Var、 4DEnVar) は両者の良いとこ取りを狙う。 EnKF でアンサンブル共分散を推定し、 それを 4D-Var の B 行列に組み込む。 ECMWF、 Met Office、 気象庁、 NCEP の業務同化システムはすべてハイブリッドを採用しており、 純粋な 4D-Var や純粋な EnKF より一段精度が高い。 ただし実装は最も複雑で、 同化系統を 1 つ作るのに数年〜十年単位のエンジニアリングを要する。
最後に、 同化系の評価指標として最も重要なのが「予報スコアの改善」である。 同化品質をどれだけ改善しても、 最終的な予報精度 (RMSE、 アノマリー相関係数、 CRPS、 Brier スコアなど) が改善しなければ意味がない。 業務同化センターは毎月、 同化系統の改修案を「OSE (Observing System Experiment)」「OSSE (Observing System Simulation Experiment)」と呼ばれる検証実験で評価し、 統計的に有意な予報改善が確認されたものだけを業務系に投入する。 こうした厳格な品質管理が、 数値気象予報の予報精度を 30 年で「1 日あたり 1 日分」改善してきた原動力である。
データ同化の論文や業務マニュアルを読むときに頻出する専門用語を 20 個、 1 行で簡潔に整理する。 はじめて読む論文で意味が分からない用語があったら、 この辞典に立ち戻ると効率的。
次のステップ: 時系列分析 で Kalman フィルタの理論基盤を確認、 ベイズの定理 で逐次更新の数学的根拠を学び、 欠損メカニズム や ノイズ でデータの不確実性表現について理解を深めるとよい。 センサーデータ や アンサンブル法 の関連ページも合わせて参照されたい。
データ同化は単なる数値計算技法ではなく、 「不完全なモデルと不完全な観測から、 確率的に最良の現実像を構築する」という認識論的な営みである。 ここには「観測は完璧である」「モデルは正しい」といった素朴な実在論を超え、 「すべての知識は不確実性を伴う事後分布として表現される」というベイズ哲学が組み込まれている。 統計学・機械学習・物理学・制御工学の境界を溶かす学問であり、 21 世紀の科学の中核技術の一つに位置づけられる。
本ページを読み終えた後、 次の 5 項目を自分の言葉で説明できるようになることが学習目標である。 第一に、 データ同化が「動的モデル予測と観測値を Bayes 更新で逐次融合する技術」であることを 1 文で説明できる。 第二に、 Kalman フィルタの「予測ステップ」と「同化ステップ」の役割の違いを明確に区別できる。 第三に、 KF・EKF・UKF・EnKF・粒子フィルタ・4D-Var の 6 手法の使い分けを「線形性」「次元」「非 Gauss 性」の 3 軸で判断できる。 第四に、 観測誤差 R・モデル誤差 Q・カルマンゲイン K の意味と挙動への影響を説明できる。 第五に、 革新統計・spread 推移・filter collapse といった健全性診断指標を 1 つずつ挙げて意味を述べられる。 これらを満たせば、 業務同化センターや SLAM エンジニアと共通言語で議論できる段階に達している。
下のシミュレータでは、減衰振動する真の状態(黒線)を、不完全なモデル(「状態は前の時刻からほぼ変わらない」と仮定するローカルレベルモデル)とノイズ付き観測(オレンジ点)から、正確な 1 次元カルマンフィルタで逐次推定します。 スライダーで観測ノイズ σobs とモデル誤差 σmodel を動かすと、カルマンゲイン $K = P^f/(P^f + R)$ が変わり、「モデルと観測のどちらをどれだけ信じるか」の重みがリアルタイムに切り替わります。 グラフ上をドラッグ(タッチ対応)すると、各時刻の「予測 → 観測 → 解析」の内訳を数値で確認できます。
1 次元では解析値は $x^a = x^f + K(y - x^f) = (1-K)\,x^f + K\,y$、 つまり 予測と観測の重み付き平均そのものです。 重み $K = P^f/(P^f+R)$ は「予測の不確かさ」と「観測の不確かさ」の比だけで決まります。 実際に試してみましょう:
このデモの 1 次元カルマンフィルタは、本ページ上部の行列版(多次元)カルマンフィルタの最小例です。 状態が数千万次元になる気象の数値予報では、共分散行列 $P^f$ を保持できないため、多数の予報を並走させてサンプル共分散で代用するアンサンブルカルマンフィルタ(EnKF)や、時間窓内の観測すべてに合う初期値を最適化で求める 4D-Var が使われます。 いずれも本質は同じ「ベイズの定理による事前(モデル予測)× 尤度(観測)の更新」であり、正規分布の仮定の下では分散の逆数重み付き平均に帰着します。 非ガウスな系では粒子フィルタ(本文参照)が受け皿になります。 時系列・条件付き確率の各ページも合わせて読むと、状態空間モデルの全体像がつかめます。
データ同化は 状態空間モデル の解析手法、 ベイズ推定 の逐次版、 最適化問題 としても定式化される三つの顔を持ちます。 用語の地図全体 も参照してください。
| 視点 | 同化に対応する操作 |
|---|---|
| ベイズ推定 | 事前×尤度→事後 |
| 最適化 | $\min J(x)$ をニュートン法で解く |
| 機械学習 | オンライン学習(重み更新) |
| 信号処理 | ウィーナーフィルタの時間領域拡張 |
データ同化はベイズ推定の時系列拡張で、 気象・海洋への代表応用がある。
モデル予測 → 観測比較 → 共分散更新 (Kalman 等) → 状態推定 → 次ステップ予測の流れで、 観測誤差とモデル誤差のバランスが精度を決める。
| 関係 | 概念 | データ同化との接続 |
|---|---|---|
| 上位(一般化) | 統計推論一般 | データ同化は推論の構成要素 |
| 下位(特殊化) | 特定の検定・推定 | データ同化の応用 |
| 並列(兄弟) | 関連手法 | 同じ問題への別アプローチ |
| 前提 | 確率分布・標本 | データ同化の数学的基礎 |
| 応用 | 政策評価・施策効果測定 | SSDSE-B-2026 のような公的統計での実務 |
SSDSE-B-2026 で「人口」「出生数」「死亡数」を比較。 データ同化を使って自然増減のパターンを定量化。 東京・神奈川・愛知の都市集中、 秋田・高知の過疎化。
「学校数」「教員数」「進学率」を データ同化で分析。 県別の教育リソース配分の効率性を評価。 都市と地方の格差を可視化。
「病院数」「医師数」「平均寿命」 を組み合わせ。 データ同化で医療資源の不均衡と健康成果の関係を推定。 北海道の医師偏在問題。
「就業者数」「延べ宿泊者数」「1 人当たり所得」を データ同化で関連付け。 製造業県と観光業県のパターン差。
「高齢化率」「税収」「社会保障費」を データ同化で評価。 高齢化が進む県の財政負担の重さを定量化。 県政策への含意。
研究結果を データ同化を使って報告するときに守るべきチェックリスト:
データ同化は学術研究だけでなく、 政策・ビジネスの意思決定に直接活用されています。
計量経済学・教育測定・心理測定・疫学などで データ同化は基礎ツール。 近年は機械学習との融合で新しい応用が広がっています。
データ同化 の概念は、 統計学の発展史と並行して洗練されてきました。
日本では、 1947 年の統計法制定以降、 SSDSE-B のような公的統計の整備が進み、 データ同化を学ぶ実データ環境が充実してきました。
「データ同化」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。
このフローに沿って判断することで、 「データ同化」を中核とした適切な手法選択ができる。
本ページの各所(直感・落とし穴・関連手法)を、 一段抽象化した視点で束ね直す補足です。 データ同化の本質は「不確実性を持つ 2 つの情報源を、 それぞれの確からしさで重み付けて足し合わせる」という一点に集約されます。
カルマン更新は「加重平均」と説明されますが、 精度(precision, 分散の逆数)の言葉に翻訳すると更に明快です。 スカラー・観測演算子 $H=1$ の 1 次元では、 解析後の精度は次のように 単純な足し算 になります。
$$\frac{1}{P^{a}} = \frac{1}{P^{f}} + \frac{1}{R}$$
「モデル予測が持つ情報量 $1/P^f$」に「観測が持つ情報量 $1/R$」を足したものが、 同化後の情報量 $1/P^a$ になる、 という描像です。 情報(精度)はつねに増える=不確実性はつねに縮む($P^a \le P^f$ かつ $P^a \le R$)ため、 「観測を取り込んで損をすることはない($Q,R$ が正しく設定されている限り)」ことが一目で分かります。 このとき解析平均は精度で重み付けた平均
$$x^{a} = \frac{(1/P^{f})\,x^{f} + (1/R)\,y}{1/P^{f} + 1/R}$$
となり、 カルマンゲイン $K = P^f/(P^f+R)$ を使った $x^a = x^f + K(y-x^f)$ と厳密に一致します。 これは 2 つの正規分布(事前と尤度)を掛け算すると、 より鋭い正規分布になる——というベイズの定理のガウス版そのものです。 条件付き確率・分散・共分散の各ページを合わせて読むと、 多次元版($P^f, R$ が行列の場合)も「逆共分散の足し算」として同じ形に見えてきます。
落とし穴セクションで挙げた「$Q$ の過小評価」「非線形での線形化誤差」「観測の偏り」「モデルバイアス」に加え、 実装・運用でとくに事故が多い論点を補います。
本文で登場した多数の手法(KF/EKF/UKF/EnKF/粒子フィルタ/3D-Var/4D-Var/スムーザ)は、 次の 4 つの独立な軸の組み合わせとして整理できます。
| 軸 | 一方の端 | もう一方の端 |
|---|---|---|
| 推定の時間範囲 | フィルタ(現在まで $p(x_t\mid y_{1:t})$) | スムーザ(全期間 $p(x_t\mid y_{1:N})$、 RTS 等) |
| 更新の枠組み | 逐次(ベイズ更新を 1 ステップずつ) | 変分(時間窓を一括最適化、 3D/4D-Var) |
| 分布の仮定 | ガウス近似(KF/EKF/UKF/EnKF) | 非ガウス許容(粒子フィルタ・SMC) |
| 共分散の持ち方 | 明示行列(KF/EKF) | アンサンブル標本(EnKF/ETKF/LETKF) |
近年の業務系はこれらを混ぜたハイブリッド(EnVar / ハイブリッド 4D-EnVar)——アンサンブルで流れ依存の背景誤差共分散を推定しつつ、 変分の枠で観測を一括同化する——が主流です。 さらに深層学習との融合が進み、 モデル自体を学習する emulator(GraphCast・Pangu-Weather 等、 本文「📜 歴史と発展」参照)や、 同化アルゴリズムを微分可能に書き下す DA4ML/ML4DA が発展中です。 いずれも根っこは「ベイズ更新で予測と観測を統合する」という同一原理で、 時系列解析における状態空間モデルの自然な拡張として理解できます。 機械学習側からの接続は 機械学習・深層学習・ニューラルネットワーク の各ページが入口になります。
※「カルマンフィルタ」「粒子フィルタ」「状態空間モデル」「ベイズ推定」は用語集に個別ページが未整備のため、 本ページ本文(数式・Python 実装・🎮 シミュレータ)を該当解説として参照してください。