早晚高峰堵在环路上的时候很多人都会想导航软件是怎么知道前面三公里要堵二十分钟的这背后是城市计算里一个经典问题——交通流量预测。它的输入是遍布城市的线圈、卡口、网约车 GPS 产生的时空数据输出是未来几十分钟到几小时内每个路段的车速、流量和拥堵概率。看似只是猜车多不多做起来却牵扯到时空建模、图结构学习和大量工程妥协。交通流量预测难在哪交通数据有三个让常规时序模型头疼的特性。第一是空间依赖。上游路段堵车会在十几分钟后传导到下游而路网不是规则的网格是一个带方向的图。欧氏距离近的两个点在路网里可能隔着一条河完全不相干。第二是时间上的多周期性工作日有早晚高峰周末曲线完全不同节假日又会整体漂移再加一场暴雨或一场演唱会规律立刻被打乱。第三是数据质量问题。线圈检测器常年有一定比例的故障率缺失值不是随机分布的往往集中在暴雨、严寒这些恰恰最需要准确预测的场景里。理解这三点就理解了为什么单纯的 ARIMA 或 LSTM 在实际路网里表现平平它们把每个路段当成孤立序列丢掉了图结构这一半信息。主流模型路线对比这些年交通预测的模型演进大致是从统计方法到深度时序再到时空图网络。下面是一个简化的对比| 模型路线 | 代表方法 | 空间建模 | 优点 | 局限 | | --- | --- | --- | --- | --- | | 统计方法 | ARIMA、Kalman Filter | 无 | 可解释、无需训练数据量大 | 无法处理非线性和路网传导 | | 纯时序深度模型 | LSTM、TCN、Informer | 无 | 拟合非线性周期强 | 忽略空间依赖跨路段泛化差 | | 时空图网络 | DCRNN、ST-GCN、Graph WaveNet | 图卷积/扩散卷积 | 显式建模路网拓扑精度领先 | 训练成本高图结构需人工先验 | | 大模型/基座路线 | 时序基础模型微调 | 隐式 | 迁移能力强、冷启动友好 | 可解释性弱落地案例尚少 |目前工业界落地最多的还是时空图网络。思路很直接把路段或检测器看作节点道路连接关系看作边用图卷积聚合邻居信息再叠一层 GRU 或 TCN 捕捉时间演化。DCRNN 用扩散卷积模拟车流的上下游传播Graph WaveNet 则进一步让模型自己学习邻接矩阵避免人工定义图结构带来的偏差。一个最小可跑的时空模型示例下面用 PyTorch 写一个简化版图卷积 GRU 的预测单元帮助理解数据流动的形状。真实项目里可以直接用 DCRNN、STSGCN 等开源实现但核心结构就是这两块的组合import torch import torch.nn as nn class GraphConv(nn.Module): 简化的图卷积AXWA 为归一化邻接矩阵 def __init__(self, in_dim, out_dim): super().__init__() self.linear nn.Linear(in_dim, out_dim) def forward(self, x, adj): # x: (batch, num_nodes, in_dim), adj: (num_nodes, num_nodes) support torch.einsum(ij,bjd-bid, adj, x) return self.linear(support) class STBlock(nn.Module): def __init__(self, hidden_dim): super().__init__() self.gconv GraphConv(hidden_dim, hidden_dim) self.gru nn.GRU(hidden_dim, hidden_dim, batch_firstTrue) def forward(self, x, adj): # x: (batch, seq_len, num_nodes, hidden_dim) b, t, n, d x.shape out [] for step in range(t): out.append(torch.relu(self.gconv(x[:, step], adj))) g torch.stack(out, dim1) # (b, t, n, d) g g.permute(0, 2, 1, 3).reshape(b * n, t, d) h, _ self.gru(g) # 时间维建模 return h[:, -1].reshape(b, n, d) # 取最后时刻隐状态这里的要点不在代码本身而在于数据组织方式输入永远是四维的批次 × 时间 × 节点 × 特征任何一步 reshape 出错都会静默地产出一个能跑但全错的模型。调试时空模型的第一课就是打印每一步的张量形状。工程落地绕不开的几个坑模型精度只是入场券真正上线时会碰到一堆论文里不提的问题。缺失值处理要前置。检测器掉线是常态简单的线性插值在早高峰会引入严重偏差。实践里常用历史同时段均值 相邻路段回归双层填补并把缺失掩码作为特征喂给模型让它自己学会这条数据不可靠。节假日和事件要单独建模。春节、国庆的流量模式与平日完全不同硬塞进一个模型只会互相拖累。常见做法是日历特征外加上下文门控让模型在不同 regime间切换大型活动则靠人工维护的事件日历做显式修正。评估指标别只看 MAPE。交通流里低流量时段凌晨的 MAPE 会爆表把整体指标拉得很难看。行业里更常用 MAE RMSE 分段看高峰段单独评估因为那才是调度决策真正关心的区间。冷启动比精度更重要。新开通的路段没有历史数据图网络的迁移能力有限。一个务
AI城市计算:交通流量预测与智慧城市实践
早晚高峰堵在环路上的时候很多人都会想导航软件是怎么知道前面三公里要堵二十分钟的这背后是城市计算里一个经典问题——交通流量预测。它的输入是遍布城市的线圈、卡口、网约车 GPS 产生的时空数据输出是未来几十分钟到几小时内每个路段的车速、流量和拥堵概率。看似只是猜车多不多做起来却牵扯到时空建模、图结构学习和大量工程妥协。交通流量预测难在哪交通数据有三个让常规时序模型头疼的特性。第一是空间依赖。上游路段堵车会在十几分钟后传导到下游而路网不是规则的网格是一个带方向的图。欧氏距离近的两个点在路网里可能隔着一条河完全不相干。第二是时间上的多周期性工作日有早晚高峰周末曲线完全不同节假日又会整体漂移再加一场暴雨或一场演唱会规律立刻被打乱。第三是数据质量问题。线圈检测器常年有一定比例的故障率缺失值不是随机分布的往往集中在暴雨、严寒这些恰恰最需要准确预测的场景里。理解这三点就理解了为什么单纯的 ARIMA 或 LSTM 在实际路网里表现平平它们把每个路段当成孤立序列丢掉了图结构这一半信息。主流模型路线对比这些年交通预测的模型演进大致是从统计方法到深度时序再到时空图网络。下面是一个简化的对比| 模型路线 | 代表方法 | 空间建模 | 优点 | 局限 | | --- | --- | --- | --- | --- | | 统计方法 | ARIMA、Kalman Filter | 无 | 可解释、无需训练数据量大 | 无法处理非线性和路网传导 | | 纯时序深度模型 | LSTM、TCN、Informer | 无 | 拟合非线性周期强 | 忽略空间依赖跨路段泛化差 | | 时空图网络 | DCRNN、ST-GCN、Graph WaveNet | 图卷积/扩散卷积 | 显式建模路网拓扑精度领先 | 训练成本高图结构需人工先验 | | 大模型/基座路线 | 时序基础模型微调 | 隐式 | 迁移能力强、冷启动友好 | 可解释性弱落地案例尚少 |目前工业界落地最多的还是时空图网络。思路很直接把路段或检测器看作节点道路连接关系看作边用图卷积聚合邻居信息再叠一层 GRU 或 TCN 捕捉时间演化。DCRNN 用扩散卷积模拟车流的上下游传播Graph WaveNet 则进一步让模型自己学习邻接矩阵避免人工定义图结构带来的偏差。一个最小可跑的时空模型示例下面用 PyTorch 写一个简化版图卷积 GRU 的预测单元帮助理解数据流动的形状。真实项目里可以直接用 DCRNN、STSGCN 等开源实现但核心结构就是这两块的组合import torch import torch.nn as nn class GraphConv(nn.Module): 简化的图卷积AXWA 为归一化邻接矩阵 def __init__(self, in_dim, out_dim): super().__init__() self.linear nn.Linear(in_dim, out_dim) def forward(self, x, adj): # x: (batch, num_nodes, in_dim), adj: (num_nodes, num_nodes) support torch.einsum(ij,bjd-bid, adj, x) return self.linear(support) class STBlock(nn.Module): def __init__(self, hidden_dim): super().__init__() self.gconv GraphConv(hidden_dim, hidden_dim) self.gru nn.GRU(hidden_dim, hidden_dim, batch_firstTrue) def forward(self, x, adj): # x: (batch, seq_len, num_nodes, hidden_dim) b, t, n, d x.shape out [] for step in range(t): out.append(torch.relu(self.gconv(x[:, step], adj))) g torch.stack(out, dim1) # (b, t, n, d) g g.permute(0, 2, 1, 3).reshape(b * n, t, d) h, _ self.gru(g) # 时间维建模 return h[:, -1].reshape(b, n, d) # 取最后时刻隐状态这里的要点不在代码本身而在于数据组织方式输入永远是四维的批次 × 时间 × 节点 × 特征任何一步 reshape 出错都会静默地产出一个能跑但全错的模型。调试时空模型的第一课就是打印每一步的张量形状。工程落地绕不开的几个坑模型精度只是入场券真正上线时会碰到一堆论文里不提的问题。缺失值处理要前置。检测器掉线是常态简单的线性插值在早高峰会引入严重偏差。实践里常用历史同时段均值 相邻路段回归双层填补并把缺失掩码作为特征喂给模型让它自己学会这条数据不可靠。节假日和事件要单独建模。春节、国庆的流量模式与平日完全不同硬塞进一个模型只会互相拖累。常见做法是日历特征外加上下文门控让模型在不同 regime间切换大型活动则靠人工维护的事件日历做显式修正。评估指标别只看 MAPE。交通流里低流量时段凌晨的 MAPE 会爆表把整体指标拉得很难看。行业里更常用 MAE RMSE 分段看高峰段单独评估因为那才是调度决策真正关心的区间。冷启动比精度更重要。新开通的路段没有历史数据图网络的迁移能力有限。一个务