Spatiotemporal Multi-Graph Convolution Network for Ride-Hailing Demand Forecasting
论文链接,见这里
作者:Xu Geng, Yaguang Li, Leye Wang, Lingyu Zhang, Qiang Yang, Jieping Ye, Yan Liu
期刊:The Thirty-Third AAAI Conference on Artificial Intelligence (AAAI-19);2019年
关键字: MGCN,网约车
摘要
区域需求预测是网约车服务的一项基本任务。准确预测网约车需求,可以指导车辆调度,提高车辆利用率,减少等待时间,缓解交通拥堵。由于区域间复杂的时空依赖性,这项任务具有挑战性。现有的方法主要集中在空间相邻区域之间的欧氏相关性建模,而我们观察到可能遥远区域之间的非欧氏成对相关性也对准确预测至关重要。在本文中,我们提出了一种用于网约车需求预测的新型深度学习模型——时空多图卷积网络(ST-MGCN)。我们首先将区域间的非欧几里得成对相关性编码成多个图,然后使用多图卷积对这些相关性进行显式建模。为了利用全局上下文信息来建模时间相关性,我们进一步提出上下文门控递归神经网络,该网络通过上下文感知门控机制来增强递归神经网络,以重新加权不同的历史观测。我们在两个真实世界的大规模网约车需求数据集上评估提出的模型,并观察到与最先进的基线相比有超过10%的持续改进。
论文翻译
论文视频讲解
代码链接
代码Wang:https://github.com/underdoc-wang/ST-MGCN
MGCN?GCN
from torch import nn
import torch
# Static GCN w/ dense adj
class GCN(nn.Module):
def __init__(self, K:int, input_dim:int, hidden_dim:int, bias=True, activation=nn.ReLU):
super().__init__()
self.K = K
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.bias = bias
self.activation = activation() if activation is not None else None
self.init_params(n_supports=K)
def init_params(self, n_supports:int, b_init=0):
self.W = nn.Parameter(torch.empty(n_supports*self.input_dim, self.hidden_dim), requires_grad=True)
nn.init.xavier_normal_(self.W)
if self.bias:
self.b = nn.Parameter(torch.empty(self.hidden_dim), requires_grad=True)
nn.init.constant_(self.b, val=b_init)
def forward(self, A:torch.Tensor, x:torch.Tensor):
'''
Batch-wise graph convolution operation on given list of support adj matrices
:param A: support adj matrices - torch.Tensor (K, n_nodes, n_nodes)
:param x: graph feature/signal - torch.Tensor (batch_size, n_nodes, input_dim)
:return: hidden representation - torch.Tensor (batch_size, n_nodes, hidden_dim)
'''
assert self.K == A.shape[0]
support_list = list()
for k in range(self.K):
support = torch.einsum('ij,bjp->bip', [A[k,:,:], x])
support_list.append(support)
support_cat = torch.cat(support_list, dim=-1)
output = torch.einsum('bip,pq->biq', [support_cat, self.W])
if self.bias:
output += self.b
output = self.activation(output) if self.activation is not None else output
return output
def __repr__(self):
return self.__class__.__name__ + f'({self.K} * input {self.input_dim} -> hidden {self.hidden_dim})'