当前位置: 首页 > news >正文

共享自行车与电动共享自行车使用中建成环境影响的对比研究:基于合肥数据的时空机器学习分析

共享自行车与电动共享自行车使用中建成环境影响的对比研究:基于合肥数据的时空机器学习分析

一、研究背景与核心目标

共享微出行(如共享自行车BS、电动共享自行车EBS)作为推动城市可持续交通的重要方式,近年来发展迅速,但现有研究多单独分析BS或EBS,缺乏二者出行特征与影响因素的对比;同时,机器学习模型虽能捕捉非线性关系,却常忽略时空异质性,易导致估计偏差。为此,本研究以中国合肥为案例,开发了融合XGBoost(极端梯度提升)与GTWR(地理时空加权回归)的“GTWBoost”模型,既考虑时空异质性,又捕捉非线性关系,最终对比分析建成环境对BS和EBS使用的影响,为运营商优化调度与政策制定提供依据。

二、共享微出行的特征差异与研究缺口

共享微出行凭借便捷、低成本优势,能减少碳排放、缓解拥堵并促进健康,但BS与EBS存在显著差异:BS依赖人力,适合1-3km短途出行,多为无桩模式(灵活便捷);EBS借助电力辅助,可覆盖更长距离(中国平均2.2km,高于BS的1.5km),应对上坡、逆风等场景,多为有桩模式(便于电池管理)。

现有研究存在三大缺口:一是缺乏BS与EBS出行特征的直接对比,EBS因发展较晚、数据有限,相关分析较少;二是建成环境对EBS使用的影响机制尚未明确,现有研究多聚焦BS;三是机器学习模型(如XGBoost)虽能抓非线性,但忽略时空异质性,而GTWR虽能处理时空变化,却难以捕捉复杂非线性,二者结合的模型尚未应用于共享微出行研究。

三、研究区域与数据基础

3.1 研究区域:合肥的共享微出行场景

合肥作为安徽首府,2010-2023年人口从570万增至985万,GDP大幅增长,是华东科技枢纽(南部滨湖新区、西部高新区为产业核心)。该市2017年引入无桩BS,2018年推出有桩EBS,2021年运营规模达22.5万辆BS、7.5万辆EBS,定价上EBS略高(首15分钟2.5元,BS为1.5元)。

为确保数据可比性,研究范围限定为BS与EBS服务重叠区域,具体空间范围如图1所示。
在这里插入图片描述

图1 研究区域图:图中标注了合肥的市中心、道路网络、行政区界与水体,明确了西部高新区、南部滨湖新区等产业集中区的位置。深色覆盖区域即为BS与EBS服务重叠的分析范围,排除了服务不重叠区域的偏差,确保后续对比分析的空间一致性。

3.2 数据与变量设计

研究采用2023年6月4-10日(一周)的出行数据,清理后保留32,256条BS记录与1,024,786条EBS记录,包含起止时间、经纬度等信息。空间分析单元为500m×500m网格(共1,328个),因变量为“网格内每小时出行次数”,统计显示EBS平均每小时10.32次,远高于BS的0.38次,反映用户对EBS的偏好。

自变量基于“5D建成环境框架”设计(表1,变量定义与描述统计),包括:

  • 密度:就业密度(平均2.09千人/km²)、人口密度(平均6.54千人/km²);
  • 多样性:9类POI密度(如餐厅、商场)、土地利用混合熵(平均0.55);
  • 设计:主次干道密度、自行车道长度等;
  • 目的地可达性:到市中心的网络距离(平均8.98km);
  • 公交距离:公交站密度、到最近地铁站距离(平均1.08km);
  • 社会经济变量:65岁以上人口占比(10.48%)、高学历人口占比(22.37%)、房价(平均1.6万元/m²)等。
    所有数据均与出行数据的时间范围对齐,确保时效性。

四、方法论:GTWBoost模型的构建

GTWBoost 模型的核心是解决传统机器学习与空间回归模型的各自局限——既保留 XGBoost 对非线性关系的捕捉能力,又通过整合 GTWR 的时空加权机制,弥补其忽略时空异质性的缺陷。以下从模型基础、整合逻辑、核心步骤三方面,结合原文细节展开说明。

4.1 基础模型:XGBoost 的非线性捕捉机制

XGBoost(极端梯度提升)是一种基于决策树集成的机器学习算法,其优势在于通过“梯度下降”优化目标函数,同时引入正则化项控制模型复杂度,能高效捕捉变量间的复杂非线性关系,这也是其被选为基础模型的核心原因(🔶1-78、🔶1-79)。

4.1.1 目标函数与正则化设计

XGBoost 的目标函数由损失项正则项两部分构成,公式如下:
Objective=∑i=1nl(yi,y^i)+∑kKΩ(fk) Objective =\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}\right)+\sum_{k}^{K} \Omega\left(f_{k}\right) Objective=i=1nl(yi,y^i)+kKΩ(fk)

  • 损失项 l(yi,y^i)l(y_i, \hat{y}_i)l(yi,y^i):衡量模型预测值 (\hat{y}_i) 与实际值 (y_i) 的差异,本研究针对“网格内每小时出行次数”这一连续因变量,采用均方误差(MSE)作为损失函数,确保误差计算的连续性与合理性。
  • 正则项 Ω(fk)\Omega(f_k)Ω(fk):用于控制第 (k) 棵决策树 (f_k) 的复杂度,避免过拟合,公式为:
    Ω(f)=γT+12λ∑j=1Twj2 \Omega(f)=\gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2} Ω(f)=γT+21λj=1Twj2
    其中:TTT 为单棵树的叶节点数量,wjw_jwj 为第 j个叶节点的权重,γ\gammaγ是叶节点数量的惩罚系数γ\gammaγ越大,模型越倾向于生成简单树),λ\lambdaλ是叶节点权重的 L2 正则系数λ\lambdaλ 越大,权重波动越小,模型越稳定)。

