手机网页及网站设计,搜索推广采用哪种方式计费,阿里云服务器做盗版视频网站,linux wordpress 下载文件一、引言 作者首先提出#xff1a;空间结构是非欧几里得且有方向性的#xff0c;未来的交通速度受下游交通影响大于上游交通。虽然卷积神经网络#xff08;CNN#xff09;在部分研究中用于建模空间相关性#xff0c;但其主要适用于欧几里得空间#xff08;例如二维图像空间结构是非欧几里得且有方向性的未来的交通速度受下游交通影响大于上游交通。虽然卷积神经网络CNN在部分研究中用于建模空间相关性但其主要适用于欧几里得空间例如二维图像而非更为复杂的非欧几里得图结构。此外现有的图卷积研究大多局限于无向图。 在此背景下作者将交通传感器之间的空间相关性表示为有向图上的扩散过程通过扩散卷积操作捕捉空间依赖性提出了扩散卷积递归神经网络DCRNN。
二、方法
1. 空间依赖建模 首先在空间依赖建模上使用了扩散模型Diffusion Mode。这个模型首先定义了一个马尔卡夫链。这是一个随机过程用于模拟图上信息从一个节点传播到其他节点的方式通过随机游走来捕捉节点间的空间依赖性。当马尔科夫过程经过多次迭代或多个时间步步数达到一定程度后它会逐渐达到一个稳态分布。在这个稳态分布下每个节点与其他节点的连接强度或称扩散影响力将变得稳定不再随时间变化。 关于扩散卷模型的更多知识CSDN 这位博主讲的非常好扩散模型 (Diffusion Model) 之最全详解图解-CSDN博客 说回论文。在空间依赖建模上想要用到扩散模型扩散卷积其核心思想如下 对于每个节点 i我们考虑它在不同步数 k 下从其他节点接收到的影响。对每一个步数 k我们使用正向转移矩阵的 k 次幂和反向转移矩阵的 k 次幂来表示扩散的传播过程。在步数 k 时通过 θ(k,1) 和 θ(k,2) 来控制正向和反向扩散的权重。最后将每一步的结果加和以捕捉多步扩散过程中的节点间依赖关系。 有了这个思想就不难理解论文中图信号 X 与滤波器 fθ 的扩散卷积操作定义 式中X 是一个 N×P 的矩阵X:,p 就表示第 p 个节点的所有特征值如速度。fθ 是扩散卷积的滤波器其作用是控制和调整扩散卷积的影响范围和特性类似于图卷积中的卷积核。W 是图的加权邻接矩阵。Do 是 W 的出度对角矩阵表示每个节点的出度。那么这两项相乘后的矩阵表示一个随机游走过程也就是说矩阵的每个元素表示从节点 i 到节点 j 的条件概率即在随机游走中从 i 到达 j 的概率。 那么结合这个公式作者的扩散卷积代码就很容易理解
with tf.variable_scope(scope):if self._max_diffusion_step 0: # 根据 _max_diffusion_step 控制扩散层数0 表示无扩散passelse:for support in self._supports:# 将 support稀疏邻接矩阵与 x0或更新的 x1相乘模拟信息在图上扩散。x1 tf.sparse_tensor_dense_matmul(support, x0)x self._concat(x, x1)# 将扩散结果 x1、x2 依次拼接到 x 上for k in range(2, self._max_diffusion_step 1):x2 2 * tf.sparse_tensor_dense_matmul(support, x1) - x0 # 切比雪夫多项式算法x self._concat(x, x2)x1, x0 x2, x1# 合并扩散结果(batch_size * num_nodes, input_size * num_matrices)num_matrices len(self._supports) * self._max_diffusion_step 1 # Adds for x itself.x tf.reshape(x, shape[num_matrices, self._num_nodes, input_size, batch_size])x tf.transpose(x, perm[3, 1, 2, 0]) # (batch_size, num_nodes, input_size, order)x tf.reshape(x, shape[batch_size * self._num_nodes, input_size * num_matrices])# 应用权重和偏置得到卷积输出weights tf.get_variable(weights, [input_size * num_matrices, output_size], dtypedtype,initializertf.contrib.layers.xavier_initializer())x tf.matmul(x, weights) # (batch_size * self._num_nodes, output_size)biases tf.get_variable(biases, [output_size], dtypedtype,initializertf.constant_initializer(bias_start, dtypedtype))x tf.nn.bias_add(x, biases) 先通过 utils.calculate_random_walk_matrix(adj_mx).T 计算出Do逆与 W 的乘积 support 并且转化为了稀疏矩阵以便高效运算。在上面的代码中x0、x1 代表着代表着不同时间步的特征也就是公式中的 X:,px2 是切比雪夫多项式的算法优化拉普拉斯矩阵的高次幂计算_max_diffusion_step 就是公式中的k代表扩散步数最后 weights 也就是公式中的 θk代表扩散权重。 基于上述卷积操作可以构建一个扩散卷积层增强模型的表达能力。将 P-维特征映射到 Q-维输出。那么输出矩阵XN×P经过激活函数a就转化为了输出矩阵HN×Q。 # Reshape res back to 2D: (batch_size, num_node, state_dim) - (batch_size, num_node * state_dim)
return tf.reshape(x, [batch_size, self._num_nodes * output_size])
2. 时间动态建模 在时间依赖建模中作者使用了递归神经网络RNN的变体——门控循环单元GRU。并且使用扩散卷积替换了 GRU 中的矩阵乘法。那么定义如下 上述式子中∗G 表示扩散卷积用扩散卷积去处理 Xt 和 HtΘr、Θu、ΘC 是相应的滤波器参数也就是原始 GRU 中的权重参数。那么接下来就能像 GRU 那样进行多步预测。 接下来看这部分的代码实现
with tf.variable_scope(scope or dcgru_cell): # 添加变量的作用域前缀# 1.计算更新门u和重置门rwith tf.variable_scope(gates):output_size 2 * self._num_units# We start with bias of 1.0 to not reset and not update.# 判断使用哪种方法计算更新门和重置门if self._use_gc_for_ru:fn self._gconvelse:fn self._fcvalue tf.nn.sigmoid(fn(inputs, state, output_size, bias_start1.0))# 拆分并调整重置门和更新门的形状value tf.reshape(value, (-1, self._num_nodes, output_size))r, u tf.split(valuevalue, num_or_size_splits2, axis-1)r tf.reshape(r, (-1, self._num_nodes * self._num_units))u tf.reshape(u, (-1, self._num_nodes * self._num_units))# 2.计算候选状态 cwith tf.variable_scope(candidate):c self._gconv(inputs, r * state, self._num_units)if self._activation is not None:c self._activation(c)# 3. 计算输出和新状态output new_state u * state (1 - u) * c 不管是第1步计算更新门 u 和 重置门 r 还是第2步计算候选状态都用到了扩散卷积函数 _gconv公式中的 *G 。其中偏置值不设置时默认为0激活函数不设置时默认为 tanh。 在多步预测中模型在生成每个步骤的预测时依赖前一步的输出但如果某一步的预测错误会导致后续预测受到影响从而引发错误逐步积累最终显著降低预测精度。因此作者团队为了缓解训练和测试期间输入分布不一致的问题引入了计划抽样方法Scheduled Sampling。在训练过程中计划抽样不是每次都让模型在每一步中直接使用前一步的真实观测值而是引入一个采样概率 ϵ按一定概率从真实观测值中抽样按另一概率从模型的预测结果中抽样。随着训练的进行这个采样概率逐渐从依赖真实观测值过渡到依赖预测值最终在测试阶段模型只依赖于自己的预测。也就是说采样概率 ϵ 会逐渐从1将为0。 计划抽样的代码如下
# 控制每一步解码输入是使用模型的预测结果 prev还是使用真实的标签值 labels[i]
def _loop_function(prev, i):if is_training:# Return either the models prediction or the previous ground truth in training.if use_curriculum_learning: # 使用课程学习(模仿人类学习的特点由简单到困难来学习课程)c tf.random_uniform((), minval0, maxval1.)# 基于全局步数 global_step 计算采样阈值 thresholdthreshold self._compute_sampling_threshold(global_step, cl_decay_steps)# 当随机数 c 小于 threshold 时选择 labels[i]真实值否则使用 prev预测值result tf.cond(tf.less(c, threshold), lambda: labels[i], lambda: prev)else:result labels[i]else:# Return the prediction of the model in testing.result prevreturn result
3. 代码结构 作者在 DCRNN 模型设计上分为了三个代码文件分别是 dcrnn_cell.py、dcrnn_model.py和dcrnn_supervisor.py。一般而言cell 文件通常定义的是一个神经网络中的基本计算单元或模块。而 model 文件定义了整个神经网络模型的结构它将各个 cell 组合起来实现从输入到输出的完整计算图。supervisor 文件通常负责训练和评估的流程管理它调用 model 文件中的模型进行训练和推理设置优化流程监控训练状态。 dcnn_cell.py 中主要实现了扩散卷积和 GRU 的计算。其核心也就是上面1和2部分的代码。 dcrnn_model.py 的代码主要实现以下几个功能 将 DCGRUCell 聚合为一个多层的 GRU 单元设置训练时的特殊方法例如上文的计划抽样“编码encoding”和“解码decoding” 什么是编码和解码呢它是指在序列到序列Seq2Seq模型中将输入数据转换为潜在表示编码并生成输出序列解码的过程。在普通的 RNN 中输入和输出的处理方式是逐时间步的每个时间步的输入都会产生一个对应的输出。这只适用于固定长度的输入和输出序列在不同长度的输入输出序列上表现不佳。相反 Seq2Seq 这种结构比普通的 RNN 更适合处理不同长度的输入和输出序列尤其适合于交通预测等多步预测任务。具体知识点可见这位博主的讲解Seq2Seq 模型详解_seq2seq模型-CSDN博客。 而在 DCRNNModel 类中编码器将输入数据处理成隐藏状态enc_state这个状态浓缩了输入的特征解码器以 enc_state 作为起点逐步生成未来时刻的预测值。这部分的代码在后文实验对比会提到代码如下所示
# 创建多层RNN单元
encoding_cells [cell] * num_rnn_layers # 在编码阶段将使用多个相同的RNN单元
decoding_cells [cell] * (num_rnn_layers - 1) [cell_with_projection] # 在解码的最后一层使用具有输出投影的单元以确保输出维度正确。
encoding_cells tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tupleTrue)
decoding_cells tf.contrib.rnn.MultiRNNCell(decoding_cells, state_is_tupleTrue)# 构建编码器和解码器
_, enc_state tf.contrib.rnn.static_rnn(encoding_cells, inputs, dtypetf.float32)
outputs, final_state legacy_seq2seq.rnn_decoder(labels, enc_state, decoding_cells, loop_function_loop_function) dcrnn_supervisor.py 的代码主要实现以下几个功能 初始化参数配置配置日志系统便于后续调试和复现。数据准备通过 DCRNNModel初始化训练和测试模型的对象初始化学习率变量配置优化器默认Adam优化器定义损失函数配置梯度裁剪与优化操作配置模型保存器 其中第4步是这一个python文件的关键代码。
# 4. 构建模型
scaler self._data[scaler] # 标准化
with tf.name_scope(Train): # 训练模式with tf.variable_scope(DCRNN, reuseFalse):self._train_model DCRNNModel(is_trainingTrue, scalerscaler,batch_sizeself._data_kwargs[batch_size],adj_mxadj_mx, **self._model_kwargs)with tf.name_scope(Test): # 测试模式with tf.variable_scope(DCRNN, reuseTrue):self._test_model DCRNNModel(is_trainingFalse, scalerscaler,batch_sizeself._data_kwargs[test_batch_size],adj_mxadj_mx, **self._model_kwargs)
三、相关工作 作者首先提出了以往研究的一些缺陷 本文提出的 DCRNN 与上述方法不同它将传感器网络建模为加权有向图并利用扩散卷积捕捉空间依赖关系。通过在卷积中结合双向随机游走DCRNN 能够更灵活地捕捉上游和下游的交通影响。此外DCRNN 结合序列到序列学习框架及计划抽样技术以更好地处理长期预测中的误差累积问题。
四、实验 作者使用了两个数据集实验分别是 METR-LA 数据集和 PEMS-BAY 数据集。其中70% 的数据用于训练20% 用于测试剩余 10% 用于验证。 作者分别在后文分别讨论了时间建模和空间建模的效果。 首先在空间依赖建模上选取了 DCRNN 的变体—— DCRNN-NoConv 和 DCRNN-UniConv。前者忽略空间依赖后者使用单向游走欧几里得图结构。实验对比如下 如果在空间依赖建模上不适用传播卷积而使用切比雪夫图卷积GCRNN那么结果也是显而易见的。 在时间依赖建模上作者使用了 DCNN 和 DCRNN-SEQ 来做对比。前者是静态输入的卷积神经网络而后者加入了 Seq2Seq 框架处理。而本文使用的 DCRNN 是在 DCRNN-SEQ 的基础上添加了计划抽样方法。经过实验DCRNN 的效果表现最好。 五、总结 总结这篇论文的创新点如下 使用传播模型的双向随机游走建立空间模型使用 GRU 捕捉时间动态结合了编码器-解码器架构计划抽样技术。