系列教程GNN-algorithms之三:《将图卷积简化进行到底—SGC》

2020 年 8 月 5 日 专知

【导读】SGC对GCN进行了简化,通过反复消除GCN层之间的非线性变换并将得到的函数折叠成一个线性变换来减少GCN的额外复杂度。实验结果表明,这些简化操作并不会对许多下游应用的准确性产生负面影响。本文将结合公式推导手把手教大家构建基于Tensorflow的SGC模型。


系列教程《GNN-algorithms》


本文为系列教程《GNN-algorithms》中的内容,该系列教程不仅会深入介绍GNN的理论基础,还结合了TensorFlow GNN框架tf_geometric对各种GNN模型(GCN、GAT、GIN、SAGPool等)的实现进行了详细地介绍。本系列教程作者王有泽(https://github.com/wangyouze)也是tf_geometric框架的贡献者之一。


系列教程《GNN-algorithms》Github链接:

  • https://github.com/wangyouze/GNN-algorithms


TensorFlow GNN框架tf_geometric的Github链接:

  • https://github.com/CrawlScript/tf_geometric


前序讲解:

系列教程GNN-algorithms之一:《图卷积网络(GCN)的前世今生》

系列教程GNN-algorithms之二:《切比雪夫显神威—ChebyNet》


前言


GCN作为一种经典的图神经网络模型,已经成为了诸多新手入门图神经网络的必学模型,而近些年对于GCN的各种魔改也层出不穷。本着爱屋及乌的目的,本教程将教你如何用Tensorflow构建GCN的变体SGC模型进行节点分类任务。完整的代码可在Github中下载:

https://github.com/CrawlScript/tf_geometric/blob/master/demo/demo_sgc.py


SGC模型简介


SGC是GCN的变体之一,全称Simplifying Graph Convolutional Networks,论文发表在ICML2019上。相比于GCN,SGC通过消除GCN层之间的非线性,将非线性的GCN转变为一个简单的线性模型,减小了模型复杂度,在很多任务上比GCN以及其他GNN模型更加高效。

下面我们对GCN与SGC在节点分类任务上的异同点进行对比:

  • GCN做节点分类任务时:

         1. 对邻接矩阵进行归一化并且添加自环:


          2. 对输入的节点特征进行平滑处理:


           3. 对接点特征进行非线性转换


        所以对于节点分类任务,一个K层的GCN可以表示为


  • SGC移除了GCN每层之间的激活函数,将原先的非线性变换简化为线性变换,因此SGC在做节点分类任务时:

            1. 对邻接矩阵进行归一化并且添加自环

          2. 对输入的节点特征进行平滑处理:

            3. 对节点特征进行线性转换

    所以对于节点分类任务,一个K层的SGC可以表示为:

    简写为:

SGC中的可以提前计算,大大减少了计算量。

通过以上的对比,我们可以清晰的认识到二者之间的异同点,下面我们将基于tf_geometric实现SGC模型(SGC已经集成到GNN库tf_geometric中)。

教程中完整的代码链接:

  • demo_sgc.py:https://github.com/CrawlScript/tf_geometric/blob/master/demo/demo_sgc.py

  • 论文地址:https://arxiv.org/pdf/1902.07153.pdf

教程目录


  • 开发环境

  • SGC 的实现

  • 模型构建

  • SGC训练

  • SGC评估

开发环境


  • 操作系统: Windows / Linux / Mac OS

  • Python 版本: >= 3.5

  • 依赖包:

    • tf_geometric(一个基于Tensorflow的GNN库)

根据你的环境(是否已安装TensorFlow、是否需要GPU)从下面选择一条安装命令即可一键安装所有Python依赖:

	pip install -U tf_geometric # 这会使用你自带的TensorFlow,注意你需要tensorflow/tensorflow-gpu >= 1.14.0 or >= 2.0.0b1

pip install -U tf_geometric[tf1-cpu] # 这会自动安装TensorFlow 1.x CPU版

pip install -U tf_geometric[tf1-gpu] # 这会自动安装TensorFlow 1.x GPU版

pip install -U tf_geometric[tf2-cpu] # 这会自动安装TensorFlow 2.x CPU版

pip install -U tf_geometric[tf2-gpu] # 这会自动安装TensorFlow 2.x GPU版

教程使用的核心库是tf_geometric,一个基于TensorFlow的GNN库。tf_geometric的详细教程可以在其Github主页上查询:

  • https://github.com/CrawlScript/tf_geometric


SGC的实现


对图的邻接矩阵添加自环,进行对称归一化处理:

     updated_edge_index, normed_edge_weight = gcn_norm_edge(edge_index, x.shape[0], edge_weight,renorm, improved, cache)

计算,扩大模型的感受野。aggregator_neighbor聚合一阶邻居节点信息,迭代聚合K次,相当于聚合了距离中心节点k-hop的邻域信息。

     h = x
for _ in range(K):
h = aggregate_neighbors(
h,
updated_edge_index,
normed_edge_weight,
gcn_mapper,
sum_reducer,
identity_updater
)

对上面的聚合结果进行线性变换,即计算:

然后返回计算结果

h = h @ kernel

if bias is not None:
h += bias
return h

以上我们实现了SGC中的

部分,现在我们只需要在模型的最后一层的输出上添加softmax激活函数(为了获得概率输出)就可以进行节点分类了。

模型构建


  • 导入相关库

    本教程使用的核心库是tf_geometric,我们用它来进行图数据导入、图数据预处理及图神经网络构建。SGC的具体实现已经在上面详细介绍,另外我们后面会使用keras.metrics.Accuracy评估模型性能。

    # coding=utf-8import osos.environ["CUDA_VISIBLE_DEVICES"] = "0"import tensorflow as tffrom tensorflow import kerasfrom tf_geometric.layers.conv.sgc import SGCfrom tf_geometric.datasets.cora import CoraDataset
  • 使用tf_geometric自带的图结构数据接口加载Cora数据集:

    graph, (train_index, valid_index, test_index) = CoraDataset().load_data()
  • 定义模型,这里我们只聚合2阶邻域内的信息。

    model = SGC(num_classes, k=2)


SGC训练 


模型的训练与其他基于Tensorflow框架的模型训练基本一致,主要步骤有定义优化器,计算误差与梯度,反向传播等。SGC模型K阶的计算结果由softmax映射到(0,1)直接进行多分类任务。在每一个step结束的时候,我们分别计算模型在验证集和测试集上的准确率。

optimizer = tf.keras.optimizers.Adam(learning_rate=0.2)
for step in range(1,101):
with tf.GradientTape() as tape:
logits = model([graph.x, graph.edge_index, graph.edge_weight], cache=graph.cache)
logits = tf.nn.log_softmax(logits,axis=1)
loss = compute_loss(logits, train_index, tape.watched_variables())

vars = tape.watched_variables()
grads = tape.gradient(loss, vars)
optimizer.apply_gradients(zip(grads, vars))

valid_acc = evaluate(valid_index)
test_acc = evaluate(test_index)

print("step = {}\tloss = {}\tvalid_acc = {}\ttest_acc = {}".format(step, loss, valid_acc, test_acc))
  • 用交叉熵损失函数计算模型损失。注意在加载Cora数据集的时候,返回值是整个图数据以及相应的train_mask,valid_mask,test_mask。SGC在训练的时候的输入整个Graph,在计算损失的时候通过train_mask来计算模型在训练集上的迭代损失。因此,此时传入的mask_index是train_index。由于是多分类任务,需要将节点的标签转换为one-hot向量以便于模型输出的结果维度对应。由于图神经模型在小数据集上很容易就会疯狂拟合数据,所以这里用L2正则化缓解过拟合。

    def compute_loss(logits, mask_index, vars):
    masked_logits = tf.gather(logits, mask_index)
    masked_labels = tf.gather(graph.y, mask_index)

    losses = tf.nn.softmax_cross_entropy_with_logits(
    logits=masked_logits,
    labels=tf.one_hot(masked_labels, depth=num_classes)
    )

    kernel_vals = [var for var in vars if "kernel" in var.name]
    l2_losses = [tf.nn.l2_loss(kernel_var) for kernel_var in kernel_vals]

    return tf.reduce_mean(losses) + tf.add_n(l2_losses) * 5e-5


SGC评估


在评估模型性能的时候我们只需传入valid_mask或者test_mask,通过tf.gather函数就可以拿出验证集或测试集在模型上的预测结果与真实标签,用keras自带的keras.metrics.Accuracy计算准确率。

def evaluate(mask):
logits = forward(graph)
logits = tf.nn.log_softmax(logits, axis=1)
masked_logits = tf.gather(logits, mask)
masked_labels = tf.gather(graph.y, mask)

y_pred = tf.argmax(masked_logits, axis=-1, output_type=tf.int32)
accuracy_m = keras.metrics.Accuracy()
accuracy_m.update_state(masked_labels, y_pred)
return accuracy_m.result().numpy()


运行结果


sgc在100轮训练后在测试集上的准确率最高为0.81

step = 1	loss = 1.9458770751953125	valid_acc = 0.5120000243186951	test_acc = 0.5389999747276306
step = 2 loss = 1.8324840068817139 valid_acc = 0.722000002861023 test_acc = 0.7350000143051147
step = 3 loss = 1.7052000761032104 valid_acc = 0.4740000069141388 test_acc = 0.4729999899864197
step = 4 loss = 1.6184687614440918 valid_acc = 0.5580000281333923 test_acc = 0.5360000133514404
...
step = 97 loss = 0.9681359529495239 valid_acc = 0.7919999957084656 test_acc = 0.8130000233650208
step = 98 loss = 0.9678354263305664 valid_acc = 0.7919999957084656 test_acc = 0.8100000023841858
step = 99 loss = 0.9675441384315491 valid_acc = 0.7919999957084656 test_acc = 0.8100000023841858
step = 100 loss = 0.967261791229248 valid_acc = 0.7919999957084656 test_acc = 0.8100000023841858


完整代码


教程中的完整代码链接:

  • demo_sgc.py:https://github.com/CrawlScript/tf_geometric/blob/master/demo/demo_sgc.py


本教程(属于系列教程《GNN-algorithms》)Github链接:

  • https://github.com/wangyouze/GNN-algorithms


专知便捷查看

便捷下载,请关注专知公众号(点击上方蓝色专知关注)

  • 后台回复“SGC” 可以获取《《将图卷积简化进行到底—SGC》》专知下载链接索引


专 · 知
专知,专业可信的人工智能知识分发,让认知协作更快更好!欢迎注册登录专知www.zhuanzhi.ai,获取5000+AI主题干货知识资料!
欢迎微信扫一扫加入专知人工智能知识星球群,获取最新AI专业干货知识教程视频资料和与专家交流咨询
点击“阅读原文”,了解使用专知,查看5000+AI主题知识资料
登录查看更多
10

相关内容

系列教程GNN-algorithms之七:《图同构网络—GIN》
专知会员服务
47+阅读 · 2020年8月9日
系列教程GNN-algorithms之六:《多核卷积拓扑图—TAGCN》
专知会员服务
49+阅读 · 2020年8月8日
一份简单《图神经网络》教程,28页ppt
专知会员服务
124+阅读 · 2020年8月2日
【GNN】图神经网络入门之GRN图循环网络
深度学习自然语言处理
17+阅读 · 2020年5月9日
图神经网络三剑客:GCN、GAT与GraphSAGE
PaperWeekly
65+阅读 · 2020年2月27日
一文读懂图卷积GCN
计算机视觉life
21+阅读 · 2019年12月21日
GraphSAGE: GCN落地必读论文
AI100
29+阅读 · 2019年8月15日
Github热门图深度学习(GraphDL)源码与框架
新智元
21+阅读 · 2019年3月19日
图分类:结合胶囊网络Capsule和图卷积GCN(附代码)
中国人工智能学会
36+阅读 · 2019年2月26日
Arxiv
19+阅读 · 2020年7月13日
Arxiv
20+阅读 · 2019年11月23日
Geometric Graph Convolutional Neural Networks
Arxiv
10+阅读 · 2019年9月11日
Arxiv
24+阅读 · 2018年10月24日
Arxiv
3+阅读 · 2018年2月11日
VIP会员
相关资讯
【GNN】图神经网络入门之GRN图循环网络
深度学习自然语言处理
17+阅读 · 2020年5月9日
图神经网络三剑客:GCN、GAT与GraphSAGE
PaperWeekly
65+阅读 · 2020年2月27日
一文读懂图卷积GCN
计算机视觉life
21+阅读 · 2019年12月21日
GraphSAGE: GCN落地必读论文
AI100
29+阅读 · 2019年8月15日
Github热门图深度学习(GraphDL)源码与框架
新智元
21+阅读 · 2019年3月19日
图分类:结合胶囊网络Capsule和图卷积GCN(附代码)
中国人工智能学会
36+阅读 · 2019年2月26日
Top
微信扫码咨询专知VIP会员