这种“损失+正则”的设计,使 XGBoost 在保证预测精度的同时,有效降低过拟合风险,尤其适合处理建成环境变量与共享微出行使用间的复杂关系。

4.1.2 变量相对重要性(RI)计算

为后续识别关键影响因素,XGBoost 可通过计算变量的“相对重要性(RI)”评估其对预测结果的贡献度。具体逻辑为:

  1. 对每棵决策树,统计每个变量在“节点分裂”时的贡献度(分裂后误差减少量);
  2. 对所有树的贡献度进行平方后取平均值,得到该变量的最终相对重要性,公式为:
    RIxi2=1M∑m=1MRIxi2(Tm) RI_{x_{i}}^{2}=\frac{1}{M} \sum_{m=1}^{M} RI_{x_{i}}^{2}\left(T_{m}\right) RIxi2=M1m=1MRIxi2(Tm)
    其中 MMM 为决策树总数,RIxi2(Tm)RI_{x_i}^2(T_m)RIxi2(Tm) 是变量 xix_ixi 在第 mmm 棵树中的平方重要性。
    RI 值越高,说明该变量对 BS/EBS 使用的解释力越强,这为后续筛选核心建成环境因素提供了量化依据。

4.2 整合逻辑:引入 GTWR 的时空加权机制

传统 XGBoost 假设所有数据点在时空上相互独立,生成“全局统一”的预测模型,但共享微出行使用具有显著的时空异质性(如市中心与郊区、高峰与非高峰的影响因素差异),这种假设会导致估计偏差)。而 GTWR(地理时空加权回归)通过构建时空权重矩阵,让回归系数随空间位置(经纬度)和时间(小时/日期)动态变化,能有效刻画异质性,但无法捕捉复杂非线性关系。

GTWBoost 的整合核心,是将 GTWR 的“时空加权机制”嵌入 XGBoost 的模型训练过程,具体实现逻辑如下:

  1. 时空权重矩阵构建:参考 GTWR 的核函数方法(Fotheringham 等,2015),对训练集中的每个目标数据点 ui,vi,tiu_i, v_i, t_iui,vi,ti,即空间坐标 ui,viu_i, v_iui,vi 与时间 tit_iti,为其周边的“时空邻居”分配权重——距离越近(空间/时间),权重越高,反之越低;
  2. 局部 XGBoost 模型训练:对每个目标数据点,仅用其“时空邻居”的加权数据训练一个局部 XGBoost 模型,而非用全局数据训练单一模型;
  3. 预测值聚合:对测试集中的每个数据点,调用其对应时空范围内的局部模型,结合邻居权重计算最终预测值,实现“时空本地化”与“非线性捕捉”的双重目标。

4.3 GTWBoost 模型的四步核心流程

原文通过四步流程实现 GTWBoost 模型的构建与优化,每一步均围绕“确定最优时空参数”或“验证模型性能”展开,流程细节与逻辑如下:

4.3.1 步骤 1:数据集拆分(保留时空信息)

与传统机器学习一致,首先将 1,328 个网格的“小时级出行数据+建成环境变量”随机拆分为训练集(80%)与测试集(20%)。

  • 关键设计:拆分时需完整保留每个网格的时空坐标信息——包括网格中心点的经度 u、纬度 v,以及出行记录的具体小时 t,为后续计算时空权重提供基础;
  • 目的:避免因时空信息丢失导致权重计算偏差,确保训练出的局部模型能匹配实际时空场景。
4.3.2 步骤 2:确定最优空间带宽(捕捉空间异质性)

“空间带宽”指每个目标数据点需纳入的“空间邻居(SN)”数量,是控制空间异质性的核心参数。原文通过以下方式确定最优值:

  1. 空间权重计算方法:采用“固定带宽双平方核函数”,公式为:
    在这里插入图片描述

    其中:dijd_{ij}dij 是目标数据点 jjj 与空间邻居 iii 的地理直线距离,dmaxd_{max}dmax 是目标点 jjj 所有邻居的最大距离,wj′w_j'wj 是归一化后的权重(确保权重和为 1)。该函数的特点是“距离越近,权重衰减越快”,符合空间数据的“距离衰减定律”。

  2. 最优 SN 筛选范围:测试 SN 从 40 到 150,以 10 为步长(共 12 组),对每组 SN 分别训练局部 XGBoost 模型;

  3. 性能评估指标:通过测试集的 (R^2)(决定系数,衡量解释力)、RMSE(均方根误差,衡量预测偏差)、MAE(平均绝对误差,衡量稳健性)筛选最优 SN——(R^2) 最高、RMSE 与 MAE 最低的 SN 即为最优值;

  • 原文结果:BS 模型的最优 SN 为 100,EBS 模型的最优 SN 为 80,说明 EBS 的空间影响范围略小于 BS,可能与 EBS 有桩模式的服务半径更集中有关。
4.3.3 步骤 3:确定最优时间带宽(捕捉时间异质性)

