前篇:
【AM-GCN】代码解读之初了解(一)
【AM-GCN】代码解读之主程序(二)
【AM-GCN】代码解读之utlis(三)
【AM-GCN】论文解读
该篇讲解具有前后联系的:layers.py
和models.py
壹、文件 layers.py
一、导入库
import math
import torch
from torch.nn.parameter import Parameter
from torch.nn.modules.module import Module
二、GCN卷积层
class GraphConvolution(Module):
def __init__(self, in_features, out_features, bias=True):
super(GraphConvolution, self).__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(torch.FloatTensor(in_features, out_features))
if bias:
self.bias = Parameter(torch.FloatTensor(out_features))
else:
self.register_parameter('bias', None)
self.reset_parameters()
def reset_parameters(self):
stdv = 1. / math.sqrt(self.weight.size(1))
self.weight.data.uniform_(-stdv, stdv)
if self.bias is not None:
self.bias.data.uniform_(-stdv, stdv)
def forward(self, input, adj):
support = torch.mm(input, self.weight)
output = torch.spmm(adj, support)
if self.bias is not None:
return output + self.bias
else:
return output
def __repr__(self):
return self.__class__.__name__ + ' (' \
+ str(self.in_features) + ' -> ' \
+ str(self.out_features) + ')'
这是所有图卷积层的基础框架,大同小异。
如果不明白的话,可以查看链接 《torch搭建GCN的详细介绍》
根据我个人的修改经验,在自己搭建框架的时候只需要注意两点:
- reset_parameters()中初始化的方法(不了解可查看超链接):
- self.weight.data.uniform_(-stdv, stdv)[原文]
- init.kaiming_uniform_(self.weight)[具体见下]
def reset_parameters(self):
"""
数据初始化的方法
"""
init.kaiming_uniform_(self.weight)
if self.use_bias:
init.zeros_(self.bias)
- 矩阵的乘法(非点乘,可点开查看超链接)。有的A是稀疏的,有的不是,有的是二维乘法有的是多维乘法。根据不同情况,选择合适的函数。
- torch.mm (仅试用于二维矩阵)
- torch.matmul (多维矩阵乘法)
- torch.spmm 稀疏矩阵乘法
- torch.sparse.mm 稀疏矩阵乘法
贰、文件models.py
一、导入库
import torch.nn as nn #torch中定义好的神经网络层
import torch.nn.functional as F #torch中自带的一些函数
import torch
from layers import GraphConvolution #导入从前面定义好的GCN层
二、搭建GCN模块
class GCN(nn.Module):
def __init__(self, nfeat, nhid, out, dropout):
super(GCN, self).__init__()
self.gc1 = GraphConvolution(nfeat, nhid)
self.gc2 = GraphConvolution(nhid, out)
self.dropout = dropout
def forward(self, x, adj):
x = F.relu(self.gc1(x, adj))
x = F.dropout(x, self.dropout, training = self.training)
x = self.gc2(x, adj)
return x
1.区别:对GCNlayer和GCNmodule不理解的看过来!
GCNlayer—对应—单层神经网络
GCNmodule—对应—多层神经网络
- F.dropout()函数,不理解的可以查看对用链接
三、注意力机制
class Attention(nn.Module):
def __init__(self, in_size, hidden_size=16):
super(Attention, self).__init__()
self.project = nn.Sequential(
nn.Linear(in_size, hidden_size),
nn.Tanh(),
nn.Linear(hidden_size, 1, bias=False)
)
def forward(self, z):
w = self.project(z)
beta = torch.softmax(w, dim=1)
return (beta * z).sum(1), beta
函数解释:
- nn.Sequential(),是一个Model搭建的容器,按照添加的顺序运行。如上代码中,添加的顺序为:nn.Linear, nn.Tanh, nn.Linear
假设没有nn.Sequential这个容器。可以等价于如下。当Model中的神经层很多的时候比较麻烦。而nn.Sequential就可以更方便的书写了。
def __init__(self, in_size, hidden_size=16):
self.l1 = nn.Linear(in_size, hidden_size)
self.l2 =nn.Linear(hidden_size, 1, bias=False)
def forward(self, z):
h1 = self.l1(z)
h2 = nn.Tanh(h1)
w = self.l2(h2)
可参考:torch.nn.Sequential()讲解,或者,torch.nn.Sequential()搭建神经网络
- torch.softmax()
sogtmax公式解析
函数解析
代码演示
用途:用于多分类任务进行分类的。
特点:非线性性,和为1.
- 作用:【见论文解读】文章中有三个嵌入:feature graph 的嵌入,topology graph 的嵌入以及 common 嵌入。对于这三个嵌入进行“资源分配”的。具体可以查看《注意力机制》
四、AM-GCN结构
class SFGCN(nn.Module):
def __init__(self, nfeat, nclass, nhid1, nhid2, n, dropout):
super(SFGCN, self).__init__()
# nfeat特征,nhid1隐藏层1,nhid2隐藏层2,dropout丢弃率
self.SGCN1 = GCN(nfeat, nhid1, nhid2, dropout) #gcnmodule
self.SGCN2 = GCN(nfeat, nhid1, nhid2, dropout) #gcnmodule
self.CGCN = GCN(nfeat, nhid1, nhid2, dropout) #gcnmodule
self.dropout = dropout
self.a = nn.Parameter(torch.zeros(size=(nhid2, 1)))
nn.init.xavier_uniform_(self.a.data, gain=1.414) # 初始化参数
self.attention = Attention(nhid2) # 注意力机制
self.tanh = nn.Tanh()
self.MLP = nn.Sequential(
nn.Linear(nhid2, nclass),
nn.LogSoftmax(dim=1)
) # MLP(多层感知机)=神经网络
def forward(self, x, sadj, fadj):
emb1 = self.SGCN1(x, sadj) # Special_GCN out1 -- sadj structure graph
com1 = self.CGCN(x, sadj) # Common_GCN out1 -- sadj structure graph
com2 = self.CGCN(x, fadj) # Common_GCN out2 -- fadj feature graph
emb2 = self.SGCN2(x, fadj) # Special_GCN out2 -- fadj feature graph
Xcom = (com1 + com2) / 2
##attention
emb = torch.stack([emb1, emb2, Xcom], dim=1)
emb, att = self.attention(emb)
output = self.MLP(emb)
return output, att, emb1, com1, com2, emb2, emb
代码解析:
- nn.Lineae():torch中全链接网络
- nn.LogSoftmax():torch中的函数,先求softmax函数,再求log函数。
- torch.stack:向量拼接
数据流转: