Zindi「A Step Ahead of Drought」に挑戦する:GRACE/TWSで地球規模の水貯留量を1か月先予測する
1. はじめに
Zindiで公開されている A Step Ahead of Drought: Forecasting Global Water Storage Challenge by ITU は、地球規模の水循環・干ばつ監視をテーマにした機械学習コンペです。
このコンペの目的は、NASAのGRACE/GRACE-FOなどで推定される TWS(Total Water Storage:陸域水貯留量、総水貯留量) を、1か月先まで予測することです。
TWSは、地下水、土壌水分、表流水、雪氷などを含む「陸域に蓄えられた水の総量」に相当します。干ばつは洪水のように急激に発生する災害ではなく、ゆっくり進行する災害であるため、早期把握と短期予測が重要になります。
このコンペの面白い点は、単なる表形式データの回帰ではなく、全球スケールの空間情報、月単位の時系列情報、水文・気候指標 を組み合わせて、次月の水貯留量を予測するところです。
2. コンペ概要
| 項目 | 内容 |
|---|---|
| コンペ名 | A Step Ahead of Drought: Forecasting Global Water Storage Challenge by ITU |
| 主催 | ITU / AI for Good 関連チャレンジ |
| プラットフォーム | Zindi |
| タスク | 全球スケールでTWSの1か月先値を予測する回帰問題 |
| 入力 | NetCDF形式の特徴量、CSV形式のラベル |
| 主な特徴量 |
TWS_t, SPEI_01〜SPEI_12, SOIL_MOISTURE_t, SOIL_MOISTURE_tp1
|
| 主キー | 緯度、経度、日付 |
| 出力 |
ID, Target
|
| 評価指標 | RMSE(Root Mean Squared Error) |
| 学習データ | 2,154,021行 |
| テストデータ | 280,961行 |
| 期間 | 2026-07-07 開始、2026-09-13 終了予定 |
| 提出上限 | 1日10回、全体300回 |
| チーム | 最大4人 |
| 賞金 | TBD、Zindi points 5,000 |
3. 評価指標
このコンペでは、リーダーボード評価として RMSE(Root Mean Squared Error) が使われます。
RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2}
RMSEは、大きな誤差に強いペナルティを与える指標です。そのため、平均的にそこそこ当てるだけでなく、極端な乾燥・湿潤イベントで大きく外しすぎないモデルが重要になります。
提出ファイルは以下のような形式です。
ID Target
201509_-55.4_-68.5 0.082
201509_-55.4_-67.5 0.182
201509_-54.5_-71.5 0.558
最終評価ではリーダーボードスコアだけでなく、上位者を対象に AI Trustworthiness、Innovation and Practicality も評価されます。したがって、単にスコアを上げるだけではなく、説明可能性、再現性、バイアス確認、実用性も重要です。
4. このコンペの難しさ
4.1 TWSは複合的な水文量
TWSは、地下水、土壌水分、表流水、雪氷などをまとめた総量です。つまり、単一の観測量ではなく、複数の水文プロセスが重なった指標です。
そのため、単純に前月値だけを見るのではなく、以下のような要素を同時に考える必要があります。
- 季節性
- 地域差
- 気候帯の違い
- 干ばつ指標
- 土壌水分の変化
- 長期的な乾燥・湿潤傾向
4.2 GRACE由来TWSには公開遅れがある
GRACE由来のTWSは、地表面や地下に蓄えられた水の変化を広域的に捉えられる強力な情報です。一方で、データ公開には遅れがあるため、最新の水文状態をリアルタイムに把握しにくいという課題があります。
このコンペでは、最新のGRACE観測に対して、その次の時点 t+1 のTWSを予測します。これがうまくできれば、干ばつモニタリングの即時性を高められる可能性があります。
4.3 空間と時間の両方に強いモデルが必要
全球スケールのデータでは、地域によって気候・地形・水文特性が大きく異なります。
たとえば、乾燥地域、湿潤地域、高緯度地域、雪氷の影響を受ける地域では、TWSの変動パターンが異なります。ランダム分割だけで検証すると、空間的・時間的に近いデータが学習と検証に混ざり、実力以上に良いスコアが出る可能性があります。
そのため、時系列分割や空間分割を意識した検証が重要です。
5. まず試したいベースライン方針
5.1 EDA
最初に以下を確認します。
- train / test の行数
-
Targetの分布 - 欠損値
- 緯度・経度・日付の範囲
- train と test の時期差
- 地域ごとのデータ数
- TWSとSPEI、土壌水分の相関
- 地域別・月別のTWS分布
特に、月別・緯度帯別のTWS分布を見ると、季節性と地域差をつかみやすくなります。
5.2 モデル候補
まずは表形式データとして扱い、以下のモデルから始めるのがよいです。
- Persistence Model
- Linear Regression / Ridge / ElasticNet
- Random Forest
- LightGBM
- XGBoost
- CatBoost
最初に重要なのは、いきなり複雑なモデルを作ることではなく、Persistence Modelを超える堅実なベースライン を作ることです。
水文時系列では、前月値が非常に強いベースラインになることがあります。
TWS_{t+1} = TWS_t
この単純なモデルよりも、どれだけRMSEを改善できるかを基準にします。
5.3 特徴量エンジニアリング
このコンペでは、GIS・時系列・水文の特徴量が効きそうです。
有効そうな特徴量は以下です。
| カテゴリ | 例 |
|---|---|
| 時間特徴量 | 年、月、季節、sin(month), cos(month)
|
| 空間特徴量 | 緯度、経度、緯度帯、地域クラスタ |
| 水文特徴量 |
TWS_t, SOIL_MOISTURE_t, SOIL_MOISTURE_tp1
|
| 干ばつ指標 |
SPEI_01〜SPEI_12
|
| 異常値特徴量 | 月別平均からの偏差、地域平均からの偏差 |
| 相互作用 | SPEI × 緯度帯、土壌水分 × 季節 |
6. 検証設計
このコンペで一番大事なのは、ローカル検証の作り方です。
現状で考えられるのは以下の項目になると考えています。
1. まず通常のKFoldでベースラインを作る
2. Time splitで将来予測性能を確認する
3. Spatial splitで未知地域への汎化性能を確認する
4. 緯度帯別・月別に誤差を確認する
5. Public Leaderboardに過剰適合しないように提出回数を管理する
検証方法の考え方です。
| 検証方法 | 目的 |
|---|---|
| Random KFold | まず全体のベースラインを作る |
| Time split | 将来時点への予測性能を見る |
| Spatial split | 未知地域への汎化を見る |
| Latitudinal split | 気候帯の違いに強いか見る |
| Public LBとの比較 | ローカル検証とLBのズレを確認する |
特にPrivate Leaderboardはテストデータの一部または大部分で評価されるため、Public Leaderboardだけに合わせると最終順位が落ちる可能性があります。
7. 信頼性と再現性への注意
このコンペでは、最終評価でAI TrustworthinessやInnovation and Practicalityも考慮されます。
実務で使える干ばつ予測モデルを作るという観点では、以下を徹底した方がよいと考えています。
- データ前処理の手順を明確にする
- 欠損値処理を記録する
- 特徴量の意味を説明できるようにする
- 検証方法を固定する
- 乱数seedを固定する
- 使用ライブラリのバージョンを残す
- 地域別・季節別の誤差分析を行う
- 学習から提出ファイル作成までを一発で再現できるようにする
AI Trustworthiness(信頼できるAI) とは、精度だけでなく、説明可能性、公平性、安全性、再現性、プライバシー、運用監視まで含めて、安心して使える状態を指します。
8. 実装ディレクトリ案
zindi-drought-tws/
├── data/
│ ├── raw/
│ ├── interim/
│ ├── processed/
│ └── submissions/
├── notebooks/
│ ├── 01_eda.ipynb
│ ├── 02_persistence_baseline.ipynb
│ ├── 03_baseline_lgbm.ipynb
│ └── 04_feature_engineering.ipynb
├── src/
│ ├── config.py
│ ├── load_data.py
│ ├── features.py
│ ├── train.py
│ ├── predict.py
│ └── metrics.py
├── outputs/
│ ├── models/
│ ├── figures/
│ └── logs/
├── requirements.txt
└── README.md
NetCDFを扱うため、xarray を使うと便利です。
import xarray as xr
import pandas as pd
# NetCDF読み込み例
# ds = xr.open_dataset("data/raw/features.nc")
# df_features = ds.to_dataframe().reset_index()
# ラベルCSV読み込み例
# train_labels = pd.read_csv("data/raw/train_labels.csv")
9. ベースラインコードの考え方
まずは TWS_t をそのまま Target とするPersistence Modelを作り、その後にLightGBMへ進む流れからかんがえていきます。
import numpy as np
import pandas as pd
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error
from lightgbm import LGBMRegressor
train = pd.read_csv("data/processed/train.csv")
test = pd.read_csv("data/processed/test.csv")
sample = pd.read_csv("data/raw/SampleSubmission.csv")
target_col = "Target"
id_col = "ID"
# まずはPersistence Modelを確認
rmse_persistence = mean_squared_error(
train[target_col],
train["TWS_t"],
squared=False,
)
print("Persistence RMSE:", rmse_persistence)
features = [c for c in train.columns if c not in [id_col, target_col]]
X = train[features]
y = train[target_col]
X_test = test[features]
oof = np.zeros(len(train))
test_pred = np.zeros(len(test))
kf = KFold(n_splits=5, shuffle=True, random_state=42)
for fold, (tr_idx, va_idx) in enumerate(kf.split(X)):
X_tr, X_va = X.iloc[tr_idx], X.iloc[va_idx]
y_tr, y_va = y.iloc[tr_idx], y.iloc[va_idx]
model = LGBMRegressor(
n_estimators=2000,
learning_rate=0.03,
num_leaves=64,
subsample=0.8,
colsample_bytree=0.8,
random_state=42,
objective="regression",
)
model.fit(
X_tr,
y_tr,
eval_set=[(X_va, y_va)],
eval_metric="rmse",
)
pred_va = model.predict(X_va)
oof[va_idx] = pred_va
test_pred += model.predict(X_test) / kf.n_splits
rmse = mean_squared_error(y, oof, squared=False)
print("OOF RMSE:", rmse)
submission = sample.copy()
submission["Target"] = test_pred
submission.to_csv("data/submissions/submission_lgbm_baseline.csv", index=False)
これを元に発展させています。
以下はチャレンジのロードマップです。
まずは、NetCDFの読み込み、TWSの可視化、Persistence Model、LightGBM baseline、時空間分割検証から始めて、徐々に特徴量とモデルを強化していきたいと思います。
10. チャレンジロードマップ
Step 1: データを読み込む
NetCDFを xarray で読み込み、CSVラベルと結合できる形にします。
Step 2: Persistence Modelを作る
まず TWS_t をそのまま TWS_{t+1} とみなすベースラインを作り、RMSEの基準値を確認します。
Step 3: LightGBMで1回提出する
最初はシンプルな特徴量でLightGBMを学習し、提出形式・スコア・エラーの有無を確認します。
Step 4: EDAを丁寧に行う
目的変数の分布、欠損、train/testの分布差、地域差、季節差を確認します。
Step 5: 検証を改善する
ランダムKFoldだけでなく、Time split、Spatial split、緯度帯別検証を試します。
Step 6: 特徴量を増やす
SPEIの短期・長期特徴、TWS anomaly、土壌水分差分、季節特徴量、空間クラスタなどを追加します。
Step 7: アンサンブル
LightGBM、CatBoost、XGBoost、線形モデルなどを組み合わせ、予測を平均または重み付き平均します。
Step 8: 再現性を整える
上位を狙う場合、raw dataからsubmissionまで一発で再現できる形にします。
11. まとめ
このコンペは、地球観測データ、水文・干ばつ監視、GIS、機械学習が交差する非常に実践的なチャレンジです。
特に重要なポイントは以下の項目になると考えています。
12. 参考リンク
-
Zindi公式コンペページ
https://zindi.africa/competitions/one-step-ahead-of-drought-forecasting-global-water-storage-challenge -
Zindiデータページ
https://zindi.africa/competitions/one-step-ahead-of-drought-forecasting-global-water-storage-challenge/data -
Zindiリーダーボード
https://zindi.africa/competitions/one-step-ahead-of-drought-forecasting-global-water-storage-challenge/leaderboard -
NASA GRACE-FO Water Storage
https://gracefo.jpl.nasa.gov/science/water-storage/ -
UCAR Climate Data Guide: GRACE
https://climatedataguide.ucar.edu/climate-data/grace-gravity-recovery-and-climate-experiment-surface-mass-total-water-storage-and -
UCAR Climate Data Guide: SPEI
https://climatedataguide.ucar.edu/climate-data/standardized-precipitation-evapotranspiration-index-spei