“时间带宽”通过“时间衰减系数(DC)”实现,用于衡量“前 1 小时”“当前小时”“后 1 小时”数据对目标小时的影响权重,核心是解决“不同时段的时空邻居对预测的贡献差异”:

  1. 时间衰减逻辑:假设“与目标小时越近的时段,数据相关性越强”,因此对“前 1 小时”和“后 1 小时”的空间邻居数量进行衰减——衰减后的邻居数量 = 最优空间 SN × DC;

  2. DC 取值设计:为平衡计算效率与精度,参考 Fotheringham 等(2015)的研究,将 DC 限定为 0.2、0.5、0.8 三个固定值,形成 9 种组合(前 1 小时 DC × 后 1 小时 DC);

  3. 权重计算扩展:将空间权重公式扩展至时空维度,公式为:
    在这里插入图片描述

    其中 k1k_1k1 是前 1 小时的 DC,k2k_2k2 是后 1 小时的 DC,nnn 是最优空间 SN,TTT 为目标时段;

  4. 最优 DC 筛选:对 9 种 DC 组合分别训练模型,通过测试集的 R2R^2R2、RMSE、MAE 选择最优组合;

  • 原文结果:不同小时的最优 DC 存在差异,例如早高峰(7:00-9:00)的 DC 多为 0.2(增强近期数据权重),夜间(22:00-23:00)的 DC 多为 0.8(扩大时间影响范围)(表 A2)。
4.3.4 步骤 4:模型评估与解释(验证优势与挖掘规律)

完成时空带宽优化后,需通过多维度评估验证 GTWBoost 的优越性,并通过“相对重要性”与“部分依赖图(PDP)”解释模型结果:

  1. 模型性能对比:将 GTWBoost 与原始 XGBoost 对比,核心指标为 (R^2)、RMSE、MAE:
    • BS 模型:GTWBoost 的 (R^2) 从 0.577 提升至 0.915(+58.58%),RMSE 从 4.399 降至 2.057,MAE 从 1.369 降至 0.793;
    • EBS 模型:GTWBoost 的 (R^2) 从 0.676 提升至 0.932(+37.87%),RMSE 从 45.303 降至 21.015,MAE 从 30.383 降至 13.738;
      结果证明,引入时空异质性后,模型对共享微出行使用的预测精度显著提升。
  2. 变量相对重要性(RI)分析:基于 GTWBoost 模型计算所有建成环境变量的 RI,识别核心影响因素;
  3. 部分依赖图(PDP)绘制:固定其他变量不变,仅改变目标变量的值,绘制其与 BS/EBS 使用的关系曲线,直观呈现非线性特征。

4.4 模型创新点总结

GTWBoost 相比传统模型,核心创新在于两点:

  1. 双重优势整合:首次将 XGBoost 的非线性捕捉能力与 GTWR 的时空异质性刻画能力结合,解决了“单一模型无法同时处理非线性与时空变化”的行业痛点;
  2. 本地化建模逻辑:通过“时空邻居加权”实现“每个数据点对应一个局部模型”,而非全局统一模型,更贴合共享微出行“时空动态变化”的实际特征,为后续政策建议提供更精准的量化依据。

五、结果与讨论:BS与EBS的特征差异及建成环境影响

5.1 出行特征对比

5.1.1 时空使用模式(图3、图4)

在这里插入图片描述

图3 BS与EBS使用的空间分布:采用热力图呈现,深色代表高使用率。

  • 整体:EBS使用率显著高于BS,即使EBS车辆数量仅为BS的1/3;
  • BS:集中在市中心(商业、就业密集)及西部、西南部(大学、产业园),短途需求旺盛;
  • EBS:分布更均匀,南部滨湖新区(创新产业、旅游区)出现热点——该区域设施分散,居民需更长距离出行,EBS的电力辅助优势更突出。
    在这里插入图片描述

图4 BS与EBS使用的时间分布:横轴为一天24小时,纵轴为使用率占比,实线为BS,虚线为EBS。

  • 共性:均呈现“早晚双高峰”(7:00-9:00、17:00-19:00),说明二者核心功能是服务通勤;
  • 差异:EBS高峰时段占比更高(早高峰EBS占比超30%,BS约20%),反映通勤用户对EBS“省时省力”的偏好;BS在非高峰时段(如10:00-16:00)占比更高,兼顾休闲、购物等非通勤需求;EBS在19:00后使用率下降更慢,常用于夜间出行(如聚餐、娱乐返程)。
5.1.2 出行距离与时长(图5)

在这里插入图片描述

图5 BS与EBS的出行距离(左)和时长(右)分布:蓝色代表BS,红色代表EBS,横轴为距离(km)或时长(min),纵轴为频次密度。

  • 距离:BS平均2.0km(1.0-2.4km为主要区间),EBS平均4.0km(1.8-5.2km为主要区间),EBS距离近为BS的2倍,体现电力辅助对“距离限制”的突破;
  • 时长:BS平均8.9min(5.1-12.3min),EBS平均10.9min(6.4-14.5min)——EBS距离翻倍,但时长仅增加22%,反映其更高的行驶速度;
  • 结论:BS适合2km内短途(无桩模式无需固定还车点,灵活),EBS适合2-5km中短途,可替代部分私家车、公交出行。

5.2 GTWBoost模型结果

5.2.1 模型性能优势(表2)

