机器学习 + 城市规划第九期:地理加权回归(GWR)算法的应用
🧭 引言
在城市规划与空间分析中,我们常常面对这样的问题:某个变量(比如自行车使用量)是否在不同区域受到不同程度的影响?传统回归方法只能给出“全局平均效应”,而忽略了空间异质性。
这时,地理加权回归(GWR)就派上了用场。
🧠 什么是 GWR?
Geographically Weighted Regression(GWR) 是一种局部回归模型,它允许解释变量的回归系数在地理空间中发生变化。也就是说,它假设城市空间是“多样”的,而不是“一刀切”的。
与传统线性回归的对比:
模型 | 假设 | 适用 |
---|---|---|
线性回归 | 所有区域参数相同(全局) | 整体趋势建模 |
GWR | 每个位置参数不同(局部回归) | 空间异质建模 |
🧪 数据与研究背景
本期案例中,我们使用了一组城市区域的空间数据,每个观测点包含:
- 经度、纬度
- 自行车事故的严重性(作为因变量 Y)
- 一个影响变量(该数据采用骑行者年龄,作为解释变量 X)
目标:分析这个城市特征因子在不同区域对自行车事故的空间作用差异。
🧰 GWR 模型实现(Python)
我们使用 mgwr
和 geopandas
在 Python 中实现 GWR。以下是核心代码:
激活必要环境
# ===== 导入依赖库 =====
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
import numpy as np
np.float = float # 修复 mgwr 包中对 np.float 的兼容性问题
from mgwr.gwr import GWR
from mgwr.sel_bw import Sel_BW
# 配置 matplotlib 中文显示
import matplotlib
matplotlib.use('TkAgg')# 设置图像后端(防止警告)
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']# 设置中文字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
from gwr_tools import save_gwr_summary # 引入我们自定义的结果保存函数
数据处理部分
# ===== 1. 读取数据 =====
df = pd.read_csv("shuju bike.csv", header=None) # 读取无表头的 CSV
df.columns = ["lon", "lat", "Y", "X"] # 人工指定列名
# 清洗数据
for col in ["lon", "lat", "Y", "X"]:
df[col] = pd.to_numeric(df[col], errors="coerce") # 转换为浮点型,非法值变 NaN
df.dropna(subset=["lon", "lat", "Y", "X"], inplace=True) # 删除缺失值
df.reset_index(drop=True, inplace=True)
空间数据格式处理
# 构造空间数据
geometry = [Point(xy) for xy in zip(df["lon"], df["lat"])] # 创建点对象
gdf = gpd.GeoDataFrame(df, geometry=geometry) # 构建 GeoDataFrame
gdf.set_crs(epsg=4326, inplace=True) # 设置为地理坐标系
gdf = gdf.to_crs(epsg=3857) # 转为平面投影(用于计算距离)
🌍 说明:GWR 建模需要空间坐标,且必须是平面坐标系(不能直接用经纬度计算距离)。
# ===== 2. 提取建模数据 =====
coords = np.array([(point.x, point.y) for point in gdf.geometry]) # 提取空间坐标
y = gdf["Y"].values.reshape((-1, 1)) # 响应变量
X = gdf["X"].values.reshape((-1, 1)) # 解释变量
📐 说明:将 GeoDataFrame 中的值提取为模型所需的 NumPy 数组格式。
模型自动化调优
# ===== 3. 带宽选择 + 模型拟合 =====
print("正在选择最优带宽,请稍候...")
selector = Sel_BW(coords, y, X) # 初始化带宽选择器
bw = selector.search() # 自动寻找最优带宽
print(f"选定的最优带宽为:{bw}")
model = GWR(coords, y, X, bw) # 初始化 GWR 模型
results = model.fit() # 拟合模型
⚙️ 说明:
- 带宽控制了“局部”的范围,是 GWR 的核心参数;
- 自动选择带宽能让模型自适应当前数据分布;
- 模型拟合后,会得到每个点上的局部系数、残差、局部 R² 等。
模型结果输出
print("\n======= GWR 模型结果汇总 =======")
print(results.summary()) # 打印模型整体统计结果
🧾 说明:输出的内容包括 AIC、残差平方和、R²、参数均值等关键指标。
# ===== 4. 保存结果到 GeoJSON,用于地图展示 =====
gdf["GWR_coef_X"] = results.params[:, 0] # 每个点的局部系数
gdf["GWR_resid"] = results.resid_response # 每个点的残差
gdf["local_R2"] = results.localR2 # 每个点的局部 R²
gdf.to_file("gwr_result.geojson", driver="GeoJSON")
print("\n📍 局部系数结果已保存为 'gwr_result.geojson'。")
🗺️ 说明:GeoJSON 文件可用于 QGIS
、ArcGIS
或 Python 中可视化,适合做地图渲染。
# ===== 5. 保存模型统计摘要为 CSV 文件(调用封装的函数)=====
save_gwr_summary(results, model, filename_prefix="bike_gwr")
📊 说明:这个函数会自动导出两个 CSV 文件:
bike_gwr_model_summary.csv
:模型整体诊断指标;bike_gwr_parameter_summary.csv
:解释变量的系数分布统计(均值、标准差、最大/最小值等)。
📌 注意事项:
- 数据要转换为投影坐标系(如 EPSG:3857),以正确计算距离;
- 坐标、变量需清洗成数值型;
- 推荐封装函数保存模型摘要结果,便于后期分析。
📈 模型输出解读
在完成模型训练后,我们得到了以下关键输出:
🟡 局部回归系数(GWR_coef_X)
每个点上,该因子对骑行量的回归系数,可视化后形成“空间影响图”:
- 正系数:该因子促进骑行
- 负系数:该因子抑制骑行
- 越大说明作用越强
🔵 局部 R²(local_R2)
说明 GWR 模型在某一地区拟合的好坏:
- 高值:解释力强,变量在此有效;
- 低值:说明可能有其他重要变量未纳入。
🔴 残差分布(GWR_resid)
揭示模型预测误差,辅助识别系统性低估或高估区域。
📊 模型摘要自动输出
我们使用封装函数 save_gwr_summary()
自动保存:
封装包名称为gwr_tools.py
代码如下:
# gwr_tools.py
import pandas as pd
import numpy as np
def save_gwr_summary(results, model, filename_prefix='gwr'):
"""
保存 GWR 模型结果摘要为两个 CSV 文件:
1. {prefix}_model_summary.csv - 模型整体指标
2. {prefix}_parameter_summary.csv - 各变量参数统计
"""
summary_dict = {}
# 模型诊断与整体指标
summary_dict["RSS"] = results.RSS
summary_dict["trace(S)"] = results.tr_S
summary_dict["DoF (n - trace(S))"] = results.n - results.tr_S
summary_dict["sigma"] = np.sqrt(results.RSS / (results.n - results.tr_S)) # ✅ 用公式替代
summary_dict["log_likelihood"] = results.llf
summary_dict["AIC"] = results.aic
summary_dict["AICc"] = results.aicc
summary_dict["BIC"] = results.bic
summary_dict["R2"] = results.R2
summary_dict["Adj_R2"] = results.adj_R2
# 写入整体模型信息文件
summary_df = pd.DataFrame(list(summary_dict.items()), columns=["Metric", "Value"])
summary_df.to_csv(f"{filename_prefix}_model_summary.csv", index=False, encoding="utf-8-sig")
# 各变量参数统计
param_stats = []
var_names = [f"X{i}" for i in range(results.params.shape[1])]
for i, name in enumerate(var_names):
param_stats.append({
"Variable": name,
"Mean": np.round(results.params[:, i].mean(), 6),
"Std": np.round(results.params[:, i].std(), 6),
"Min": np.round(results.params[:, i].min(), 6),
"Median": np.round(np.median(results.params[:, i]), 6),
"Max": np.round(results.params[:, i].max(), 6)
})
param_df = pd.DataFrame(param_stats)
param_df.to_csv(f"{filename_prefix}_parameter_summary.csv", index=False, encoding="utf-8-sig")
print(f"\n✅ 模型统计结果已保存:")
print(f" - {filename_prefix}_model_summary.csv")
print(f" - {filename_prefix}_parameter_summary.csv")
bike_gwr_model_summary.csv
:模型整体指标(AIC、R² 等)bike_gwr_parameter_summary.csv
:每个变量的空间系数统计(均值、标准差等)
📊 GWR 模型输出结果详细解读
在完成地理加权回归(GWR)模型拟合后,我们得到了系统输出的一系列统计指标和参数估计。下面对这些结果进行详细拆解与分析,帮助理解 GWR 模型的实际表现。
✅ 1. 模型诊断指标(Diagnostic Information)
Residual sum of squares (RSS): 3036.221
Effective number of parameters: 89.542
Degree of freedom: 8706.458
Sigma estimate: 0.591
Log-likelihood: -7802.904
AIC: 15786.891
AICc: 15788.796
BIC: 16428.113
R²: 0.025
Adjusted R²: 0.015
指标 | 含义解释 |
---|---|
RSS | 模型残差平方和。越小代表预测越准确 |
trace(S) | 模型复杂度,代表自由度消耗程度 |
DoF | 有效自由度,样本数减去 trace(S) |
Sigma | 残差标准差的估计,衡量误差的平均波动 |
Log-likelihood | 越大表示模型越好;用于与其他模型对比 |
AIC/AICc/BIC | 模型选择准则,越小越好 |
R² / Adj R² | 模型拟合优度,表示解释变量解释了多少响应变量的变化;值越高越好(当前偏低) |
📌 本例解读:
- 模型拟合能力偏弱(R² 仅为 2.5%),可能说明只有一个变量
X
不足以解释Y
的空间变化; - AIC/AICc 在不同带宽下可用于模型优选;
- trace(S) = 89.5 表示模型参数空间自由度中等。
✅ 2. GWR 局部参数估计统计(Summary Statistics)
Variable Mean Std Min Median Max
-----------------------------------------------------
X0 2.413 0.069 2.135 2.418 2.581
X1 -0.000 0.000 -0.001 -0.000 0.001
项目 | 含义 |
---|---|
X0 | 截距项,在空间上略有变化,说明整体基准值有轻微区域差异 |
X1 | 主解释变量系数,其均值接近 0,说明对因变量整体影响极弱 |
Std | 空间变异程度。数值越大,说明该变量在不同地点作用差异大 |
Min/Max | 空间作用范围(负值表负向影响,正值为正向影响) |
📌 本例解读:
X1
的系数分布在 [-0.001, 0.001] 范围内,基本接近 0;- 暗示该变量(如人口密度或道路密度)在解释骑行量上的影响极其微弱;
- 改进方法—后续加入更多影响因素,如道路类型、可达性、设施密度等。
✅ 3. 空间显著性与可信度(判断变量在哪些区域“真正有效”)
Adj. alpha (95%): 0.001
Adj. critical t value (95%): 3.260
🔍 这是什么意思?
地理加权回归(GWR)是对每个点进行局部回归,因此它为每个点生成了一组回归系数。但这并不意味着每个点的系数都是“显著有效”的。
为了判断某个点上的回归结果是否“统计显著”,GWR 提供了两个关键值:
项目 | 含义 |
---|---|
Adj. alpha (95%) = 0.001 | 调整后的显著性水平,等价于 0.1% 的显著性要求,控制多重比较误差 |
Adj. critical t value (95%) = 3.260 | t 值的临界值。只有当 t > 3.260,才认为该点上的系数“统计显著” |
🎯 实用意义:
- 可以绘制一张“显著性空间图”,只高亮那些满足
|t| > 3.260
的点; - 这将帮助回答一个重要的城市规划问题:
👉 某个变量(如人口密度)到底在哪些地区真正有用,在哪些地区可以忽略?
比如:如果人口密度只在核心城区显著,而在郊区不显著,那么郊区规划就应该考虑其他因子。
✅ 总体评价与建议
📉 本模型结果表明:当前单变量 GWR 模型解释力偏弱,但也揭示了以下方向:
- ✅ 验证了空间异质性的存在(系数在空间上略有波动);
- ⚠️ 当前变量解释力不强,建议扩展为多变量 GWR(MGWR);
- 📌 可使用系数图、局部 R² 图进一步辅助城市规划决策。
本案例展示了 GWR 在城市规划中的核心优势:量化空间异质性。它让我们更清楚地看见:
- 哪些区域影响因素更强?
- 哪些地方模型拟合不好?是否遗漏了关键变量?
- 是否需要分区域制定规划策略?
@原创声明:本教程由课题组内部教学使用,利用CSDN平台记录,不进行任何商业盈利。