项目文件夹

文件
张恒瑞 80fdcfdf83 [Example] Graph Random Neural Network (#2502)
* Add Implementation of GRAND

* Performance updated

* Update README.md

add indexing entries

* add indexing entries for grand

* change grand from 2021 to 2020

* [Example] fix some bugs

* [Examples] fix bug

Co-authored-by: 张恒瑞 <hengrui@macbook.local>
Co-authored-by: 张恒瑞 <hengrui@192.168.124.35>
Co-authored-by: zhjwy9343 <6593865@qq.com>
2021-01-13 14:06:47 +08:00

154 行
4.2 KiB
Python
可执行文件

import numpy as np
import torch as th
import torch.nn as nn
import dgl.function as fn
import torch.nn.functional as F
def drop_node(feats, drop_rate, training):
n = feats.shape[0]
drop_rates = th.FloatTensor(np.ones(n) * drop_rate)
if training:
masks = th.bernoulli(1. - drop_rates).unsqueeze(1)
feats = masks.to(feats.device) * feats
else:
feats = feats * (1. - drop_rate)
return feats
class MLP(nn.Module):
def __init__(self, nfeat, nhid, nclass, input_droprate, hidden_droprate, use_bn =False):
super(MLP, self).__init__()
self.layer1 = nn.Linear(nfeat, nhid, bias = True)
self.layer2 = nn.Linear(nhid, nclass, bias = True)
self.input_dropout = nn.Dropout(input_droprate)
self.hidden_dropout = nn.Dropout(hidden_droprate)
self.bn1 = nn.BatchNorm1d(nfeat)
self.bn2 = nn.BatchNorm1d(nhid)
self.use_bn = use_bn
def reset_parameters(self):
self.layer1.reset_parameters()
self.layer2.reset_parameters()
def forward(self, x):
if self.use_bn:
x = self.bn1(x)
x = self.input_dropout(x)
x = F.relu(self.layer1(x))
if self.use_bn:
x = self.bn2(x)
x = self.hidden_dropout(x)
x = self.layer2(x)
return x
def GRANDConv(graph, feats, order):
'''
Parameters
-----------
graph: dgl.Graph
The input graph
feats: Tensor (n_nodes * feat_dim)
Node features
order: int
Propagation Steps
'''
with graph.local_scope():
''' Calculate Symmetric normalized adjacency matrix \hat{A} '''
degs = graph.in_degrees().float().clamp(min=1)
norm = th.pow(degs, -0.5).to(feats.device).unsqueeze(1)
graph.ndata['norm'] = norm
graph.apply_edges(fn.u_mul_v('norm', 'norm', 'weight'))
''' Graph Conv '''
x = feats
y = 0+feats
for i in range(order):
graph.ndata['h'] = x
graph.update_all(fn.u_mul_e('h', 'weight', 'm'), fn.sum('m', 'h'))
x = graph.ndata.pop('h')
y.add_(x)
return y /(order + 1)
class GRAND(nn.Module):
r"""
Parameters
-----------
in_dim: int
Input feature size. i.e, the number of dimensions of: math: `H^{(i)}`.
hid_dim: int
Hidden feature size.
n_class: int
Number of classes.
S: int
Number of Augmentation samples
K: int
Number of Propagation Steps
node_dropout: float
Dropout rate on node features.
input_dropout: float
Dropout rate of the input layer of a MLP
hidden_dropout: float
Dropout rate of the hidden layer of a MLPx
batchnorm: bool, optional
If True, use batch normalization.
"""
def __init__(self,
in_dim,
hid_dim,
n_class,
S = 1,
K = 3,
node_dropout=0.0,
input_droprate = 0.0,
hidden_droprate = 0.0,
batchnorm=False):
super(GRAND, self).__init__()
self.in_dim = in_dim
self.hid_dim = hid_dim
self.S = S
self.K = K
self.n_class = n_class
self.mlp = MLP(in_dim, hid_dim, n_class, input_droprate, hidden_droprate, batchnorm)
self.dropout = node_dropout
self.node_dropout = nn.Dropout(node_dropout)
def forward(self, graph, feats, training = True):
X = feats
S = self.S
if training: # Training Mode
output_list = []
for s in range(S):
drop_feat = drop_node(X, self.dropout, True) # Drop node
feat = GRANDConv(graph, drop_feat, self.K) # Graph Convolution
output_list.append(th.log_softmax(self.mlp(feat), dim=-1)) # Prediction
return output_list
else: # Inference Mode
drop_feat = drop_node(X, self.dropout, False)
X = GRANDConv(graph, drop_feat, self.K)
return th.log_softmax(self.mlp(X), dim = -1)