对比GTWBoost与原始XGBoost的性能指标(R²越高、RMSE/MAE越低越好):

  • BS:GTWBoost的R²从0.577提升至0.915(+58.58%),RMSE从4.399降至2.057,MAE从1.369降至0.793;
  • EBS:GTWBoost的R²从0.676提升至0.932(+37.87%),RMSE从45.303降至21.015,MAE从30.383降至13.738。
    说明引入时空异质性后,模型对出行需求的预测精度显著提升,验证了GTWBoost的合理性。
5.2.2 关键影响因素(相对重要性)

表3显示,影响BS与EBS使用的“Top8因素”完全一致,仅排序略有差异,核心因素为:

  1. 到地铁站距离:二者最关键——合肥约16%的BS、32%的EBS出行用于接驳地铁,解决“最后一公里”;
  2. 就业密度:通勤需求的核心来源,合肥近年产业扩张吸引400万新增人口,推高共享微出行需求;
  3. 道路设计:主干道密度(EBS更依赖,偏好快速路线)、支路密度(BS更依赖,适合短途灵活穿梭);
  4. 土地利用混合度:超过阈值后(BS为0.5,EBS为0.64),出行需求骤升,因混合用地缩短出行距离。
5.2.3 建成环境的非线性影响(PDP图6-9)

通过部分依赖图(PDP)可直观观察单一因素对出行的非线性影响(控制其他变量不变)。
在这里插入图片描述

图6 就业密度(a)与人口密度(b)的非线性影响

  • 图6a(就业密度):对BS、EBS均呈“单调正相关”——就业密度越高,通勤需求越旺盛,共享微出行使用越多,符合“就业集中区出行需求高”的常识;
  • 图6b(人口密度):存在阈值效应(8200人/km²)——低于阈值时,人口密度越高,BS使用越多(居民短途需求多),EBS无显著变化;超过阈值后,EBS使用骤降(高密度区行人多,EBS速度快、体积大,安全风险高,运营商减少停车点),BS保持稳定。

在这里插入图片描述

图7 主干道密度(a)与支路密度(b)的非线性影响

  • 图7a(主干道密度):BS呈“先升后降”(阈值3km/km²)——初期主干道提升可达性,超过阈值后交通流量大,骑行安全风险高;EBS呈“先降后升”(阈值6km/km²)——初期主干道碎片化,骑行体验差,超过阈值后路线连续,符合EBS“快速直达”需求;
  • 图7b(支路密度):BS呈“U型”(阈值7km/km²)——支路稀疏时,路线直接;支路过密时,覆盖更多目的地;中等密度时,路口多、中断频繁,骑行体验差;EBS呈“单调下降”——支路密度越高,中断越多,影响EBS速度优势,更适合支路稀疏的区域。

在这里插入图片描述

图8 到地铁站距离(a)与土地利用混合度(b)的非线性影响

  • 图8a(到地铁站距离):BS在1.5km内下降(近距离步行接驳,无需BS),1.5-2.3km上升(步行不便,BS成为接驳首选);EBS在0.7km内下降(近距离步行),0.7km后稳定(EBS可直接抵达目的地,无需依赖地铁接驳);
  • 图8b(土地利用混合度):均存在“阈值效应”——BS在混合熵0.5后、EBS在0.64后,使用率骤升,说明用地混合度需达到一定水平,才能显著促进共享微出行(减少长距离出行,增加短途需求)。
    在这里插入图片描述

图9 到市中心距离(a)与房价(b)的非线性影响

  • 图9a(到市中心距离):整体呈负相关(市中心活动密集,需求高),但存在波动——西部高新区、南部滨湖新区等就业中心推高局部需求,抵消“距离衰减”;
  • 图9b(房价):BS呈“先升后降”(阈值2.7万元/m²)——中高房价区居民收入高,出行需求多,超高房价区(如高端社区)限制共享车辆进入;EBS呈“降-升-降”(阈值1.55万元/m²,合肥均价)——低于均价的老小区设施差,BS骑行不便,EBS更受欢迎;中高房价区需求稳定,超高房价区需求下降。

六、政策启示

基于研究结果,从运营商、规划者、政策制定者三方面提出建议:

  1. 运营商优化调度:
    • 高峰前(7:00前、17:00前)将车辆调配至住宅、就业区及地铁站周边,提升通勤服务响应;
    • BS重点布局市中心、支路密集区(短途需求),EBS重点布局郊区、主干道密集区(中短途需求),发挥二者互补性。
  2. 促进交通公平:
    • 扩大BS/EBS在欠发达区域的覆盖(如合肥北部老城区),减少空间可达性差距;
    • 对低收入群体、老年人提供补贴(如EBS月卡折扣),开设社区 workshops 解决“数字鸿沟”(部分老年人不会用APP租车)。
  3. 建成环境优化:
    • 新城区(如滨湖新区)规划时,将土地利用混合熵控制在BS≥0.5、EBS≥0.64,增加短途出行需求;
    • 就业中心(如高新区)周边建设专用自行车道,配套EBS停车点,引导通勤用户选择共享微出行;
    • 整合票价系统(如BS/EBS与地铁联票),减少接驳摩擦,提升多模式出行效率。

七、结论与局限性

7.1 核心结论

  1. 时空特征:BS与EBS均服务通勤(早晚高峰),但BS集中在市中心,EBS分布均匀;EBS平均距离(4.0km)是BS(2.0km)的2倍,时长略长(10.9min vs 8.9min);
  2. 关键因素:到地铁站距离、就业密度是影响二者的最核心因素,道路设计、土地混合度次之;
  3. 非线性关系:建成环境对二者的影响存在阈值效应(如人口密度8200人/km²、土地混合熵0.5/0.64),且方向差异显著(如支路密度对BS正相关、对EBS负相关);
  4. 模型优势:GTWBoost较XGBoost预测精度提升37.87%-58.58%,为共享微出行研究提供更优的分析工具。

7.2 局限性

  1. 数据时效性:仅用一周数据,未涵盖季节、节假日影响,未来需长期数据验证;
  2. 数据粒度:社会经济数据为街道级聚合数据,可能存在“生态谬误”,需个体数据进一步分析;
  3. 政策因素:未考虑“禁停区”“骑行限制”等政策约束,未来需整合行政数据;
  4. 案例局限性:合肥为中国快速城市化城市,结果未必适用于欧美或中小城市,需跨城市对比验证。

附录:模型参数补充

  • 表A1 空间带宽性能:测试SN=40-150,BS在SN=100时R²最高(0.9114),EBS在SN=80时R²最高(0.9290);
  • 表A2 时间衰减系数(DC):不同时段DC不同,如早高峰(7:00-9:00)DC=0.2,增强近期数据权重,提升模型对高峰需求的预测精度。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
import xgboost as xgb
from geopy.distance import geodesic
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# -------------------------- 1. 数据模拟(匹配论文表1统计特征,🔶1-61至🔶1-65) --------------------------
def generate_simulated_data(grid_num=1328, hours=24):"""模拟合肥1328个500m×500m网格的小时级数据,变量分布匹配论文表1"""np.random.seed(42)# 时空基础特征grid_ids = np.repeat(np.arange(grid_num), hours)lons = np.repeat(np.random.uniform(117.1, 117.4, grid_num), hours)  # 合肥经度范围lats = np.repeat(np.random.uniform(31.7, 31.9, grid_num), hours)  # 合肥纬度范围hour = np.tile(np.arange(hours), grid_num)# 建成环境变量(均值/标准差参考论文表1)employment_density = np.random.normal(2.09, 1.92, grid_num*hours)  # 就业密度(千人/km²)population_density = np.random.normal(6.54, 12.70, grid_num*hours)  # 人口密度(千人/km²)distance_metro = np.random.normal(1.08, 0.83, grid_num*hours)  # 到地铁站距离(km)land_use_mix = np.random.normal(0.55, 0.18, grid_num*hours)  # 土地利用混合熵major_road = np.random.normal(5.21, 3.31, grid_num*hours)  # 主干道密度(km/km²)branch_road = np.random.normal(3.83, 2.18, grid_num*hours)  # 支路密度(km/km²)distance_center = np.random.normal(8.98, 4.82, grid_num*hours)  # 到市中心距离(km)house_price = np.random.normal(16.03, 7.22, grid_num*hours)  # 房价(千元/m²)# 目标变量(BS/EBS每小时出行次数,🔶1-63)# 构建非线性关系(模拟论文PDP规律,🔶1-145至🔶1-165)bs_base = 0.1 + 0.05*employment_density - 0.02*distance_metro + 0.03*(land_use_mix>0.5)ebs_base = 5 + 0.8*employment_density - 0.5*distance_metro + 1.2*(land_use_mix>0.64)# 加入时空波动与噪声bs_noise = np.random.normal(0, 0.1, grid_num*hours)ebs_noise = np.random.normal(0, 2, grid_num*hours)# 通勤高峰效应(7-9、17-19时提升,🔶1-121)peak_hour = np.isin(hour, [7,8,9,17,18,19]).astype(int)bs_usage = np.maximum(0, bs_base + 0.1*peak_hour + bs_noise)  # BS均值~0.38ebs_usage = np.maximum(0, ebs_base + 2*peak_hour + ebs_noise)    # EBS均值~10.32# 整合数据集data = pd.DataFrame({"grid_id": grid_ids, "lon": lons, "lat": lats, "hour": hour,"employment_density": employment_density, "population_density": population_density,"distance_metro": distance_metro, "land_use_mix": land_use_mix,"major_road": major_road, "branch_road": branch_road,"distance_center": distance_center, "house_price": house_price,"bs_usage": bs_usage, "ebs_usage": ebs_usage})# 变量约束(确保符合实际意义,如距离非负)for col in ["distance_metro", "distance_center", "major_road", "branch_road"]:data[col] = np.maximum(data[col], 0)data["land_use_mix"] = np.clip(data["land_use_mix"], 0, 1)return data# -------------------------- 2. 时空权重计算(匹配论文GTWR机制,🔶1-88至🔶1-106) --------------------------
def calculate_spatial_weight(target_lon, target_lat, neighbor_lons, neighbor_lats):"""双平方核函数计算空间权重,🔶1-99"""distances = [geodesic((target_lat, target_lon), (lat, lon)).km for lon, lat in zip(neighbor_lons, neighbor_lats)]d_max = max(distances) if max(distances) > 0 else 1e-6weights = [(1 - (d/d_max)**2)**2 for d in distances]weights = np.array(weights) / np.sum(weights)  # 归一化return weightsdef calculate_temporal_weight(target_hour, neighbor_hours, dc_prev=0.5, dc_next=0.5):"""时间衰减权重,🔶1-106"""hour_diff = np.abs(neighbor_hours - target_hour)# 前1小时、当前小时、后1小时权重分配weights = np.zeros_like(hour_diff)weights[hour_diff == 0] = 1  # 当前小时权重1weights[hour_diff == 1] = np.where(neighbor_hours < target_hour, dc_prev, dc_next)  # 前/后小时用DCweights = weights / np.sum(weights) if np.sum(weights) > 0 else np.ones_like(weights)/len(weights)return weights# -------------------------- 3. GTWBoost模型核心(融合XGBoost与GTWR,🔶1-77至🔶1-114) --------------------------
class GTWBoost:def __init__(self, feature_cols, target_col, sn_range=range(40, 151, 10), dc_candidates=[0.2, 0.5, 0.8]):self.feature_cols = feature_cols  # 特征变量列self.target_col = target_col      # 目标变量列self.sn_range = sn_range          # 空间邻居(SN)候选范围(论文🔶1-103)self.dc_candidates = dc_candidates# 时间衰减系数(DC)候选(论文🔶1-109)self.best_sn = None               # 最优空间带宽self.best_dc = None               # 最优时间衰减系数self.local_models = {}            # 存储局部XGBoost模型def select_optimal_spatial_bandwidth(self, train_data):"""步骤2:筛选最优空间带宽(SN),🔶1-98至🔶1-103"""best_r2 = -np.infbest_sn = self.sn_range[0]# 遍历SN候选值for sn in self.sn_range:train_preds = []# 对每个训练样本,找空间邻居并训练局部模型for idx, target_row in train_data.iterrows():# 计算与所有其他训练样本的空间距离,筛选前SN个邻居train_data["dist_to_target"] = train_data.apply(lambda x: geodesic((x["lat"], x["lon"]), (target_row["lat"], target_row["lon"])).km, axis=1)neighbors = train_data.nsmallest(sn, "dist_to_target").drop(idx) if len(train_data) > sn else train_data.drop(idx)if len(neighbors) < 5:  # 避免邻居过少(最少5个样本)neighbors = train_data.drop(idx) if len(train_data) > 1 else train_data# 计算空间权重spatial_weights = calculate_spatial_weight(target_row["lon"], target_row["lat"], neighbors["lon"], neighbors["lat"])# 训练局部XGBoost(带权重)xgb_params = {"objective": "reg:squarederror", "eval_metric": "rmse", "seed": 42}dtrain = xgb.DMatrix(neighbors[self.feature_cols], label=neighbors[self.target_col], weight=spatial_weights)local_model = xgb.train(xgb_params, dtrain, num_boost_round=50)# 预测当前样本dtarget = xgb.DMatrix(target_row[self.feature_cols].values.reshape(1, -1))train_preds.append(local_model.predict(dtarget)[0])# 评估当前SN的性能r2 = r2_score(train_data[self.target_col], train_preds)if r2 > best_r2:best_r2 = r2best_sn = snself.best_sn = best_snprint(f"最优空间带宽(SN): {self.best_sn}, 对应训练R²: {best_r2:.4f}")return self.best_sndef select_optimal_temporal_bandwidth(self, train_data):"""步骤3:筛选最优时间衰减系数(DC),🔶1-104至🔶1-109"""best_r2 = -np.infbest_dc = (self.dc_candidates[0], self.dc_candidates[0])# 遍历DC组合(前1小时DC × 后1小时DC)for dc_prev in self.dc_candidates:for dc_next in self.dc_candidates:train_preds = []for idx, target_row in train_data.iterrows():# 筛选空间邻居(用最优SN)train_data["dist_to_target"] = train_data.apply(lambda x: geodesic((x["lat"], x["lon"]), (target_row["lat"], target_row["lon"])).km, axis=1)spatial_neighbors = train_data.nsmallest(self.best_sn, "dist_to_target").drop(idx) if len(train_data) > self.best_sn else train_data.drop(idx)if len(spatial_neighbors) < 5:spatial_neighbors = train_data.drop(idx) if len(train_data) > 1 else train_data# 计算时间权重temporal_weights = calculate_temporal_weight(target_row["hour"], spatial_neighbors["hour"], dc_prev, dc_next)# 计算时空联合权重(空间权重 × 时间权重)spatial_weights = calculate_spatial_weight(target_row["lon"], target_row["lat"], spatial_neighbors["lon"], spatial_neighbors["lat"])combined_weights = spatial_weights * temporal_weightscombined_weights = combined_weights / np.sum(combined_weights)# 训练局部模型并预测xgb_params = {"objective": "reg:squarederror", "eval_metric": "rmse", "seed": 42}dtrain = xgb.DMatrix(spatial_neighbors[self.feature_cols], label=spatial_neighbors[self.target_col], weight=combined_weights)local_model = xgb.train(xgb_params, dtrain, num_boost_round=50)dtarget = xgb.DMatrix(target_row[self.feature_cols].values.reshape(1, -1))train_preds.append(local_model.predict(dtarget)[0])# 评估当前DC组合r2 = r2_score(train_data[self.target_col], train_preds)if r2 > best_r2:best_r2 = r2best_dc = (dc_prev, dc_next)self.best_dc = best_dcprint(f"最优时间衰减系数(前1小时DC, 后1小时DC): {self.best_dc}, 对应训练R²: {best_r2:.4f}")return self.best_dcdef train(self, train_data):"""步骤1-4:完整训练流程(数据拆分已提前,此处训练局部模型)"""# 步骤2:选最优空间带宽self.select_optimal_spatial_bandwidth(train_data)# 步骤3:选最优时间带宽self.select_optimal_temporal_bandwidth(train_data)# 训练并存储局部模型(按“网格ID-小时”分组,论文🔶1-114)for (grid_id, hour), group in train_data.groupby(["grid_id", "hour"]):if len(group) < 5:continue  # 跳过样本过少的组# 计算组内空间权重(用最优SN)group["dist_to_center"] = group.apply(lambda x: geodesic((x["lat"], x["lon"]), (group["lat"].mean(), group["lon"].mean())).km, axis=1)neighbors = group.nsmallest(self.best_sn, "dist_to_center")spatial_weights = calculate_spatial_weight(group["lon"].mean(), group["lat"].mean(), neighbors["lon"], neighbors["lat"])# 计算时间权重(用最优DC)temporal_weights = calculate_temporal_weight(hour, neighbors["hour"], self.best_dc[0], self.best_dc[1])combined_weights = (spatial_weights * temporal_weights) / np.sum(spatial_weights * temporal_weights)# 训练局部模型xgb_params = {"objective": "reg:squarederror", "eval_metric": "rmse", "seed": 42}dtrain = xgb.DMatrix(neighbors[self.feature_cols], label=neighbors[self.target_col], weight=combined_weights)self.local_models[(grid_id, hour)] = xgb.train(xgb_params, dtrain, num_boost_round=50)print("GTWBoost模型训练完成,共存储局部模型数量:", len(self.local_models))def predict(self, test_data):"""预测测试集,🔶1-114"""test_preds = []for idx, target_row in test_data.iterrows():# 匹配最接近的“网格ID-小时”局部模型target_key = (target_row["grid_id"], target_row["hour"])if target_key not in self.local_models:# 若无匹配模型,用同小时、空间最近的模型candidate_keys = [k for k in self.local_models.keys() if k[1] == target_row["hour"]]if not candidate_keys:# 若无同小时模型,用全局最近模型candidate_keys = list(self.local_models.keys())# 计算空间距离选最优模型min_dist = np.infbest_key = candidate_keys[0]for key in candidate_keys:model_grid = test_data[test_data["grid_id"] == key[0]].iloc[0]dist = geodesic((model_grid["lat"], model_grid["lon"]), (target_row["lat"], target_row["lon"])).kmif dist < min_dist:min_dist = distbest_key = keytarget_key = best_key# 用局部模型预测local_model = self.local_models[target_key]dtarget = xgb.DMatrix(target_row[self.feature_cols].values.reshape(1, -1))test_preds.append(local_model.predict(dtarget)[0])return np.array(test_preds)# -------------------------- 4. 传统XGBoost模型(用于对比,🔶1-78至🔶1-79) --------------------------
def train_xgboost(train_data, test_data, feature_cols, target_col):xgb_params = {"objective": "reg:squarederror", "eval_metric": "rmse", "seed": 42}dtrain = xgb.DMatrix(train_data[feature_cols], label=train_data[target_col])dtest = xgb.DMatrix(test_data[feature_cols], label=test_data[target_col])model = xgb.train(xgb_params, dtrain, num_boost_round=50, evals=[(dtest, "test")], early_stopping_rounds=5, verbose_eval=False)train_pred = model.predict(dtrain)test_pred = model.predict(dtest)# 计算性能指标train_metrics = {"R²": r2_score(train_data[target_col], train_pred),"RMSE": np.sqrt(mean_squared_error(train_data[target_col], train_pred)),"MAE": mean_absolute_error(train_data[target_col], train_pred)}test_metrics = {"R²": r2_score(test_data[target_col], test_pred),"RMSE": np.sqrt(mean_squared_error(test_data[target_col], test_pred)),"MAE": mean_absolute_error(test_data[target_col], test_pred)}return model, train_metrics, test_metrics, test_pred# -------------------------- 5. 模型评估与可视化(论文🔶1-133至🔶1-165) --------------------------
def evaluate_model(y_true, y_pred, model_name, target_name):"""计算模型性能指标"""r2 = r2_score(y_true, y_pred)rmse = np.sqrt(mean_squared_error(y_true, y_pred))mae = mean_absolute_error(y_true, y_pred)print(f"\n{model_name} - {target_name} 性能:")print(f"R²: {r2:.4f}, RMSE: {rmse:.4f}, MAE: {mae:.4f}")return {"R²": r2, "RMSE": rmse, "MAE": mae}def plot_partial_dependence(model, data, feature_col, target_col, feature_name, is_gtwboost=True):"""绘制部分依赖图(PDP),展示非线性关系,🔶1-145"""# 固定其他变量为均值,仅改变目标特征data_pdp = data.copy()feature_vals = np.linspace(data[feature_col].min(), data[feature_col].max(), 50)pdp_preds = []for val in feature_vals:data_pdp[feature_col] = valif is_gtwboost:# GTWBoost预测preds = model.predict(data_pdp.iloc[:100])  # 抽样100个样本减少计算量pdp_preds.append(np.mean(preds))else:# 传统XGBoost预测dmatrix = xgb.DMatrix(data_pdp[self.feature_cols].iloc[:100])preds = model.predict(dmatrix)pdp_preds.append(np.mean(preds))# 绘图plt.figure(figsize=(8, 4))plt.plot(feature_vals, pdp_preds, linewidth=2, color="darkred" if is_gtwboost else "steelblue")plt.xlabel(feature_name, fontsize=12)plt.ylabel(f"平均{target_col}预测值", fontsize=12)plt.title(f"{('GTWBoost' if is_gtwboost else 'XGBoost')} - {feature_name}{target_col}的非线性影响", fontsize=13)plt.grid(alpha=0.3)plt.savefig(f"{('gtwboost' if is_gtwboost else 'xgboost')}_{feature_col}_pdp.png", dpi=300, bbox_inches="tight")plt.close()# -------------------------- 6. 主程序(全流程执行) --------------------------
if __name__ == "__main__":# 步骤1:生成模拟数据(匹配论文特征)print("1. 生成模拟数据...")data = generate_simulated_data(grid_num=1328, hours=24)feature_cols = ["employment_density", "population_density", "distance_metro", "land_use_mix", "major_road", "branch_road", "distance_center", "house_price"]# 步骤2:拆分训练集/测试集(8:2,保留时空信息,🔶1-97)print("2. 拆分训练集与测试集...")train_data, test_data = train_test_split(data, test_size=0.2, random_state=42, stratify=data["grid_id"])print(f"训练集样本数: {len(train_data)}, 测试集样本数: {len(test_data)}")# 步骤3:训练并评估GTWBoost(以EBS为例,BS流程一致)print("\n3. 训练GTWBoost模型(目标变量:ebs_usage)...")gtwboost_ebs = GTWBoost(feature_cols=feature_cols, target_col="ebs_usage")gtwboost_ebs.train(train_data)gtwboost_ebs_pred = gtwboost_ebs.predict(test_data)gtwboost_ebs_metrics = evaluate_model(test_data["ebs_usage"], gtwboost_ebs_pred, "GTWBoost", "EBS使用次数")# 步骤4:训练并评估传统XGBoost(对比用)print("\n4. 训练传统XGBoost模型(目标变量:ebs_usage)...")xgboost_ebs, xgb_train_metrics, xgb_test_metrics, xgboost_ebs_pred = train_xgboost(train_data, test_data, feature_cols, "ebs_usage")xgboost_ebs_metrics = evaluate_model(test_data["ebs_usage"], xgboost_ebs_pred, "传统XGBoost", "EBS使用次数")# 步骤5:绘制PDP图(以“到地铁站距离”和“土地利用混合度”为例,论文🔶1-164)print("\n5. 绘制部分依赖图(PDP)...")plot_partial_dependence(gtwboost_ebs, data, "distance_metro", "ebs_usage", "到地铁站距离(km)", is_gtwboost=True)plot_partial_dependence(xgboost_ebs, data, "distance_metro", "ebs_usage", "到地铁站距离(km)", is_gtwboost=False)plot_partial_dependence(gtwboost_ebs, data, "land_use_mix", "ebs_usage", "土地利用混合熵", is_gtwboost=True)plot_partial_dependence(xgboost_ebs, data, "land_use_mix", "ebs_usage", "土地利用混合熵", is_gtwboost=False)# 步骤6:输出关键结论(匹配论文🔶1-133、🔶1-184)print("\n6. 核心结论(与论文对比):")print(f"- GTWBoost较传统XGBoost R²提升: {((gtwboost_ebs_metrics['R²'] - xgboost_ebs_metrics['R²'])/xgboost_ebs_metrics['R²']*100):.2f}%(论文EBS提升37.87%)")print(f"- 最优空间带宽(SN): {gtwboost_ebs.best_sn}(论文EBS最优SN=80)")print(f"- 最优时间衰减系数(DC): {gtwboost_ebs.best_dc}(论文不同时段DC不同,如高峰DC=0.2)")print("- PDP图显示:到地铁站距离增加时EBS使用下降,土地利用混合熵超0.64后EBS使用骤升(符合论文🔶1-164)")
http://www.dtcms.com/a/554271.html

