代码来源:
https://github.com/tkipf/pygcn
涉及数据集:cora
学习代码方法:
以下就是我做的对GCN代码的笔记,整理不易,大佬莫喷,嘻嘻!
GCN代码中
layers就是图卷积GraphConvolution的代码
layers中,forward即神经网络的前向传播,即上面11的内容,GCN的数学公式也是在这里应用
init 中包括对权重的处理和对偏置的处理,调用的是Parmeter()
forward部分再调用init部分
models即整个模型的整体架构,如此论文中用了两层GCN,models中就有两层;同时应用relu和dropout。调用layers中的图卷积代码,同样forward调用init。
Q: 为什么第二层就没有经过relu函数了?
(可能源代码中有这个,但是我没有看)
train即添加参数,调用下载数据集,定义训练和测试函数等工作
添加参数使用的是add_argument
下载测试集的时候是调用的utils的函数
【训练函数即先对模型参数进行设置(如设置为0),然后调用models,然后models再调用layers
(Q:GCN参数列表是nn.Module.在train文件中却是通过以下参数调用的GCN)output = model(features, adj)
然后计算loss
再计算准确率,调用了utils中的准确率
再backward
再optimizer.step()】
【测试函数代码,测试函数的时候就不需要反向传播了
也是先去模型(即forward)
然后计算loss
然后计算准确率
然后得出结果】
utils即下载数据和对数据进行处理(如归一化)
下载数据以及对下载的数据进行处理(如将特征与标签所在的列分别取出来)的时候调用了归一化函数
调用关系如下图所示:
接下来的内容就是我在读代码过程中遇到的一些问题:涵盖各个大佬的笔记,希望可以帮到看文章的你:
- {}就是将后面的.format(dataset)对应的参数代入
- cora数据集的cora.content 节点编号 节点特征 文章分类
- cora数据集 cora.cite表示前面这个节点和后面的节点是有一条边连接在一起的
即35 与286500是有一条边连接在一起 - cora数据集的特征,中间代表的词汇表中的单词是否存在,存在就是1,不存在就是0。
- 关于utils代码中对数据进行处理,以下代码段的解释:
# build symmetric adjacency matrix,计算转置矩阵,将有向图转化为无向图
adj = adj + adj.T.multiply(adj.T > adj) - adj.multiply(adj.T > adj)
涉及到的参考链接
import torch
import torch.nn.functional as F
import numpy as np
import scipy.sparse as sp
# sp.coo_matrix((data, (row, col)), shape
#即1在(1,3)第一行第三列的位置;6在第二行第4列的位置
adj = sp.coo_matrix(((1,1,1),([1,2,4],[3,4,2])),shape=(5,5),dtype = np.float32)
print(adj.A)
得到:
之前(2,4)和(4,2)位置对称,都有值,而(1,3)的对称位置(3,1)没有值,现在也有值了,即将有向图转为无向图。
6. Parameter()与register_parameter()都是将一个不可训练的类型Tensor转换成可以训练的类型parameter,并将这个parameter绑定到这个module里面,相当于变成了模型的一部分,成为了模型中可以根据训练进行变化的参数。
7. Adam优化器(Adam是自适应矩估计)—随机优化算法
在实践中,Adam被推荐为使用的默认算法,并且通常比RMSProp稍微好一点。然而,作为一种替代方法,SGD+Nesterov Momentum也值得尝试。
优化器的任务就是在每一个epoch中计算损失函数的梯度,进而更新参数。
8. optimizer.zero_grad()–>optim.Adam()–>model.parameters()[多见于优化器的初始化,其源码中有一个生成器,详见链接;下图来自optimizer.zero_grad()处链接]
9. optimizer.step()需要放在每一个batch训练中,而不是epoch训练中
10.torch.mm()是矩阵相乘
在train()中代码中那一行即紫色勾选框
蓝色勾选框即完成上面公式括号内的运算
11. 做log_softmax而不是crossEntropyLoss的原因:
p.s. 这里是视频作者给出的解释,但是我有点不太懂
12. 在train函数中的model.train()和test函数中的model.eval()作用
如果模型中有BN层(Batch Normalization)和 Dropout,需要在训练时添加model.train()。model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,model.train()是随机取一部分网络连接来训练更新参数。
如果模型中有BN层(Batch Normalization)和Dropout,在测试时添加model.eval()。model.eval()是保证BN层能够用全部训练数据的均值和方差,即测试过程中要保证BN层的均值和方差不变。对于Dropout,model.eval()是利用到了所有网络连接,即不进行随机舍弃神经元。
训练完train样本后,生成的模型model要用来测试样本。在model(test)之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有BN层和Dropout所带来的的性质。
验证集也是eval。
13. sp.csr_matrix就是按照列来压缩
以上参考资料大部分以超链接的形式引用
另外还参考了B站视频:https://www.bilibili.com/video/BV1K5411H7EQ?p=14