gnnwr について
GNNWRは、回帰係数の空間的な変化を調べる分析者向けの地理加重回帰用Pythonツールです。空間・時空間モデルに加え、疎な近傍距離、診断、地図表示機能を備えています。
主な機能
- 01ニューラルネットによる地理的空間回帰
- 02GTNNWRによる時空間回帰
- 03KNN疎距離行列
- 04R²、RMSEなどのモデル診断
- 05係数と予測値のインタラクティブマップ
活用シーン
- 01空間的に変化する回帰係数の分析
- 02時間座標を含むモデルの適合
- 03大規模な空間回帰データの処理
- 04係数と予測結果の地図化
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ steadfastasart/ geoscience-skills --skill gnnwrインストール後、Claude Code で/gnnwrを入力して読み込まれたか確認します。
同梱ファイルreferences/diagnostics.mdreferences/visualization.md
詳細
GNNWR - 地理ニューラルネットワーク加重回帰
クイックリファレンス
from gnnwr import models, datasets, utils
import pandas as pd
data = pd.read_csv("data.csv")
train, val, test = datasets.init_dataset(
data=data, test_ratio=0.2, valid_ratio=0.1,
x_column=["x1", "x2", "x3"], y_column=["y"],
spatial_column=["lon", "lat"], # REQUIRED: geographic coords
batch_size=32, process_fn="minmax_scale"
)
model = models.GNNWR(train, val, test, use_gpu=True, optimizer="Adam", start_lr=0.01)
model.run(max_epoch=200, early_stop=30)
result = model.reg_result(only_return=True) # DataFrame: coef_x1, coef_x2, ..., Pred_y
print(model.result()) # R², AIC, RMSE, F-tests summary
時空間(GTNNWR)
train, val, test = datasets.init_dataset(
data=data, ...,
spatial_column=["lon", "lat"],
temp_column=["year", "month"], # add temporal coords
use_model="gtnnwr"
)
model = models.GTNNWR(train, val, test, use_gpu=True)
大規模(N > 10k)— KNN モード
train, val, test = datasets.init_dataset(
data=data, ..., knn_k=500 # only k nearest neighbor distances
)
# Memory: N=100k full=55GB → knn_k=2000 only 763MB
主要クラス
| クラス | 目的 |
|---|---|
models.GNNWR | ニューラルネットワークによる地理的重み付けを用いた空間回帰 |
models.GTNNWR | 時間+空間の重み付けを用いた時空間回帰 |
datasets.init_dataset | データ分割、正規化、距離行列の構築 |
utils.Visualize | 係数と予測を表示する組み込みの folium インタラクティブマップ |
基本的な操作
init_dataset のパラメーター
| パラメーター | デフォルト | 備考 |
|---|---|---|
knn_k | None | KNN 疎距離。None=完全行列 |
process_fn | "minmax_scale" | または "standard_scale" |
spatial_fun | BasicDistance | ユークリッド距離、または ManhattanDistance |
Reference | None | "train"、"train_val"、またはカスタム DataFrame |
sample_seed | 42 | 再現性 |
モデルのハイパーパラメーター
| パラメーター | 推奨値 | 備考 |
|---|---|---|
optimizer | "Adam" | ほかに SGD、AdamW、Adagrad、RMSprop |
start_lr | 0.01–0.1 | 重要な調整ポイント |
drop_out | 0.2 | 0.0–0.5 |
dense_layers | None(自動) | 自動:input_dim から n_coef までの 2 の累乗系列 |
early_stop | 20–50 | 忍耐値。-1=無効 |
batch_norm | True | 学習を安定化 |
use_ols | True | OLS で初期化された出力層 |
診断
diag = model._test_diagnosis
diag.R2() # always available
diag.RMSE() # always available
diag.AIC() # needs lite=False (auto for N<10k)
diag.AICc() # corrected AIC
diag.F1_Global() # GNNWR vs OLS significance
diag.F2_Global() # spatial weight significance
diag.F3_Local() # per-variable significance → (dict1, dict2)
lite=True(N>10k の場合は自動):R²/RMSE のみ。ハット行列による診断はスキップされます。
可視化パターン
Folium インタラクティブマップ(組み込み)
viz = utils.Visualize(model, lon_lat_columns=["lon", "lat"], zoom=5)
m1 = viz.display_dataset(name="all", y_column="y")
m1.save("dataset_map.html")
for col in [c for c in result.columns if c.startswith("coef_")]:
m = viz.coefs_heatmap(data_column=col, steps=20)
m.save(f"map_{col}.html")
Matplotlib 静的マップ(論文掲載向け)
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
coef_cols = [c for c in result.columns if c.startswith("coef_")]
for ax, col in zip(axes.flat, coef_cols):
sc = ax.scatter(
result["lon"], result["lat"],
c=result[col], cmap="RdYlBu_r", s=5, alpha=0.8,
vmin=result[col].quantile(0.02), vmax=result[col].quantile(0.98)
)
ax.set_title(col.replace("coef_", "β_"), fontsize=14)
plt.colorbar(sc, ax=ax, shrink=0.8)
plt.suptitle("Spatially Varying Coefficients (GNNWR)", fontsize=16)
plt.tight_layout()
plt.savefig("coefficients_map.png", dpi=300, bbox_inches="tight")
GeoPandas + Contextily(ベースマップ付き)
import geopandas as gpd
import contextily as ctx
gdf = gpd.GeoDataFrame(result, geometry=gpd.points_from_xy(result.lon, result.lat), crs="EPSG:4326")
gdf_web = gdf.to_crs(epsg=3857)
fig, ax = plt.subplots(figsize=(12, 10))
gdf_web.plot(column="coef_x1", ax=ax, cmap="RdYlBu_r", legend=True,
markersize=5, alpha=0.7, legend_kwds={"shrink": 0.6})
ctx.add_basemap(ax, source=ctx.providers.CartoDB.Positron)
ax.set_title("β_x1 Spatial Variation")
ax.set_axis_off()
plt.savefig("coef_basemap.png", dpi=300, bbox_inches="tight")
代替手段との使い分け
| ユースケース | ツール | 理由 |
|---|---|---|
| 空間的に変化する係数(ニューラルネット) | GNNWR | 非線形の重み付け、スケーラブル、係数マップ |
| 古典的な地理的加重回帰 | mgwr / GWR4 | 従来型の帯域幅ベースで、理論が確立 |
| 空間補間(共変量なし) | verde / scikit-gstat | 回帰を使わないグリッディング/クリギング |
| グローバル回帰のベースライン | statsmodels / scikit-learn | 空間的非定常性を仮定しない |
| 時空間的に変化する係数 | GTNNWR | 時間次元に拡張した GNNWR |
| 大規模な空間回帰(N > 100k) | GNNWR + knn_k | 疎距離行列、O(n·k²) の診断 |
| 地球統計シミュレーション | geostatspy / SGeMS | 確率的実現、定量的な不確実性 |
GNNWR を選ぶ場合:ニューラルネットワークベースの地理的重み付けによる空間的に変化する回帰係数が必要な場合、特に従来型の GWR では計算が困難な大規模データセットに適しています。
古典的な GWR を選ぶ場合:確立された推測統計、帯域幅ベースの重み付け、よりシンプルなモデル解釈が必要な場合に適しています。
verde/クリギングを選ぶ場合:説明変数を使わず、観測値から純粋な空間予測を行う補間が必要な場合に適しています。
一般的なワークフロー
空間回帰分析
- EDA:空間分布、特徴量の相関、OLS のベースラインを確認
- データ分割:適切な比率と
sample_seed=42を指定してinit_datasetを使用 - 学習:デフォルト値から始め、
start_lrとearly_stopを調整 - 診断:R²、RMSE、F1(GNNWR 対 OLS)、F2(空間重みの有意性)
- 可視化:係数マップ、残差の空間分布、予測値対観測値
- 解釈:係数が最も大きく変化する場所はどこか。どの変数が最も強い非定常性を示すか。(F3_Local)
- 報告:モデルの要約表+係数マップ+診断統計量
よくある問題
| 問題 | 解決策 |
|---|---|
| モデルがグローバル回帰に退化する | spatial_column を指定し忘れています。必ず渡してください |
| 距離行列で OOM が発生する | knn_k を指定せずに N > 10k となっています。knn_k=500–2000 を使用してください |
| トレーニング中に損失が急増する | start_lr が高すぎます。0.01 から始めてください |
| 過学習 | early_stop がありません。必ず 20–50 に設定してください |
| 係数のスケールが正しくない | スケールを元に戻した予測には reg_result() を使用してください |
| GTNNWR が GNNWR のように動作する | temp_column がありません。警告なしでフォールバックします |
参考資料
コメント
Markdown 対応