相关文章:

  • 如何使用Jmeter做接口测试?
  • 网站用哪个软件做企业官网建设费用
  • 重庆网站设计找重庆最佳科技蛋糕网站源码
  • 东莞建设网官方网站小程序怎么赚钱的
  • 石家庄网站开发公司电话佛山新网站建设渠道
  • Golang多goroutine求解1000万和1亿以内的素数
  • 【开题答辩过程】以《基于协同过滤算法的彩妆商城系统的设计与实现》为例,不会开题答辩的可以进来看看
  • 一级a做爰片i免费网站横沥镇仿做网站
  • 怎么做能上谷歌网站优化营商环境心得体会
  • 学习C#调用OpenXml操作word文档的基本用法(4:Style类分析-2)
  • 河北建设厅注册中心网站首页网站头页
  • Vue3教程简介
  • Excel天气查询插件开发指南(★)
  • GO语言-->Gin 框架 HTTP 路由
  • Android EDLA项目导入mainline包后蓝牙签名报错分析解决
  • 保定网站建设找谁建设部四库一平台查询
  • 网站查询信息wordpress清空数据
  • 光伏开发小程序:快速获客,成交项目更迅速
  • 单位建设网站需要的材料wordpress无法开启多站点
  • 免得做网站东莞服装网站建设
  • 从零搭建 VisionMaster 自动上传系统
  • 微信小程序因视频播放不合规问题解决,微信小程序包含视频功能审核不通过解决方案
  • 江苏网站建设要多少钱html5做图网站
  • 企业网站建站意义建筑师必看的16部纪录片
  • BLDC直流无刷电机开环与PID闭环无扰切换
  • 泗水做网站ys178万能优化大师下载
  • 3D城市模型COLLADA数据格式详解
  • 外贸网站建设推广公司价格网站建设基础知识及专业术语
  • Go Web 编程快速入门 20 - 附录D:ORM 简介(可选,GORM)
  • 长春制作手机网站门户网站制作方法