Li G, Muller M, Thabet A, et al. Deepgcns: Can gcns go as deep as cnns?[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2019: 9267-9276.
Li G, Xiong C, Thabet A, et al. Deepergcn: All you need to train deeper gcns[J]. arXiv preprint arXiv:2006.07739, 2020.
这一系列主要是这两篇文章,由KAUST提出,给深度GCN的发展提供了一定的思路和启发。两篇文章算是姊妹篇吧,第一篇着重于分析理论,第二篇更注重在OGB数据集上将模型落到实处。在毕设的model当中也有借鉴softmax_aggr的聚合思路,让我受益匪浅。
官网:
其实和GCNII想解决的问题一样,都是模型深度的问题。GCNII通过初始剩余连接和恒等映射,成功缓解了过平滑的问题,并且在ogbn-arxiv数据集上取得了不错的效果。那么,DeeperGCN有什么其他的解决思路吗?
加深GCN会出现梯度消失、过平滑、过拟合等一系列问题。主要原因还是梯度消失,它间接导致了反向传播时的过平滑问题。如何去解决这一问题,DeeperGCN提出了自己的解决方法。
思路一: 借鉴CNN中的解决方法,并将其推广到GCN中。(第一篇paper)
思路二: 对GCN中的消息传递框架做出调整,以适应深层模型的训练。(第二篇paper)
为了使GCN更深,很多工作都在进行研究,但由于都是应用于小数据集上的,所以在OGB上并不好用。
在CNN当中,剩余连接、密集连接和扩张卷积可以缓解梯度消失的问题,例如运用了剩余连接方法的ResNet层数就可以很深。
很简单,就是将当前层的结果和上一层的结果相加,以保留前一层的计算结果。当然,也可以按照比例系数进行加权、或可学习的权重等,可以衍生出一系列剩余连接的变体。
通过实验和分析,可以明确的是,剩余连接对于深层GCN是至关重要的,它可以使模型有更稳定的梯度。因此,很多模型都会借鉴剩余连接的思路,为自己的模型设计出各式各样的剩余连接变体,以提升模型的性能。在有剩余连接的情况下,模型更深,往往可以提高性能。
把当前层和之前的所有层进行拼接(注意,是concat!),因此节点特征维度随着层数的增加而增加。
通过上面的描述和实验,一个显而易见的问题就是内存开销太大(毕竟是concat),这是一个很大的问题。此外,有paper表明,不同特征维度的层之间过多的信息交互不利于模型性能的提升,因此,综合其表现,密集连接并没有被广泛应用于深层GCN的训练当中。
首先根据距离为所有邻居(包括1-hop、2-hop…k-hop)节点由近到远编号,然后每取一个邻居就跳过d个邻居,直到取完固定数量的邻居为止。聚合时使用采样得到的邻居,其他都和GCN一样,这个过程被称为扩张聚合。
其实相当于扩大了节点的感知域,能够聚合到更高阶邻居的信息。但是实验表明,扩展聚合的影响很小,在没有剩余连接的时候还会阻碍收敛,并且还会徒增计算成本,因此此方案也被pass掉了。
总结: 经过第一篇paper的一顿分析,只有剩余连接的方案被保留沿用下来了,在第二篇paper中也用到了剩余连接。
第二篇paper延续了第一篇的剩余连接,并且将方案进行落地(DeeperGCN),感觉比第一篇更有参考价值。
为了满足置换不变性,之前的聚合函数大多采用了3中简单的聚合器:mean、max、sum。为了超越这几种聚合器的表现能力,本文提出了两种mean-max聚合函数。
当然,在特征送入聚合函数之前,首先进行F.relu(h_u) + eps
的操作。
之后的实验也证明了广义聚合函数的有效性。
其实就是调换了原先各模块的顺序,将层归一化和激活操作提到GConv层的前面。
PyG官方文档:DeepGCNLayer
实验证明了预激活版本的有效性。
本来剩余连接Res阶段操作是将当前层的表示和前一层的表示直接求和的,现在加入消息规范操作后,相当于是给了一个系数,按照比例系数进行求和(而不是直接相加)。
h v ′ = M L P ( h v + s ⋅ ∥ h v ∥ 2 ⋅ m v ∥ m v ∥ 2 ) \mathbf{h}_v^{\prime} = \mathrm{MLP} \left( \mathbf{h}_{v} + s \cdot {\| \mathbf{h}_v \|}_2 \cdot \frac{\mathbf{m}_{v}}{{\|\mathbf{m}_v\|}_2} \right) hv′=MLP(hv+s⋅∥hv∥2⋅∥mv∥2mv)
其中s是可学习的扩展因子。
PyG官方文档:MessageNorm
实验也证明MsgNorm对于训练深层GCN是有效的。
通过上述的一些改进方案,我们得到了一种新的GConv层——GENConv。
PyG官方文档:GENConv
h i ′ = M L P ( h i + A G G ( { R e L U ( h j + e j i ) + ϵ : j ∈ N ( i ) } ) ) \mathbf{ h}_i^{\prime} = \mathrm{MLP} \left( \mathbf{h}_i + \mathrm{AGG} \left( \left\{ \mathrm{ReLU} \left( \mathbf{h}_j + \mathbf{e_{ji}} \right) +\epsilon : j \in \mathcal{N}(i) \right\} \right) \right) hi′=MLP(hi+AGG({ReLU(hj+eji)+ϵ:j∈N(i)}))
结果就不再赘述了。
第一篇paper实验部分是点云实验,对我来说没有参考价值。第二篇paper是在OGB数据集上的实验,特别是ogbn-arxiv,对我来说有一些参考价值。
通过实验,作者发现,添加剩余连接的预激活版本、广义聚合函数、消息规范化对训练DeeperGCN都有很好的帮助。并且,在DyResGCN版本中, β \beta β、p、s等都是可学习的参数,这也使得模型有了自适应的聚合器,进一步提升了模型的性能。
DeeperGCN系列文章为我梳理了思路,里面的很多方法都值得思考和借鉴。同时,由于深层GCN也会占用大量的GPU内存资源,所以效率问题也是今后需要考虑的一个方向。