Unverified Commit 704bcaf6 authored by Hongzhi (Steve), Chen's avatar Hongzhi (Steve), Chen Committed by GitHub
Browse files
parent 6bc82161
import argparse import argparse
import time import time
import dgl
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from dgl.data import (
CiteseerGraphDataset,
CoraGraphDataset,
PubmedGraphDataset,
register_data_args,
)
from dgl.nn.mxnet.conv import APPNPConv
from mxnet import gluon, nd from mxnet import gluon, nd
from mxnet.gluon import nn from mxnet.gluon import nn
import dgl
from dgl.data import (CiteseerGraphDataset, CoraGraphDataset,
PubmedGraphDataset, register_data_args)
from dgl.nn.mxnet.conv import APPNPConv
class APPNP(nn.Block): class APPNP(nn.Block):
def __init__( def __init__(
......
...@@ -11,17 +11,21 @@ Pytorch implementation: https://github.com/Diego999/pyGAT ...@@ -11,17 +11,21 @@ Pytorch implementation: https://github.com/Diego999/pyGAT
import argparse import argparse
import time import time
import dgl
import mxnet as mx import mxnet as mx
import networkx as nx import networkx as nx
import numpy as np import numpy as np
from dgl.data import (
CiteseerGraphDataset,
CoraGraphDataset,
PubmedGraphDataset,
register_data_args,
)
from gat import GAT from gat import GAT
from mxnet import gluon from mxnet import gluon
from utils import EarlyStopping from utils import EarlyStopping
import dgl
from dgl.data import (CiteseerGraphDataset, CoraGraphDataset,
PubmedGraphDataset, register_data_args)
def elu(data): def elu(data):
return mx.nd.LeakyReLU(data, act_type="elu") return mx.nd.LeakyReLU(data, act_type="elu")
...@@ -132,7 +136,6 @@ def main(args): ...@@ -132,7 +136,6 @@ def main(args):
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser(description="GAT") parser = argparse.ArgumentParser(description="GAT")
register_data_args(parser) register_data_args(parser)
parser.add_argument( parser.add_argument(
......
...@@ -5,11 +5,10 @@ References: ...@@ -5,11 +5,10 @@ References:
- Paper: https://arxiv.org/abs/1609.02907 - Paper: https://arxiv.org/abs/1609.02907
- Code: https://github.com/tkipf/gcn - Code: https://github.com/tkipf/gcn
""" """
import mxnet as mx
from mxnet import gluon
import dgl import dgl
import mxnet as mx
from dgl.nn.mxnet import GraphConv from dgl.nn.mxnet import GraphConv
from mxnet import gluon
class GCN(gluon.Block): class GCN(gluon.Block):
......
...@@ -5,48 +5,44 @@ Code: https://github.com/tkipf/gcn ...@@ -5,48 +5,44 @@ Code: https://github.com/tkipf/gcn
GCN with batch processing GCN with batch processing
""" """
import argparse import argparse
import numpy as np
import time import time
import mxnet as mx
from mxnet import gluon
import dgl import dgl
import dgl.function as fn import dgl.function as fn
from dgl.data import register_data_args import mxnet as mx
from dgl.data import CoraGraphDataset, CiteseerGraphDataset, PubmedGraphDataset import numpy as np
from dgl.data import (
CiteseerGraphDataset,
CoraGraphDataset,
PubmedGraphDataset,
register_data_args,
)
from mxnet import gluon
class GCNLayer(gluon.Block): class GCNLayer(gluon.Block):
def __init__(self, def __init__(self, g, out_feats, activation, dropout):
g,
out_feats,
activation,
dropout):
super(GCNLayer, self).__init__() super(GCNLayer, self).__init__()
self.g = g self.g = g
self.dense = gluon.nn.Dense(out_feats, activation) self.dense = gluon.nn.Dense(out_feats, activation)
self.dropout = dropout self.dropout = dropout
def forward(self, h): def forward(self, h):
self.g.ndata['h'] = h * self.g.ndata['out_norm'] self.g.ndata["h"] = h * self.g.ndata["out_norm"]
self.g.update_all(fn.copy_u(u='h', out='m'), self.g.update_all(
fn.sum(msg='m', out='accum')) fn.copy_u(u="h", out="m"), fn.sum(msg="m", out="accum")
accum = self.g.ndata.pop('accum') )
accum = self.dense(accum * self.g.ndata['in_norm']) accum = self.g.ndata.pop("accum")
accum = self.dense(accum * self.g.ndata["in_norm"])
if self.dropout: if self.dropout:
accum = mx.nd.Dropout(accum, p=self.dropout) accum = mx.nd.Dropout(accum, p=self.dropout)
h = self.g.ndata.pop('h') h = self.g.ndata.pop("h")
h = mx.nd.concat(h / self.g.ndata['out_norm'], accum, dim=1) h = mx.nd.concat(h / self.g.ndata["out_norm"], accum, dim=1)
return h return h
class GCN(gluon.Block): class GCN(gluon.Block):
def __init__(self, def __init__(self, g, n_hidden, n_classes, n_layers, activation, dropout):
g,
n_hidden,
n_classes,
n_layers,
activation,
dropout):
super(GCN, self).__init__() super(GCN, self).__init__()
self.inp_layer = gluon.nn.Dense(n_hidden, activation) self.inp_layer = gluon.nn.Dense(n_hidden, activation)
self.dropout = dropout self.dropout = dropout
...@@ -55,7 +51,6 @@ class GCN(gluon.Block): ...@@ -55,7 +51,6 @@ class GCN(gluon.Block):
self.layers.add(GCNLayer(g, n_hidden, activation, dropout)) self.layers.add(GCNLayer(g, n_hidden, activation, dropout))
self.out_layer = gluon.nn.Dense(n_classes) self.out_layer = gluon.nn.Dense(n_classes)
def forward(self, features): def forward(self, features):
emb_inp = [features, self.inp_layer(features)] emb_inp = [features, self.inp_layer(features)]
if self.dropout: if self.dropout:
...@@ -75,14 +70,14 @@ def evaluate(model, features, labels, mask): ...@@ -75,14 +70,14 @@ def evaluate(model, features, labels, mask):
def main(args): def main(args):
# load and preprocess dataset # load and preprocess dataset
if args.dataset == 'cora': if args.dataset == "cora":
data = CoraGraphDataset() data = CoraGraphDataset()
elif args.dataset == 'citeseer': elif args.dataset == "citeseer":
data = CiteseerGraphDataset() data = CiteseerGraphDataset()
elif args.dataset == 'pubmed': elif args.dataset == "pubmed":
data = PubmedGraphDataset() data = PubmedGraphDataset()
else: else:
raise ValueError('Unknown dataset: {}'.format(args.dataset)) raise ValueError("Unknown dataset: {}".format(args.dataset))
g = data[0] g = data[0]
if args.gpu < 0: if args.gpu < 0:
...@@ -93,55 +88,64 @@ def main(args): ...@@ -93,55 +88,64 @@ def main(args):
ctx = mx.gpu(args.gpu) ctx = mx.gpu(args.gpu)
g = g.to(ctx) g = g.to(ctx)
features = g.ndata['feat'] features = g.ndata["feat"]
labels = mx.nd.array(g.ndata['label'], dtype="float32", ctx=ctx) labels = mx.nd.array(g.ndata["label"], dtype="float32", ctx=ctx)
train_mask = g.ndata['train_mask'] train_mask = g.ndata["train_mask"]
val_mask = g.ndata['val_mask'] val_mask = g.ndata["val_mask"]
test_mask = g.ndata['test_mask'] test_mask = g.ndata["test_mask"]
in_feats = features.shape[1] in_feats = features.shape[1]
n_classes = data.num_labels n_classes = data.num_labels
n_edges = data.graph.number_of_edges() n_edges = data.graph.number_of_edges()
print("""----Data statistics------' print(
"""----Data statistics------'
#Edges %d #Edges %d
#Classes %d #Classes %d
#Train samples %d #Train samples %d
#Val samples %d #Val samples %d
#Test samples %d""" % #Test samples %d"""
(n_edges, n_classes, % (
train_mask.sum().asscalar(), n_edges,
val_mask.sum().asscalar(), n_classes,
test_mask.sum().asscalar())) train_mask.sum().asscalar(),
val_mask.sum().asscalar(),
test_mask.sum().asscalar(),
)
)
# add self loop # add self loop
if args.self_loop: if args.self_loop:
g = dgl.remove_self_loop(g) g = dgl.remove_self_loop(g)
g = dgl.add_self_loop(g) g = dgl.add_self_loop(g)
# normalization # normalization
in_degs = g.in_degrees().astype('float32') in_degs = g.in_degrees().astype("float32")
out_degs = g.out_degrees().astype('float32') out_degs = g.out_degrees().astype("float32")
in_norm = mx.nd.power(in_degs, -0.5) in_norm = mx.nd.power(in_degs, -0.5)
out_norm = mx.nd.power(out_degs, -0.5) out_norm = mx.nd.power(out_degs, -0.5)
if cuda: if cuda:
in_norm = in_norm.as_in_context(ctx) in_norm = in_norm.as_in_context(ctx)
out_norm = out_norm.as_in_context(ctx) out_norm = out_norm.as_in_context(ctx)
g.ndata['in_norm'] = mx.nd.expand_dims(in_norm, 1) g.ndata["in_norm"] = mx.nd.expand_dims(in_norm, 1)
g.ndata['out_norm'] = mx.nd.expand_dims(out_norm, 1) g.ndata["out_norm"] = mx.nd.expand_dims(out_norm, 1)
model = GCN(g, model = GCN(
args.n_hidden, g,
n_classes, args.n_hidden,
args.n_layers, n_classes,
'relu', args.n_layers,
args.dropout, "relu",
) args.dropout,
)
model.initialize(ctx=ctx) model.initialize(ctx=ctx)
n_train_samples = train_mask.sum().asscalar() n_train_samples = train_mask.sum().asscalar()
loss_fcn = gluon.loss.SoftmaxCELoss() loss_fcn = gluon.loss.SoftmaxCELoss()
# use optimizer # use optimizer
print(model.collect_params()) print(model.collect_params())
trainer = gluon.Trainer(model.collect_params(), 'adam', trainer = gluon.Trainer(
{'learning_rate': args.lr, 'wd': args.weight_decay}) model.collect_params(),
"adam",
{"learning_rate": args.lr, "wd": args.weight_decay},
)
# initialize graph # initialize graph
dur = [] dur = []
...@@ -160,36 +164,53 @@ def main(args): ...@@ -160,36 +164,53 @@ def main(args):
if epoch >= 3: if epoch >= 3:
dur.append(time.time() - t0) dur.append(time.time() - t0)
acc = evaluate(model, features, labels, val_mask) acc = evaluate(model, features, labels, val_mask)
print("Epoch {:05d} | Time(s) {:.4f} | Loss {:.4f} | Accuracy {:.4f} | " print(
"ETputs(KTEPS) {:.2f}". format( "Epoch {:05d} | Time(s) {:.4f} | Loss {:.4f} | Accuracy {:.4f} | "
epoch, np.mean(dur), loss.asscalar(), acc, n_edges / np.mean(dur) / 1000)) "ETputs(KTEPS) {:.2f}".format(
epoch,
np.mean(dur),
loss.asscalar(),
acc,
n_edges / np.mean(dur) / 1000,
)
)
# test set accuracy # test set accuracy
acc = evaluate(model, features, labels, test_mask) acc = evaluate(model, features, labels, test_mask)
print("Test accuracy {:.2%}".format(acc)) print("Test accuracy {:.2%}".format(acc))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='GCN') if __name__ == "__main__":
parser = argparse.ArgumentParser(description="GCN")
register_data_args(parser) register_data_args(parser)
parser.add_argument("--dropout", type=float, default=0.5, parser.add_argument(
help="dropout probability") "--dropout", type=float, default=0.5, help="dropout probability"
parser.add_argument("--gpu", type=int, default=-1, )
help="gpu") parser.add_argument("--gpu", type=int, default=-1, help="gpu")
parser.add_argument("--lr", type=float, default=1e-2, parser.add_argument("--lr", type=float, default=1e-2, help="learning rate")
help="learning rate") parser.add_argument(
parser.add_argument("--n-epochs", type=int, default=200, "--n-epochs", type=int, default=200, help="number of training epochs"
help="number of training epochs") )
parser.add_argument("--n-hidden", type=int, default=16, parser.add_argument(
help="number of hidden gcn units") "--n-hidden", type=int, default=16, help="number of hidden gcn units"
parser.add_argument("--n-layers", type=int, default=1, )
help="number of hidden gcn layers") parser.add_argument(
parser.add_argument("--normalization", "--n-layers", type=int, default=1, help="number of hidden gcn layers"
choices=['sym','left'], default=None, )
help="graph normalization types (default=None)") parser.add_argument(
parser.add_argument("--self-loop", action='store_true', "--normalization",
help="graph self-loop (default=False)") choices=["sym", "left"],
parser.add_argument("--weight-decay", type=float, default=5e-4, default=None,
help="Weight for L2 loss") help="graph normalization types (default=None)",
)
parser.add_argument(
"--self-loop",
action="store_true",
help="graph self-loop (default=False)",
)
parser.add_argument(
"--weight-decay", type=float, default=5e-4, help="Weight for L2 loss"
)
args = parser.parse_args() args = parser.parse_args()
print(args) print(args)
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
import argparse import argparse
import time import time
import dgl
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from dgl.data import CiteseerGraphDataset, CoraGraphDataset, PubmedGraphDataset
from gcn import GCN from gcn import GCN
from mxnet import gluon from mxnet import gluon
import dgl
from dgl.data import CiteseerGraphDataset, CoraGraphDataset, PubmedGraphDataset
# from gcn_mp import GCN # from gcn_mp import GCN
# from gcn_spmv import GCN # from gcn_spmv import GCN
......
...@@ -4,13 +4,13 @@ MxNet compatible dataloader ...@@ -4,13 +4,13 @@ MxNet compatible dataloader
import math import math
import dgl
import numpy as np import numpy as np
from mxnet import nd from mxnet import nd
from mxnet.gluon.data import DataLoader, Sampler from mxnet.gluon.data import DataLoader, Sampler
from sklearn.model_selection import StratifiedKFold from sklearn.model_selection import StratifiedKFold
import dgl
class SubsetRandomSampler(Sampler): class SubsetRandomSampler(Sampler):
def __init__(self, indices): def __init__(self, indices):
...@@ -52,7 +52,6 @@ class GraphDataLoader: ...@@ -52,7 +52,6 @@ class GraphDataLoader:
fold_idx=0, fold_idx=0,
split_ratio=0.7, split_ratio=0.7,
): ):
self.shuffle = shuffle self.shuffle = shuffle
self.seed = seed self.seed = seed
......
...@@ -6,11 +6,11 @@ Author's implementation: https://github.com/weihua916/powerful-gnns ...@@ -6,11 +6,11 @@ Author's implementation: https://github.com/weihua916/powerful-gnns
""" """
import mxnet as mx import mxnet as mx
from mxnet import gluon, nd
from mxnet.gluon import nn
from dgl.nn.mxnet.conv import GINConv from dgl.nn.mxnet.conv import GINConv
from dgl.nn.mxnet.glob import AvgPooling, MaxPooling, SumPooling from dgl.nn.mxnet.glob import AvgPooling, MaxPooling, SumPooling
from mxnet import gluon, nd
from mxnet.gluon import nn
class ApplyNodeFunc(nn.Block): class ApplyNodeFunc(nn.Block):
......
...@@ -3,14 +3,14 @@ from parser import Parser ...@@ -3,14 +3,14 @@ from parser import Parser
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from dataloader import GraphDataLoader, collate from dataloader import collate, GraphDataLoader
from dgl.data.gindt import GINDataset
from gin import GIN from gin import GIN
from mxnet import gluon, nd from mxnet import gluon, nd
from mxnet.gluon import nn from mxnet.gluon import nn
from tqdm import tqdm from tqdm import tqdm
from dgl.data.gindt import GINDataset
def train(args, net, trainloader, trainer, criterion, epoch): def train(args, net, trainloader, trainer, criterion, epoch):
running_loss = 0 running_loss = 0
...@@ -71,7 +71,6 @@ def eval_net(args, net, dataloader, criterion): ...@@ -71,7 +71,6 @@ def eval_net(args, net, dataloader, criterion):
def main(args): def main(args):
# set up seeds, args.seed supported # set up seeds, args.seed supported
mx.random.seed(0) mx.random.seed(0)
np.random.seed(seed=0) np.random.seed(seed=0)
......
...@@ -7,17 +7,21 @@ Simple reference implementation of GraphSAGE. ...@@ -7,17 +7,21 @@ Simple reference implementation of GraphSAGE.
import argparse import argparse
import time import time
import dgl
import mxnet as mx import mxnet as mx
import networkx as nx import networkx as nx
import numpy as np import numpy as np
from dgl.data import (
CiteseerGraphDataset,
CoraGraphDataset,
PubmedGraphDataset,
register_data_args,
)
from dgl.nn.mxnet.conv import SAGEConv
from mxnet import gluon, nd from mxnet import gluon, nd
from mxnet.gluon import nn from mxnet.gluon import nn
import dgl
from dgl.data import (CiteseerGraphDataset, CoraGraphDataset,
PubmedGraphDataset, register_data_args)
from dgl.nn.mxnet.conv import SAGEConv
class GraphSAGE(nn.Block): class GraphSAGE(nn.Block):
def __init__( def __init__(
......
import argparse import argparse
import time import time
import dgl
import mxnet as mx import mxnet as mx
import networkx as nx import networkx as nx
import numpy as np import numpy as np
from dgl.data import (
CiteseerGraphDataset,
CoraGraphDataset,
PubmedGraphDataset,
register_data_args,
)
from dgl.nn.mxnet.conv import GMMConv
from mxnet import gluon, nd from mxnet import gluon, nd
from mxnet.gluon import nn from mxnet.gluon import nn
import dgl
from dgl.data import (CiteseerGraphDataset, CoraGraphDataset,
PubmedGraphDataset, register_data_args)
from dgl.nn.mxnet.conv import GMMConv
class MoNet(nn.Block): class MoNet(nn.Block):
def __init__( def __init__(
......
...@@ -9,43 +9,66 @@ Difference compared to tkipf/relation-gcn ...@@ -9,43 +9,66 @@ Difference compared to tkipf/relation-gcn
""" """
import argparse import argparse
import numpy as np
import time import time
from functools import partial
import dgl
import mxnet as mx import mxnet as mx
from mxnet import gluon
import mxnet.ndarray as F import mxnet.ndarray as F
import dgl import numpy as np
from dgl.data.rdf import AIFBDataset, AMDataset, BGSDataset, MUTAGDataset
from dgl.nn.mxnet import RelGraphConv from dgl.nn.mxnet import RelGraphConv
from functools import partial
from dgl.data.rdf import AIFBDataset, MUTAGDataset, BGSDataset, AMDataset
from model import BaseRGCN from model import BaseRGCN
from mxnet import gluon
class EntityClassify(BaseRGCN): class EntityClassify(BaseRGCN):
def build_input_layer(self): def build_input_layer(self):
return RelGraphConv(self.num_nodes, self.h_dim, self.num_rels, "basis", return RelGraphConv(
self.num_bases, activation=F.relu, self_loop=self.use_self_loop, self.num_nodes,
dropout=self.dropout) self.h_dim,
self.num_rels,
"basis",
self.num_bases,
activation=F.relu,
self_loop=self.use_self_loop,
dropout=self.dropout,
)
def build_hidden_layer(self, idx): def build_hidden_layer(self, idx):
return RelGraphConv(self.h_dim, self.h_dim, self.num_rels, "basis", return RelGraphConv(
self.num_bases, activation=F.relu, self_loop=self.use_self_loop, self.h_dim,
dropout=self.dropout) self.h_dim,
self.num_rels,
"basis",
self.num_bases,
activation=F.relu,
self_loop=self.use_self_loop,
dropout=self.dropout,
)
def build_output_layer(self): def build_output_layer(self):
return RelGraphConv(self.h_dim, self.out_dim, self.num_rels, "basis", return RelGraphConv(
self.num_bases, activation=None, self.h_dim,
self_loop=self.use_self_loop) self.out_dim,
self.num_rels,
"basis",
self.num_bases,
activation=None,
self_loop=self.use_self_loop,
)
def main(args): def main(args):
# load graph data # load graph data
if args.dataset == 'aifb': if args.dataset == "aifb":
dataset = AIFBDataset() dataset = AIFBDataset()
elif args.dataset == 'mutag': elif args.dataset == "mutag":
dataset = MUTAGDataset() dataset = MUTAGDataset()
elif args.dataset == 'bgs': elif args.dataset == "bgs":
dataset = BGSDataset() dataset = BGSDataset()
elif args.dataset == 'am': elif args.dataset == "am":
dataset = AMDataset() dataset = AMDataset()
else: else:
raise ValueError() raise ValueError()
...@@ -56,27 +79,31 @@ def main(args): ...@@ -56,27 +79,31 @@ def main(args):
num_rels = len(hg.canonical_etypes) num_rels = len(hg.canonical_etypes)
category = dataset.predict_category category = dataset.predict_category
num_classes = dataset.num_classes num_classes = dataset.num_classes
train_mask = hg.nodes[category].data.pop('train_mask') train_mask = hg.nodes[category].data.pop("train_mask")
test_mask = hg.nodes[category].data.pop('test_mask') test_mask = hg.nodes[category].data.pop("test_mask")
train_idx = mx.nd.array(np.nonzero(train_mask.asnumpy())[0], dtype='int64') train_idx = mx.nd.array(np.nonzero(train_mask.asnumpy())[0], dtype="int64")
test_idx = mx.nd.array(np.nonzero(test_mask.asnumpy())[0], dtype='int64') test_idx = mx.nd.array(np.nonzero(test_mask.asnumpy())[0], dtype="int64")
labels = mx.nd.array(hg.nodes[category].data.pop('labels'), dtype='int64') labels = mx.nd.array(hg.nodes[category].data.pop("labels"), dtype="int64")
# split dataset into train, validate, test # split dataset into train, validate, test
if args.validation: if args.validation:
val_idx = train_idx[:len(train_idx) // 5] val_idx = train_idx[: len(train_idx) // 5]
train_idx = train_idx[len(train_idx) // 5:] train_idx = train_idx[len(train_idx) // 5 :]
else: else:
val_idx = train_idx val_idx = train_idx
# calculate norm for each edge type and store in edge # calculate norm for each edge type and store in edge
for canonical_etype in hg.canonical_etypes: for canonical_etype in hg.canonical_etypes:
u, v, eid = hg.all_edges(form='all', etype=canonical_etype) u, v, eid = hg.all_edges(form="all", etype=canonical_etype)
v = v.asnumpy() v = v.asnumpy()
_, inverse_index, count = np.unique(v, return_inverse=True, return_counts=True) _, inverse_index, count = np.unique(
v, return_inverse=True, return_counts=True
)
degrees = count[inverse_index] degrees = count[inverse_index]
norm = np.ones(eid.shape[0]) / degrees norm = np.ones(eid.shape[0]) / degrees
hg.edges[canonical_etype].data['norm'] = mx.nd.expand_dims(mx.nd.array(norm), axis=1) hg.edges[canonical_etype].data["norm"] = mx.nd.expand_dims(
mx.nd.array(norm), axis=1
)
# get target category id # get target category id
category_id = len(hg.ntypes) category_id = len(hg.ntypes)
...@@ -84,20 +111,20 @@ def main(args): ...@@ -84,20 +111,20 @@ def main(args):
if ntype == category: if ntype == category:
category_id = i category_id = i
g = dgl.to_homogeneous(hg, edata=['norm']) g = dgl.to_homogeneous(hg, edata=["norm"])
num_nodes = g.number_of_nodes() num_nodes = g.number_of_nodes()
node_ids = mx.nd.arange(num_nodes) node_ids = mx.nd.arange(num_nodes)
edge_norm = g.edata['norm'] edge_norm = g.edata["norm"]
edge_type = g.edata[dgl.ETYPE] edge_type = g.edata[dgl.ETYPE]
# find out the target node ids in g # find out the target node ids in g
node_tids = g.ndata[dgl.NTYPE] node_tids = g.ndata[dgl.NTYPE]
loc = (node_tids == category_id) loc = node_tids == category_id
loc = mx.nd.array(np.nonzero(loc.asnumpy())[0], dtype='int64') loc = mx.nd.array(np.nonzero(loc.asnumpy())[0], dtype="int64")
target_idx = node_ids[loc] target_idx = node_ids[loc]
# since the nodes are featureless, the input feature is then the node id. # since the nodes are featureless, the input feature is then the node id.
feats = mx.nd.arange(num_nodes, dtype='int32') feats = mx.nd.arange(num_nodes, dtype="int32")
# check cuda # check cuda
use_cuda = args.gpu >= 0 use_cuda = args.gpu >= 0
...@@ -113,19 +140,25 @@ def main(args): ...@@ -113,19 +140,25 @@ def main(args):
ctx = mx.cpu(0) ctx = mx.cpu(0)
# create model # create model
model = EntityClassify(num_nodes, model = EntityClassify(
args.n_hidden, num_nodes,
num_classes, args.n_hidden,
num_rels, num_classes,
num_bases=args.n_bases, num_rels,
num_hidden_layers=args.n_layers - 2, num_bases=args.n_bases,
dropout=args.dropout, num_hidden_layers=args.n_layers - 2,
use_self_loop=args.use_self_loop, dropout=args.dropout,
gpu_id=args.gpu) use_self_loop=args.use_self_loop,
gpu_id=args.gpu,
)
model.initialize(ctx=ctx) model.initialize(ctx=ctx)
# optimizer # optimizer
trainer = gluon.Trainer(model.collect_params(), 'adam', {'learning_rate': args.lr, 'wd': args.l2norm}) trainer = gluon.Trainer(
model.collect_params(),
"adam",
{"learning_rate": args.lr, "wd": args.l2norm},
)
loss_fcn = gluon.loss.SoftmaxCELoss(from_logits=False) loss_fcn = gluon.loss.SoftmaxCELoss(from_logits=False)
# training loop # training loop
...@@ -145,52 +178,91 @@ def main(args): ...@@ -145,52 +178,91 @@ def main(args):
forward_time.append(t1 - t0) forward_time.append(t1 - t0)
backward_time.append(t2 - t1) backward_time.append(t2 - t1)
print("Epoch {:05d} | Train Forward Time(s) {:.4f} | Backward Time(s) {:.4f}". print(
format(epoch, forward_time[-1], backward_time[-1])) "Epoch {:05d} | Train Forward Time(s) {:.4f} | Backward Time(s) {:.4f}".format(
epoch, forward_time[-1], backward_time[-1]
)
)
train_acc = F.sum(mx.nd.cast(pred[train_idx].argmax(axis=1), 'int64') == labels[train_idx]).asscalar() / train_idx.shape[0] train_acc = (
val_acc = F.sum(mx.nd.cast(pred[val_idx].argmax(axis=1), 'int64') == labels[val_idx]).asscalar() / len(val_idx) F.sum(
print("Train Accuracy: {:.4f} | Validation Accuracy: {:.4f}".format(train_acc, val_acc)) mx.nd.cast(pred[train_idx].argmax(axis=1), "int64")
== labels[train_idx]
).asscalar()
/ train_idx.shape[0]
)
val_acc = F.sum(
mx.nd.cast(pred[val_idx].argmax(axis=1), "int64") == labels[val_idx]
).asscalar() / len(val_idx)
print(
"Train Accuracy: {:.4f} | Validation Accuracy: {:.4f}".format(
train_acc, val_acc
)
)
print() print()
logits = model.forward(g, feats, edge_type, edge_norm) logits = model.forward(g, feats, edge_type, edge_norm)
logits = logits[target_idx] logits = logits[target_idx]
test_acc = F.sum(mx.nd.cast(logits[test_idx].argmax(axis=1), 'int64') == labels[test_idx]).asscalar() / len(test_idx) test_acc = F.sum(
mx.nd.cast(logits[test_idx].argmax(axis=1), "int64") == labels[test_idx]
).asscalar() / len(test_idx)
print("Test Accuracy: {:.4f}".format(test_acc)) print("Test Accuracy: {:.4f}".format(test_acc))
print() print()
print("Mean forward time: {:4f}".format(np.mean(forward_time[len(forward_time) // 4:]))) print(
print("Mean backward time: {:4f}".format(np.mean(backward_time[len(backward_time) // 4:]))) "Mean forward time: {:4f}".format(
np.mean(forward_time[len(forward_time) // 4 :])
)
if __name__ == '__main__': )
parser = argparse.ArgumentParser(description='RGCN') print(
parser.add_argument("--dropout", type=float, default=0, "Mean backward time: {:4f}".format(
help="dropout probability") np.mean(backward_time[len(backward_time) // 4 :])
parser.add_argument("--n-hidden", type=int, default=16, )
help="number of hidden units") )
parser.add_argument("--gpu", type=int, default=-1,
help="gpu")
parser.add_argument("--lr", type=float, default=1e-2, if __name__ == "__main__":
help="learning rate") parser = argparse.ArgumentParser(description="RGCN")
parser.add_argument("--n-bases", type=int, default=-1, parser.add_argument(
help="number of filter weight matrices, default: -1 [use all]") "--dropout", type=float, default=0, help="dropout probability"
parser.add_argument("--n-layers", type=int, default=2, )
help="number of propagation rounds") parser.add_argument(
parser.add_argument("-e", "--n-epochs", type=int, default=50, "--n-hidden", type=int, default=16, help="number of hidden units"
help="number of training epochs") )
parser.add_argument("-d", "--dataset", type=str, required=True, parser.add_argument("--gpu", type=int, default=-1, help="gpu")
help="dataset to use") parser.add_argument("--lr", type=float, default=1e-2, help="learning rate")
parser.add_argument("--l2norm", type=float, default=0, parser.add_argument(
help="l2 norm coef") "--n-bases",
parser.add_argument("--use-self-loop", default=False, action='store_true', type=int,
help="include self feature as a special relation") default=-1,
help="number of filter weight matrices, default: -1 [use all]",
)
parser.add_argument(
"--n-layers", type=int, default=2, help="number of propagation rounds"
)
parser.add_argument(
"-e",
"--n-epochs",
type=int,
default=50,
help="number of training epochs",
)
parser.add_argument(
"-d", "--dataset", type=str, required=True, help="dataset to use"
)
parser.add_argument("--l2norm", type=float, default=0, help="l2 norm coef")
parser.add_argument(
"--use-self-loop",
default=False,
action="store_true",
help="include self feature as a special relation",
)
fp = parser.add_mutually_exclusive_group(required=False) fp = parser.add_mutually_exclusive_group(required=False)
fp.add_argument('--validation', dest='validation', action='store_true') fp.add_argument("--validation", dest="validation", action="store_true")
fp.add_argument('--testing', dest='validation', action='store_false') fp.add_argument("--testing", dest="validation", action="store_false")
parser.set_defaults(validation=True) parser.set_defaults(validation=True)
args = parser.parse_args() args = parser.parse_args()
print(args) print(args)
args.bfs_level = args.n_layers + 1 # pruning used nodes for memory args.bfs_level = args.n_layers + 1 # pruning used nodes for memory
main(args) main(args)
"""DataLoader utils.""" """DataLoader utils."""
import dgl
from gluoncv.data.batchify import Pad from gluoncv.data.batchify import Pad
from mxnet import nd from mxnet import nd
import dgl
def dgl_mp_batchify_fn(data): def dgl_mp_batchify_fn(data):
if isinstance(data[0], tuple): if isinstance(data[0], tuple):
......
...@@ -8,13 +8,15 @@ import pickle ...@@ -8,13 +8,15 @@ import pickle
import warnings import warnings
from collections import Counter from collections import Counter
import dgl
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from gluoncv.data.base import VisionDataset from gluoncv.data.base import VisionDataset
from gluoncv.data.transforms.presets.rcnn import ( from gluoncv.data.transforms.presets.rcnn import (
FasterRCNNDefaultTrainTransform, FasterRCNNDefaultValTransform) FasterRCNNDefaultTrainTransform,
FasterRCNNDefaultValTransform,
import dgl )
class VGRelation(VisionDataset): class VGRelation(VisionDataset):
......
...@@ -5,7 +5,7 @@ import mxnet as mx ...@@ -5,7 +5,7 @@ import mxnet as mx
from data import * from data import *
from gluoncv.data.transforms import presets from gluoncv.data.transforms import presets
from gluoncv.utilz import download from gluoncv.utilz import download
from model import RelDN, faster_rcnn_resnet101_v1d_custom from model import faster_rcnn_resnet101_v1d_custom, RelDN
from utils import * from utils import *
import dgl import dgl
......
import pickle import pickle
import dgl
import gluoncv as gcv import gluoncv as gcv
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from mxnet import nd
from mxnet.gluon import nn
import dgl
from dgl.nn.mxnet import GraphConv from dgl.nn.mxnet import GraphConv
from dgl.utils import toindex from dgl.utils import toindex
from mxnet import nd
from mxnet.gluon import nn
__all__ = ["RelDN"] __all__ = ["RelDN"]
......
...@@ -11,19 +11,26 @@ import gluoncv as gcv ...@@ -11,19 +11,26 @@ import gluoncv as gcv
import mxnet as mx import mxnet as mx
import numpy as np import numpy as np
from data import * from data import *
from gluoncv import data as gdata from gluoncv import data as gdata, utils as gutils
from gluoncv import utils as gutils
from gluoncv.data.batchify import Append, FasterRCNNTrainBatchify, Tuple from gluoncv.data.batchify import Append, FasterRCNNTrainBatchify, Tuple
from gluoncv.data.transforms.presets.rcnn import ( from gluoncv.data.transforms.presets.rcnn import (
FasterRCNNDefaultTrainTransform, FasterRCNNDefaultValTransform) FasterRCNNDefaultTrainTransform,
FasterRCNNDefaultValTransform,
)
from gluoncv.model_zoo import get_model from gluoncv.model_zoo import get_model
from gluoncv.utils.metrics.coco_detection import COCODetectionMetric from gluoncv.utils.metrics.coco_detection import COCODetectionMetric
from gluoncv.utils.metrics.rcnn import (RCNNAccMetric, RCNNL1LossMetric, from gluoncv.utils.metrics.rcnn import (
RPNAccMetric, RPNL1LossMetric) RCNNAccMetric,
RCNNL1LossMetric,
RPNAccMetric,
RPNL1LossMetric,
)
from gluoncv.utils.metrics.voc_detection import VOC07MApMetric from gluoncv.utils.metrics.voc_detection import VOC07MApMetric
from gluoncv.utils.parallel import Parallel, Parallelizable from gluoncv.utils.parallel import Parallel, Parallelizable
from model import (faster_rcnn_resnet50_v1b_custom, from model import (
faster_rcnn_resnet101_v1d_custom) faster_rcnn_resnet101_v1d_custom,
faster_rcnn_resnet50_v1b_custom,
)
from mxnet import autograd, gluon from mxnet import autograd, gluon
from mxnet.contrib import amp from mxnet.contrib import amp
......
...@@ -28,6 +28,7 @@ use_overlap = args.overlap ...@@ -28,6 +28,7 @@ use_overlap = args.overlap
PATH_TO_DATASETS = os.path.expanduser(args.json_path) PATH_TO_DATASETS = os.path.expanduser(args.json_path)
path_to_json = os.path.join(PATH_TO_DATASETS, "rel_annotations_train.json") path_to_json = os.path.join(PATH_TO_DATASETS, "rel_annotations_train.json")
# format in y1y2x1x2 # format in y1y2x1x2
def with_overlap(boxA, boxB): def with_overlap(boxA, boxB):
xA = max(boxA[2], boxB[2]) xA = max(boxA[2], boxB[2])
......
...@@ -7,7 +7,7 @@ import numpy as np ...@@ -7,7 +7,7 @@ import numpy as np
from data import * from data import *
from gluoncv.data.batchify import Pad from gluoncv.data.batchify import Pad
from gluoncv.utils import makedirs from gluoncv.utils import makedirs
from model import RelDN, faster_rcnn_resnet101_v1d_custom from model import faster_rcnn_resnet101_v1d_custom, RelDN
from mxnet import gluon, nd from mxnet import gluon, nd
from utils import * from utils import *
......
import dgl
import numpy as np import numpy as np
from mxnet import nd from mxnet import nd
import dgl
def bbox_improve(bbox): def bbox_improve(bbox):
"""bbox encoding""" """bbox encoding"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment