LSTMからハイブリッドへ:物理モデル×深層学習で考える降雨流出解析プロトタイプ作成 Step 0
はじめに
降雨流出解析では、従来から以下のような物理モデル・概念モデルが使われてきました。
- タンクモデル
- 貯留関数法
- キネマティックウェーブ法
- 分布型流出モデル
- HEC-HMS などの水文モデル
- BTOP などの分布型水文モデル
一方で近年は、LSTM(Long Short-Term Memory)を用いたデータ駆動型の降雨流出解析も多く検討されています。
LSTMは時系列データの長期依存関係を扱えるため、雨量だけでなく、先行降雨、土壌貯留、地下水応答、積雪・融雪、季節性などをデータから学習できる可能性があります。
ただし、LSTM単独モデルには以下のような課題もあります。
LSTM単独モデルの課題
- 水収支を必ず満たすとは限らない
- 未経験規模の豪雨・洪水に弱い可能性がある
- なぜその予測になったか説明しにくい
- 観測データの品質に強く依存する
- 流域改変、ダム操作、土地利用変化などの条件変化に弱い可能性がある
そのため、現在の研究動向としては、LSTM単独モデルだけでなく、物理モデルと機械学習モデルを組み合わせたハイブリッドモデルも重要になっています。
この記事では、まずLSTM単独モデルをプロトタイプとして試し、その後、物理モデルとのハイブリッドへ拡張する流れを整理します。
なお、本記事は実務運用モデルではなく、第1段階のプロトタイプ設計として整理します。
この記事の目的
この記事の目的は、以下の流れで降雨流出解析プロトタイプを考えることです。
降雨流出解析プロトタイプの考え方
第1段階:
LSTM単独で降雨流出解析を試す
第2段階:
実効雨量・先行降雨指数などの水文特徴量を追加する
第3段階:
タンクモデルや貯留関数法などの物理・概念モデルを追加する
第4段階:
物理モデル + LSTM補正のハイブリッドモデルへ拡張する
第5段階:
将来的に微分可能水文モデル1や物理制約付きLSTMへ発展させる
最初から高度なAIモデルを作るのではなく、まずはシンプルなLSTMで動作確認し、その後、物理モデルと組み合わせる構成にします。
なぜLSTMを使うのか
降雨流出現象では、現在の流量は直近の雨量だけで決まるわけではありません。
例えば、以下のような影響があります。
- 数日前からの先行降雨
- 土壌の湿潤状態
- 地下水の遅れ応答
- 積雪・融雪
- 季節性
- 流域の貯留特性
- ダムや取水などの人為的影響
通常の回帰モデルでは、これらを明示的な説明変数として設計する必要があります。
一方、LSTMでは、過去の時系列データを入力することで、時間遅れを含む流域応答を学習できる可能性があります。
LSTM単独モデルの基本構成
最初に作るLSTM単独モデルは、以下のような構成にします。
入力:
過去N日分の雨量・気温・蒸発散量
モデル:
LSTM
出力:
当日または翌日の流量
最初の対象条件
第1段階では、いきなり複数流域や10分雨量を扱わず、日単位の単一流域モデルから始めます。
| 項目 | 第1段階の設定 |
|---|---|
| 対象流域 | 1流域 |
| 時間解像度 | 日単位 |
| 入力 | 日雨量、日平均気温、可能蒸発散量 |
| 出力 | 日流量 |
| モデル | LSTM |
| 評価指標 | NSE、KGE、RMSE、ピーク誤差 |
| 目的 | 過去データの再現性確認 |
いきなり10分雨量や1時間雨量を扱うと、データ整備、欠測処理、洪水イベント抽出、予測雨量の扱いが難しくなります。
そのため、最初は日単位モデルで基本動作を確認します。
入力データ形式
最初はCSV形式で十分です。
date,precip_mm,temp_c,pet_mm,q_m3s
2010-01-01,0.0,3.2,0.8,12.4
2010-01-02,5.0,4.1,0.7,13.1
2010-01-03,12.0,5.5,0.9,18.6
各列の意味は以下です。
| 列名 | 内容 |
|---|---|
| date | 日付 |
| precip_mm | 日雨量 mm/day |
| temp_c | 日平均気温 ℃ |
| pet_mm | 可能蒸発散量 mm/day |
| q_m3s | 観測流量 m3/s |
可能蒸発散量が用意できない場合は、最初は省略してもよいです。
流量の正規化(単位変換)
流量 m3/s をそのまま学習してもよいですが、流域面積がわかる場合は、流出高 mm/day に変換すると扱いやすくなります。
Q_mm_day = Q_m3s × 86.4 / Area_km2
ここで、
-
Q_m3s:流量 m3/s -
Area_km2:流域面積 km2 -
Q_mm_day:流出高 mm/day
です。
複数流域へ拡張する場合は、流域面積の違いをそろえるために、この変換が重要になります。
LSTMの入力形式
LSTMには、過去N日分の気象データをまとめて入力します。
例えば、過去180日分を使って当日の流量を予測する場合は、以下のようになります。
入力X:
[
[180日前の雨量, 180日前の気温, 180日前のPET],
[179日前の雨量, 179日前の気温, 179日前のPET],
...
[1日前の雨量, 1日前の気温, 1日前のPET]
]
出力y:
当日の流量
PyTorchで扱う場合のテンソル形状は以下です。
X: [batch_size, seq_length, num_features]
y: [batch_size, 1]
例えば、
batch_size = 64
seq_length = 180
num_features = 3
の場合、入力は以下になります。
X: [64, 180, 3]
LSTMモデルのサンプル
第1段階では、シンプルなLSTMで十分です。
import torch
import torch.nn as nn
class RainfallRunoffLSTM(nn.Module):
"""
降雨流出解析用のシンプルなLSTMモデル。
入力:
x: [batch_size, seq_length, num_features]
出力:
q_pred: [batch_size, 1]
注意:
このモデルはLSTM単独モデルです。
水収支や非負制約などの物理制約はまだ考慮していません。
"""
def __init__(self, input_size: int, hidden_size: int = 64, num_layers: int = 1):
super().__init__()
self.lstm = nn.LSTM(
input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
)
self.fc = nn.Linear(hidden_size, 1)
def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
順伝播処理。
Parameters
----------
x : torch.Tensor
入力時系列データ。
形状は [batch_size, seq_length, num_features]。
Returns
-------
torch.Tensor
予測流量。
形状は [batch_size, 1]。
"""
# out: [batch_size, seq_length, hidden_size]
out, _ = self.lstm(x)
# 最後の時刻の隠れ状態を使用する
last_hidden = out[:, -1, :]
# 全結合層で流量に変換する
q_pred = self.fc(last_hidden)
return q_pred
推奨パラメータ
第1段階のプロトタイプでは、以下の設定から始めます。
seq_length: 180
hidden_size: 64
num_layers: 1
dropout: 0.0
batch_size: 64
epochs: 50
learning_rate: 0.001
loss: mse
target: q_mm_day
各パラメータの意味
上記の設定ファイルで指定している各パラメータの意味は以下です。
| パラメータ | 設定例 | 意味 |
|---|---|---|
seq_length |
180 |
LSTMに入力する過去データの長さです。ここでは過去180日分の雨量・気温・蒸発散量などを使って、流量を予測します。 |
hidden_size |
64 |
LSTM内部の隠れ状態の次元数です。大きくすると表現力は上がりますが、過学習しやすくなり、計算負荷も増えます。 |
num_layers |
1 |
LSTM層を何段重ねるかを指定します。第1段階のプロトタイプでは、まず1層で十分です。 |
dropout |
0.0 |
過学習を防ぐために、一部のニューロンをランダムに無効化する割合です。1層LSTMでは効果が限定的なため、最初は0.0でもよいです。 |
batch_size |
64 |
1回の学習更新で使うサンプル数です。大きくすると学習は安定しやすくなりますが、メモリ使用量が増えます。 |
epochs |
50 |
学習データ全体を何回繰り返して学習するかを指定します。まずは50回程度で学習曲線を確認します。 |
learning_rate |
0.001 |
モデルの重みを更新する際の学習率です。大きすぎると学習が不安定になり、小さすぎると学習が進みにくくなります。 |
loss |
mse |
学習時に最小化する損失関数です。mse は平均二乗誤差で、予測流量と観測流量の差を二乗して評価します。 |
target |
q_mm_day |
予測対象となる目的変数です。ここでは流量を流域面積で割って換算した流出高 mm/day を予測します。 |
seq_length
seq_length は、LSTMに入力する過去時系列の長さです。
seq_length: 180
この場合、過去180日分のデータを使って、当日または翌日の流量を予測します。
過去180日分の雨量・気温・蒸発散量
↓
LSTM
↓
予測流量
降雨流出解析では、現在の流量は当日の雨量だけでなく、数日前から数か月前までの先行降雨や流域の貯留状態の影響を受けます。
そのため、ある程度長い時系列を入力することが重要です。
ただし、seq_length を長くしすぎると、計算量が増え、学習も難しくなります。
第1段階では、以下のように考えるとよいです。
| 目的 | 目安 |
|---|---|
| 短期洪水応答を見たい | 7〜30日 |
| 日流量の再現をしたい | 90〜180日 |
| 季節性や長期貯留も考慮したい | 180〜365日 |
今回のプロトタイプでは、日単位の降雨流出解析を想定しているため、まずは 180 日から始めます。
hidden_size
hidden_size は、LSTM内部で情報を保持する隠れ状態の大きさです。
hidden_size: 64
値を大きくすると、複雑な流域応答を表現しやすくなります。
一方で、大きくしすぎると、学習データに過剰に適合してしまう可能性があります。
| hidden_size | 特徴 |
|---|---|
| 32 | 軽量。まず動作確認したい場合に使いやすい |
| 64 | 第1段階の標準的な設定 |
| 128 | 表現力は上がるが、過学習に注意 |
| 256以上 | データ量が十分にある場合に検討 |
最初は 64 として、学習結果を見ながら 32 や 128 と比較するとよいです。
num_layers
num_layers は、LSTM層を何段重ねるかを指定します。
num_layers: 1
1層の場合は、シンプルなLSTMです。
2層以上にすると、より複雑な時系列パターンを学習できる可能性がありますが、過学習や学習不安定化のリスクも増えます。
第1段階のプロトタイプでは、まず 1 層で十分です。
| num_layers | 特徴 |
|---|---|
| 1 | シンプルで扱いやすい。最初におすすめ |
| 2 | 表現力は上がるが、過学習に注意 |
| 3以上 | データ量が十分にある場合のみ検討 |
dropout
dropout は、過学習を防ぐための設定です。
dropout: 0.0
学習時に一部のニューロンをランダムに無効化することで、モデルが特定のパターンに依存しすぎることを防ぎます。
ただし、PyTorchの nn.LSTM では、num_layers=1 の場合、LSTM層間のdropoutは実質的に効きません。
そのため、今回のように num_layers=1 で始める場合は、まず dropout: 0.0 で問題ありません。
2層以上にする場合は、以下のような値を試します。
dropout: 0.2
または、
dropout: 0.3
batch_size
batch_size は、1回の学習更新で使うデータ数です。
batch_size: 64
例えば batch_size: 64 の場合、64個の時系列サンプルをまとめてモデルに入力し、損失を計算して重みを更新します。
| batch_size | 特徴 |
|---|---|
| 16 | メモリ使用量が少ないが、学習がやや不安定になる場合がある |
| 32 | 小規模データで使いやすい |
| 64 | 標準的で扱いやすい |
| 128 | 学習は安定しやすいが、メモリ使用量が増える |
最初は 64 として、PCのメモリやGPUメモリに応じて調整します。
epochs
epochs は、学習データ全体を何回繰り返して学習するかを指定します。
epochs: 50
epochs: 50 の場合、学習データ全体を50回繰り返してモデルを更新します。
少なすぎると学習不足になり、多すぎると過学習する可能性があります。
そのため、単にepoch数を増やすのではなく、以下のような学習曲線を確認することが重要です。
train_loss:学習データの損失
valid_loss:検証データの損失
例えば、
train_loss は下がっている
valid_loss は途中から上がっている
という場合は、過学習している可能性があります。
第1段階では 50 程度から始め、必要に応じて 100 程度まで増やします。
learning_rate
learning_rate は、モデルの重みを更新する幅を決める値です。
learning_rate: 0.001
値が大きすぎると、損失が発散したり、学習が不安定になります。
値が小さすぎると、学習がなかなか進みません。
| learning_rate | 特徴 |
|---|---|
| 0.01 | 大きめ。発散する場合がある |
| 0.001 | 標準的な初期値 |
| 0.0005 | 安定重視 |
| 0.0001 | 学習は遅いが安定しやすい |
第1段階では、Adamなどの最適化手法を使う前提で、まず 0.001 から始めるのが扱いやすいです。
loss
loss は、学習時に最小化する損失関数です。
loss: mse
mse は Mean Squared Error、つまり平均二乗誤差です。
MSE = mean((Q_obs - Q_pred)^2)
ここで、
-
Q_obs:観測流量 -
Q_pred:予測流量
です。
MSEは大きな誤差を強く罰するため、洪水ピークのような大きな流量差に敏感です。
ただし、MSEだけで評価すると、低水時の再現性や水収支の良し悪しがわかりにくい場合があります。
そのため、学習にはMSEを使い、評価では以下も併用します。
- NSE
- KGE
- RMSE
- MAE
- ピーク流量誤差
- 水収支バイアス
target
target は、モデルが予測する目的変数です。
target: q_mm_day
ここでは、観測流量 m3/s ではなく、流域面積で換算した流出高 mm/day を予測対象にします。
Q_mm_day = Q_m3s × 86.4 / Area_km2
q_mm_day を使う理由は、雨量 mm/day と同じ単位系で比較しやすくなるためです。
また、将来的に複数流域へ拡張する場合も、流域面積の違いをある程度そろえることができます。
単一流域だけで試す場合は q_m3s をそのまま使ってもよいですが、プロトタイプ段階から q_mm_day にしておくと、後で拡張しやすくなります。
最初は小さく始める
これらのパラメータは、最初から最適値を決める必要はありません。
第1段階では、以下の考え方で十分です。
まず動くことを確認する
↓
学習曲線を確認する
↓
ハイドログラフを確認する
↓
NSE / KGE / RMSE を確認する
↓
seq_length や hidden_size を少しずつ調整する
最初から複雑なモデルにすると、精度が悪かったときに、データが悪いのか、モデルが悪いのか、パラメータが悪いのか判断しにくくなります。
そのため、まずは以下の設定から始めます。
seq_length: 180
hidden_size: 64
num_layers: 1
dropout: 0.0
batch_size: 64
epochs: 50
learning_rate: 0.001
loss: mse
target: q_mm_day
この設定で、学習が正常に進むか、観測流量と予測流量の波形がある程度合うかを確認します。
まずは小さなモデルで動作確認します。
精度向上は、次の段階で行います。
学習期間の分け方
降雨流出解析では、ランダム分割ではなく、時系列で学習・検証・テストを分けます。
例:
2010-01-01 ~ 2017-12-31:学習
2018-01-01 ~ 2020-12-31:検証
2021-01-01 ~ 2023-12-31:テスト
ランダム分割にすると、未来の情報が学習側に混ざる可能性があります。
そのため、必ず時系列順に分割します。
評価指標
降雨流出解析では、単純なMSEだけでは評価が不十分です。
最低限、以下の指標を確認します。
| 指標 | 内容 |
|---|---|
| NSE | 観測流量と予測流量の一致度を評価する指標。1に近いほど再現性が高く、0未満の場合は観測平均を使う単純な予測より悪いことを示す。 |
| KGE | 相関、ばらつき、バイアスを含む指標 |
| RMSE | 平均二乗誤差の平方根 |
| MAE | 平均絶対誤差 |
| Peak Error | 洪水ピーク流量の誤差 |
| Peak Timing Error | ピーク時刻のずれ |
| Bias | 全体的に過大・過小予測していないか |
NSEは以下で計算できます。
import numpy as np
def nse(obs: np.ndarray, sim: np.ndarray) -> float:
"""
Nash-Sutcliffe Efficiencyを計算する。
Parameters
----------
obs : np.ndarray
観測値。
sim : np.ndarray
計算値または予測値。
Returns
-------
float
NSE値。
1に近いほど再現性が高い。
"""
obs = np.asarray(obs, dtype=float)
sim = np.asarray(sim, dtype=float)
denominator = np.sum((obs - np.mean(obs)) ** 2)
if denominator == 0:
return np.nan
return 1.0 - np.sum((obs - sim) ** 2) / denominator
ベースラインモデルも用意する
LSTMだけを作ると、結果が良いのか悪いのか判断しにくくなります。
そのため、以下のようなベースラインも用意します。
| モデル | 内容 |
|---|---|
| 前日流量モデル | Q(t-1)をそのままQ(t)とする |
| 実効雨量回帰 | 実効雨量から流量を回帰する |
| MLP | 固定長の特徴量から流量を予測する |
| LSTM | 過去時系列を入力して流量を予測する |
LSTMが前日流量モデルに負ける場合は、データ前処理、学習期間、入力特徴量、モデル構成を見直す必要があります。
現在の動向:LSTM単独からハイブリッドモデルへ
ここからが本記事の重要なポイントです。
近年の降雨流出解析では、LSTMなどの深層学習モデルを単独で使うだけでなく、物理モデルや概念モデルと組み合わせるハイブリッドモデルが注目されています。
理由は、LSTM単独モデルには高い予測精度が期待できる一方で、以下の課題があるためです。
- 水収支を必ず満たすとは限らない
- 未経験規模の豪雨に対する外挿性が弱い可能性がある
- 学習データにない流域条件の変化に弱い可能性がある
- 結果の説明性が低い
- 長期水収支や低水流量の再現が不安定になる場合がある
そのため、現在は次のような方向が検討されています。
| 分類 | 内容 |
|---|---|
| 後処理型ハイブリッド | 物理モデルの計算結果を機械学習で補正する |
| 直列型ハイブリッド | 物理モデルの状態量や流量をLSTMの入力に使う |
| 並列型ハイブリッド | 物理モデルとLSTMの予測を統合する |
| 物理制約付きLSTM | 水収支、非負制約、質量保存などを考慮する |
| 微分可能水文モデル | タンクモデルやHBVのようなモデルをPyTorch上で微分可能に実装する |
| Mass-Conserving LSTM | LSTM内部で保存則を考慮する |
ハイブリッドモデルの考え方
ハイブリッドモデルでは、物理モデルと機械学習モデルの長所を組み合わせます。
| モデル | 長所 | 弱点 |
|---|---|---|
| 物理モデル | 水収支や流域過程を説明しやすい | パラメータ同定が難しい |
| LSTM | 複雑な非線形応答を学習しやすい | 物理的整合性が弱い |
| ハイブリッド | 説明性と予測精度の両立を狙える | モデル構成が複雑になる |
プロトタイプでは、まず以下のような単純な構成から始めるのがよいと考えます。
Q_final = Q_phys + ΔQ_ml
ここで、
-
Q_phys:物理モデル・概念モデルによる流量 -
ΔQ_ml:機械学習モデルによる補正量 -
Q_final:ハイブリッドモデルの最終予測流量
です。
流量が負にならないようにする場合は、次のようにします。
Q_final = max(0, Q_phys + ΔQ_ml)
おすすめの第1段階ハイブリッドモデル
最初に作るハイブリッドモデルとしては、タンクモデル + LSTM残差補正が分かりやすいです。
この構成では、タンクモデルで大まかな流出応答を計算し、LSTMで残差を補正します。
観測流量 Q_obs
物理モデル流量 Q_phys
残差:
residual = Q_obs - Q_phys
LSTMの学習対象:
residual
最終的な予測値は以下です。
Q_hybrid = Q_phys + residual_pred
この構成の利点は、物理モデルの説明性を残しつつ、LSTMで物理モデルが表現しきれない非線形誤差や遅れ応答を補正できる点です。
実装ロードマップ
プロトタイプは、今後段階的に作成します。
実装ロードマップ
-
RainfallRunoffLSTM_Prototype_r001
LSTM単独モデル -
RainfallRunoffLSTM_Prototype_r002
実効雨量・先行降雨指数を特徴量に追加 -
RainfallRunoffHybrid_Prototype_r001
タンクモデル + LSTM残差補正 -
RainfallRunoffHybrid_Prototype_r002
物理モデル出力 + XGBoost / LSTM 後処理 -
RainfallRunoffDifferentiableTank_r001
PyTorchで微分可能な降雨流出タンクモデル
いきなり最新研究のモデルを実装するのではなく、まずは小さく始めていきます。
フォルダー構成案
プロトタイプのフォルダー構成は現状では以下のようにします。
docker環境で動かします。後で修正追加はします。
RainfallRunoffHybrid_Docker_r001/
├─ docker/
│ ├─ Dockerfile
│ └─ requirements.txt
│
├─ docker-compose.yml
├─ .env
├─ README.md
│
├─ configs/
│ ├─ lstm_config.yaml
│ └─ hybrid_config.yaml
│
├─ data/
│ ├─ raw/
│ │ └─ rainfall_runoff_sample.csv
│ ├─ processed/
│ │ └─ rainfall_runoff_daily.csv
│ └─ sample/
│
├─ src/
│ ├─ __init__.py
│ ├─ datasets.py
│ ├─ preprocess.py
│ ├─ model_lstm.py
│ ├─ model_tank.py
│ ├─ model_hybrid.py
│ ├─ train_lstm.py
│ ├─ train_hybrid.py
│ ├─ evaluate.py
│ ├─ predict.py
│ ├─ metrics.py
│ └─ utils.py
│
├─ notebooks/
│ ├─ 01_check_data.ipynb
│ ├─ 02_train_lstm.ipynb
│ └─ 03_compare_models.ipynb
│
├─ outputs/
│ ├─ models/
│ │ ├─ lstm_best.pth
│ │ └─ hybrid_best.pth
│ ├─ figures/
│ │ ├─ hydrograph_test.png
│ │ ├─ scatter_obs_pred.png
│ │ └─ loss_curve.png
│ ├─ metrics/
│ │ └─ test_metrics.csv
│ └─ db/
│ └─ rainfall_runoff.duckdb
│
└─ scripts/
├─ run_preprocess.sh
├─ run_train_lstm.sh
├─ run_train_hybrid.sh
└─ run_evaluate.sh
| フォルダー | 役割 |
|---|---|
docker/ |
Dockerfile と Python ライブラリ定義を置く |
configs/ |
LSTM単独モデル、ハイブリッドモデルの設定ファイル |
data/raw/ |
元データを保存 |
data/processed/ |
前処理後の学習用データを保存 |
src/ |
学習・評価・モデル本体のPythonコード |
notebooks/ |
データ確認、学習結果確認用のJupyter Notebook |
outputs/models/ |
学習済みモデル |
outputs/figures/ |
ハイドログラフ、散布図、損失曲線 |
outputs/metrics/ |
NSE、KGE、RMSEなどの評価結果 |
outputs/db/ |
DuckDBを使う場合の保存先 |
scripts/ |
コンテナ内で実行する補助スクリプト |
docker-compose.yml の構成例
まずは、Jupyter + 学習実行用コンテナ1つで十分です。
services:
rainfall-runoff:
build:
context: .
dockerfile: docker/Dockerfile
container_name: rainfall_runoff_lstm
working_dir: /workspace
volumes:
- .:/workspace
- ./data:/workspace/data
- ./outputs:/workspace/outputs
- ./notebooks:/workspace/notebooks
ports:
- "8888:8888"
env_file:
- .env
command: >
jupyter lab
--ip=0.0.0.0
--port=8888
--no-browser
--allow-root
--NotebookApp.token=${JUPYTER_TOKEN}
設定ファイル例
project_name: RainfallRunoffHybrid_Docker_r001
data:
input_csv: data/processed/rainfall_runoff_daily.csv
date_column: date
target_column: q_mm_day
area_km2: 350.0
features:
dynamic_inputs:
- precip_mm
- temp_c
- pet_mm
- eff_rain_mm
- api_mm
- q_phys_mm_day
model:
type: hybrid_lstm
seq_length: 180
hidden_size: 64
num_layers: 1
dropout: 0.0
training:
batch_size: 64
epochs: 50
learning_rate: 0.001
loss: mse
split:
train_start: 2010-01-01
train_end: 2017-12-31
valid_start: 2018-01-01
valid_end: 2020-12-31
test_start: 2021-01-01
test_end: 2023-12-31
outputs:
model_dir: outputs/models
figure_dir: outputs/figures
metrics_dir: outputs/metrics
評価で確認すること
ハイブリッドモデルでは、LSTM単独より評価項目を増やします。
| 評価項目 | 確認内容 |
|---|---|
| NSE | 全体的な再現性 |
| KGE | 相関・ばらつき・バイアス |
| RMSE | 絶対誤差 |
| Peak Error | 洪水ピーク流量の誤差 |
| Peak Timing Error | ピーク発生時刻のずれ |
| Low Flow Error | 低水時の再現性 |
| Bias | 長期的な過大・過小評価 |
| Water Balance Error | 水収支のずれ |
| Event Evaluation | 洪水イベントごとの評価 |
特に、ハイブリッドモデルでは以下が重要です。
精度が上がったか?
だけではなく、
物理的におかしな予測をしていないか?
水収支が悪化していないか?
未経験洪水で極端に外していないか?
を確認します。
今回のプロトタイプの位置づけ
今回のプロトタイプは、実務運用モデルではありません。
あくまでも、以下を確認するためのモデルです。
プロトタイプ:第1段階
- LSTMで降雨流出解析ができるか
- 物理モデルとLSTMの違いを比較できるか
- 物理モデルの誤差をLSTMで補正できるか
- ハイブリッド化によりピーク流量や波形再現性が改善するか
- 水収支や外挿性の問題がどの程度残るか
また、結果を防災や避難判断に直接使うには、以下の検証が必要です。
- 多数の洪水イベントでの検証
- 未経験規模の豪雨での検証
- 流域変更やダム操作の影響確認
- 観測データ欠測時の安定性確認
- 予測雨量を使った場合の不確実性評価
- 物理的に不自然な予測のチェック
まとめ
LSTMは、降雨流出解析において強力な時系列モデルです。
ただし、LSTM単独では、水収支、説明性、未経験洪水への外挿性に課題が残る可能性があります。
そのため、今後の方向としては、LSTM単独モデルだけでなく、物理モデルや概念モデルと組み合わせたハイブリッドモデルが重要になります。
本記事では、次の順番で進める方針を整理しました。
方 針
- LSTM単独モデルを作る
- 実効雨量・先行降雨指数を特徴量に追加する
- タンクモデルなどの概念モデルを作る
- タンクモデル + LSTM残差補正を作る
- 将来的に微分可能水文モデルへ拡張する
参考リンク
LSTM降雨流出解析
-
Reproducing “Rainfall–runoff modelling using Long Short-Term Memory (LSTM) networks”
https://medium.com/@pietertolsma/reproducing-rainfall-runoff-modelling-using-long-short-term-memory-lstm-networks-991e883471ca -
Rainfall–Runoff Modelling Using Long Short-Term Memory (LSTM) Networks
https://hess.copernicus.org/articles/22/6005/2018/
LSTMと物理モデル比較
- Long Short-Term Memory (LSTM) Based Runoff Simulation and Short-Term Forecasting for Alpine Regions
https://www.mdpi.com/2073-4441/17/21/3117
物理制約付き・ハイブリッド系
-
MC-LSTM: Mass-Conserving LSTM
https://arxiv.org/abs/2101.05186 -
NeuralHydrology MC-LSTM
https://neuralhydrology.readthedocs.io/en/latest/api/neuralhydrology.modelzoo.mclstm.html -
Physics-Informed, Differentiable Hydrologic Models for Capturing Unseen Extreme Events
https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2025WR040414 -
Differentiable, learnable, regionalized process-based models with physical outputs can approach state-of-the-art hydrologic prediction accuracy
https://arxiv.org/abs/2203.14827
-
微分可能水文モデルとは、タンクモデルやHBVのような物理・概念モデルを、PyTorchなどの自動微分フレームワーク上で実装し、観測流量との誤差を使ってモデルパラメータを学習できるようにしたモデルです。
LSTM単独モデルでは、雨量と流量の関係をブラックボックス的に学習します。一方、微分可能水文モデルでは、貯留、浸透、蒸発散、地下水流出などの水文過程の構造を残しつつ、流出係数や貯留係数などを機械学習で最適化します。そのため、LSTM単独モデルよりも水文学的な解釈性を残しやすく、物理モデルよりもデータに適応しやすいという特徴があります。
第1段階のプロトタイプでは、いきなり微分可能HBVのような高度なモデルを作るのではなく、まずはLSTM単独モデル、次にタンクモデル + LSTM残差補正、その後に微分可能タンクモデルへ進めるのが現実的です。 ↩



