LSTMからハイブリッドへ:降雨流出解析プロトタイプ作成 Step 2 水文特徴量を追加する
はじめに
前回の Step 1 では、以下の3つを入力として、LSTM単独モデルで流出高を予測しました。
日雨量 precip_mm
日平均気温 temp_c
可能蒸発散量 pet_mm
今回は Step 2 として、LSTMへの入力特徴量に以下の項目を追加します。
実効雨量
先行降雨指数
累積雨量
前日流量
今回作成するプロトタイプ名は以下です。
RainfallRunoffLSTM_Prototype_r002
この段階でも、モデル本体はLSTM単独モデルのままです。
ただし、入力に水文学的な意味を持つ特徴量を追加することで、流域の先行湿潤状態や貯留状態をLSTMへ与えます。
今回の目的
今回の目的は以下です。
1. 実効雨量を作成する
2. 先行降雨指数 API を作成する
3. 累積雨量を作成する
4. 前日流量を特徴量に追加する
5. r001のLSTM単独モデルと同じ流れで学習・評価する
Step 2は、物理モデルとのハイブリッドへ進む前の準備段階です。
Step 1との違い
Step 1では、LSTMへの入力は以下でした。
features:
dynamic_inputs:
- precip_mm
- temp_c
- pet_mm
Step 2では、以下のように水文特徴量を追加します。
features:
dynamic_inputs:
- precip_mm
- temp_c
- pet_mm
- eff_rain_hl7_mm
- eff_rain_hl30_mm
- api_k85_mm
- api_k95_mm
- rain_sum_3d_mm
- rain_sum_7d_mm
- rain_sum_30d_mm
- q_prev_mm_day
- doy_sin
- doy_cos
追加する水文特徴量
| 特徴量 | 内容 |
|---|---|
eff_rain_hl7_mm |
半減期7日の実効雨量 |
eff_rain_hl30_mm |
半減期30日の実効雨量 |
api_k85_mm |
減衰係数0.85の先行降雨指数 |
api_k95_mm |
減衰係数0.95の先行降雨指数 |
rain_sum_3d_mm |
直近3日累積雨量 |
rain_sum_7d_mm |
直近7日累積雨量 |
rain_sum_30d_mm |
直近30日累積雨量 |
q_prev_mm_day |
前日流量 |
doy_sin, doy_cos
|
季節性を表す周期特徴量 |
実効雨量
実効雨量は、過去の雨量の影響が時間とともに減衰するという考え方です。
Re(t) = R(t) + α × Re(t-1)
ここで、減衰係数 α は半減期 T を使って以下のように求めます。
α = 0.5 ^ (Δt / T)
日単位データの場合、Δt = 1 day とします。
例えば、半減期7日の実効雨量では、7日経つと過去雨量の影響が半分になります。
先行降雨指数 API
API は Antecedent Precipitation Index の略で、日本語では先行降雨指数と呼ばれます。
これは、過去の雨が流域内にどれくらい残っているかを、降雨量だけから簡易的に表す指標です。
流域が乾いている状態と湿っている状態では、同じ雨量でも流出量が変わります。APIは、この「事前の湿り具合」を表す特徴量として使います。
基本式は以下です。
。
API(t) = R(t) + k × API(t-1)
ここで、k は減衰係数です。
今回のプロトタイプでは、以下の2種類を作成します。
api_k85_mm : k = 0.85
api_k95_mm : k = 0.95
k が大きいほど、過去の雨量の影響が長く残ります。
実効雨量との違い
今回は、APIと実効雨量を両方使っていますが、考え方はかなり近いです。
| 指標 | 考え方 |
|---|---|
| API | 過去降雨の影響を k で減衰させながら積み上げる |
| 実効雨量 | 半減期などで過去雨量の影響を減衰させながら積み上げる |
実装上は、どちらも「過去降雨の記憶」を表す特徴量です。
モデル構成
今回もモデル本体はLSTMです。
Step 1との違いは、LSTMに入力する特徴量が増えたことです。
フォルダー構成
RainfallRunoffLSTM_Prototype_r002/
├─ docker/
│ ├─ Dockerfile
│ └─ requirements.txt
├─ docker-compose.yml
├─ .env
├─ configs/
│ ├─ lstm_config.yaml
│ └─ lstm_config_quick.yaml
├─ data/
│ ├─ raw/
│ └─ processed/
├─ src/
│ ├─ generate_sample_data.py
│ ├─ preprocess.py
│ ├─ datasets.py
│ ├─ model_lstm.py
│ ├─ train_lstm.py
│ ├─ evaluate.py
│ ├─ predict.py
│ ├─ metrics.py
│ └─ utils.py
├─ notebooks/
├─ outputs/
├─ scripts/
└─ docs/
Step 2で主に変更したのは src/preprocess.py と configs/lstm_config.yaml です。
実行方法
Dockerコンテナ起動
ZIPファイルをダウンロードして、解凍してください。
docker compose up --build
JupyterLabは以下で開きます。
http://localhost:8888
簡易テスト
まずは簡易設定で動作確認します。
docker compose run --rm rainfall-runoff-lstm bash scripts/run_quick_test.sh
このスクリプトでは、以下を順番に実行します。
サンプルデータ作成
↓
水文特徴量を含む前処理
↓
LSTM学習
↓
評価
個別実行
サンプルデータ作成
docker compose run --rm rainfall-runoff-lstm python src/generate_sample_data.py
前処理
docker compose run --rm rainfall-runoff-lstm python src/preprocess.py --config configs/lstm_config.yaml
学習
docker compose run --rm rainfall-runoff-lstm python src/train_lstm.py --config configs/lstm_config.yaml
評価
docker compose run --rm rainfall-runoff-lstm python src/evaluate.py --config configs/lstm_config.yaml
出力ファイル
outputs/
├─ models/
│ ├─ lstm_best_r002.pth
│ └─ scaler_r002.json
├─ figures/
│ ├─ hydrograph_test.png
│ ├─ scatter_obs_pred.png
│ └─ loss_curve.png
├─ metrics/
│ ├─ lstm_training_history_r002.csv
│ └─ lstm_test_metrics_r002.csv
└─ predictions/
└─ lstm_test_predictions_r002.csv
評価指標
今回も以下の指標で評価します。
| 指標 | 内容 |
|---|---|
| NSE | 観測流量と予測流量の一致度 |
| KGE | 相関・ばらつき・バイアスを含む指標 |
| RMSE | 平均二乗誤差の平方根 |
| MAE | 平均絶対誤差 |
| Bias | 全体的な過大・過小評価 |
| Peak Error | ピーク流量の誤差 |
Step 1とStep 2を比較する場合は、同じテスト期間で評価します。
今回の位置づけ
今回の RainfallRunoffLSTM_Prototype_r002 は、LSTM単独モデルに水文特徴量を追加する段階です。
Step 1:
LSTM単独モデル
Step 2:
実効雨量・先行降雨指数を特徴量に追加
Step 3:
タンクモデルなどの概念モデルを追加
Step 4:
タンクモデル + LSTM補正のハイブリッドモデルへ拡張
今回は、LSTMに以下のような水文学的特徴量を与えました。
- 実効雨量
- 先行降雨指数
- 累積雨量
- 前日流量
- 季節性
注意点
水文特徴量を追加すると、必ず精度が良くなるとは限りません。
特に、以下に注意します。
- 特徴量を増やしすぎると過学習しやすくなる
- 前日流量を使う場合、実運用時にも前日流量が取得できる必要がある
- APIや実効雨量は似た情報を持つため、特徴量の重複に注意する
- 評価はNSEだけでなく、ピーク流量や水収支も確認する
まとめ
今回は、降雨流出解析プロトタイプの Step 2 として、LSTM単独モデルに水文特徴量を追加しました。
RainfallRunoffLSTM_Prototype_r002
Step 1では、雨量・気温・蒸発散量のみを入力しました。
Step 2では、そこに実効雨量、先行降雨指数、累積雨量、前日流量を追加しました。
次の段階では、タンクモデルなどの物理・概念モデルを追加し、LSTM単独モデルとの比較を行います。
参考リンク
-
前回記事:LSTM単独からハイブリッドへ:物理モデル×深層学習で考える降雨流出解析プロトタイプ
https://qiita.com/rino_yume/items/11238afbfc8c488488dc -
Rainfall–Runoff Modelling Using Long Short-Term Memory Networks
https://hess.copernicus.org/articles/22/6005/2018/ -
NeuralHydrology
https://neuralhydrology.readthedocs.io/ -
PyTorch LSTM
https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html
