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
......
...@@ -5,20 +5,26 @@ import os ...@@ -5,20 +5,26 @@ import os
import warnings import warnings
import mxnet as mx import mxnet as mx
from mxnet import autograd
from mxnet.gluon import nn
from mxnet.gluon.contrib.nn import SyncBatchNorm
from gluoncv.model_zoo.faster_rcnn.rcnn_target import RCNNTargetSampler, RCNNTargetGenerator from gluoncv.model_zoo.faster_rcnn.rcnn_target import (
RCNNTargetGenerator,
RCNNTargetSampler,
)
from gluoncv.model_zoo.rcnn import RCNN from gluoncv.model_zoo.rcnn import RCNN
from gluoncv.model_zoo.rpn import RPN from gluoncv.model_zoo.rpn import RPN
from gluoncv.nn.feature import FPNFeatureExpander from gluoncv.nn.feature import FPNFeatureExpander
from mxnet import autograd
from mxnet.gluon import nn
from mxnet.gluon.contrib.nn import SyncBatchNorm
__all__ = ['FasterRCNN', 'get_faster_rcnn', __all__ = [
'faster_rcnn_resnet50_v1b_coco', "FasterRCNN",
'faster_rcnn_resnet50_v1b_custom', "get_faster_rcnn",
'faster_rcnn_resnet101_v1d_coco', "faster_rcnn_resnet50_v1b_coco",
'faster_rcnn_resnet101_v1d_custom'] "faster_rcnn_resnet50_v1b_custom",
"faster_rcnn_resnet101_v1d_coco",
"faster_rcnn_resnet101_v1d_custom",
]
class FasterRCNN(RCNN): class FasterRCNN(RCNN):
...@@ -161,22 +167,62 @@ class FasterRCNN(RCNN): ...@@ -161,22 +167,62 @@ class FasterRCNN(RCNN):
""" """
def __init__(self, features, top_features, classes, box_features=None, def __init__(
short=600, max_size=1000, min_stage=4, max_stage=4, train_patterns=None, self,
nms_thresh=0.3, nms_topk=400, post_nms=100, features,
roi_mode='align', roi_size=(14, 14), strides=16, clip=None, top_features,
rpn_channel=1024, base_size=16, scales=(8, 16, 32), classes,
ratios=(0.5, 1, 2), alloc_size=(128, 128), rpn_nms_thresh=0.7, box_features=None,
rpn_train_pre_nms=12000, rpn_train_post_nms=2000, rpn_test_pre_nms=6000, short=600,
rpn_test_post_nms=300, rpn_min_size=16, per_device_batch_size=1, num_sample=128, max_size=1000,
pos_iou_thresh=0.5, pos_ratio=0.25, max_num_gt=300, additional_output=False, min_stage=4,
force_nms=False, **kwargs): max_stage=4,
train_patterns=None,
nms_thresh=0.3,
nms_topk=400,
post_nms=100,
roi_mode="align",
roi_size=(14, 14),
strides=16,
clip=None,
rpn_channel=1024,
base_size=16,
scales=(8, 16, 32),
ratios=(0.5, 1, 2),
alloc_size=(128, 128),
rpn_nms_thresh=0.7,
rpn_train_pre_nms=12000,
rpn_train_post_nms=2000,
rpn_test_pre_nms=6000,
rpn_test_post_nms=300,
rpn_min_size=16,
per_device_batch_size=1,
num_sample=128,
pos_iou_thresh=0.5,
pos_ratio=0.25,
max_num_gt=300,
additional_output=False,
force_nms=False,
**kwargs
):
super(FasterRCNN, self).__init__( super(FasterRCNN, self).__init__(
features=features, top_features=top_features, classes=classes, features=features,
box_features=box_features, short=short, max_size=max_size, top_features=top_features,
train_patterns=train_patterns, nms_thresh=nms_thresh, nms_topk=nms_topk, classes=classes,
post_nms=post_nms, roi_mode=roi_mode, roi_size=roi_size, strides=strides, clip=clip, box_features=box_features,
force_nms=force_nms, **kwargs) short=short,
max_size=max_size,
train_patterns=train_patterns,
nms_thresh=nms_thresh,
nms_topk=nms_topk,
post_nms=post_nms,
roi_mode=roi_mode,
roi_size=roi_size,
strides=strides,
clip=clip,
force_nms=force_nms,
**kwargs
)
if rpn_train_post_nms > rpn_train_pre_nms: if rpn_train_post_nms > rpn_train_pre_nms:
rpn_train_post_nms = rpn_train_pre_nms rpn_train_post_nms = rpn_train_pre_nms
if rpn_test_post_nms > rpn_test_pre_nms: if rpn_test_post_nms > rpn_test_pre_nms:
...@@ -187,27 +233,43 @@ class FasterRCNN(RCNN): ...@@ -187,27 +233,43 @@ class FasterRCNN(RCNN):
self._max_stage = max_stage self._max_stage = max_stage
self.num_stages = max_stage - min_stage + 1 self.num_stages = max_stage - min_stage + 1
if self.num_stages > 1: if self.num_stages > 1:
assert len(scales) == len(strides) == self.num_stages, \ assert len(scales) == len(strides) == self.num_stages, (
"The num_stages (%d) must match number of scales (%d) and strides (%d)" \ "The num_stages (%d) must match number of scales (%d) and strides (%d)"
% (self.num_stages, len(scales), len(strides)) % (self.num_stages, len(scales), len(strides))
)
self._batch_size = per_device_batch_size self._batch_size = per_device_batch_size
self._num_sample = num_sample self._num_sample = num_sample
self._rpn_test_post_nms = rpn_test_post_nms self._rpn_test_post_nms = rpn_test_post_nms
self._target_generator = RCNNTargetGenerator(self.num_class, int(num_sample * pos_ratio), self._target_generator = RCNNTargetGenerator(
self._batch_size) self.num_class, int(num_sample * pos_ratio), self._batch_size
)
self._additional_output = additional_output self._additional_output = additional_output
with self.name_scope(): with self.name_scope():
self.rpn = RPN( self.rpn = RPN(
channels=rpn_channel, strides=strides, base_size=base_size, channels=rpn_channel,
scales=scales, ratios=ratios, alloc_size=alloc_size, strides=strides,
clip=clip, nms_thresh=rpn_nms_thresh, train_pre_nms=rpn_train_pre_nms, base_size=base_size,
train_post_nms=rpn_train_post_nms, test_pre_nms=rpn_test_pre_nms, scales=scales,
test_post_nms=rpn_test_post_nms, min_size=rpn_min_size, ratios=ratios,
multi_level=self.num_stages > 1, per_level_nms=False) alloc_size=alloc_size,
self.sampler = RCNNTargetSampler(num_image=self._batch_size, clip=clip,
num_proposal=rpn_train_post_nms, num_sample=num_sample, nms_thresh=rpn_nms_thresh,
pos_iou_thresh=pos_iou_thresh, pos_ratio=pos_ratio, train_pre_nms=rpn_train_pre_nms,
max_num_gt=max_num_gt) train_post_nms=rpn_train_post_nms,
test_pre_nms=rpn_test_pre_nms,
test_post_nms=rpn_test_post_nms,
min_size=rpn_min_size,
multi_level=self.num_stages > 1,
per_level_nms=False,
)
self.sampler = RCNNTargetSampler(
num_image=self._batch_size,
num_proposal=rpn_train_post_nms,
num_sample=num_sample,
pos_iou_thresh=pos_iou_thresh,
pos_ratio=pos_ratio,
max_num_gt=max_num_gt,
)
@property @property
def target_generator(self): def target_generator(self):
...@@ -248,11 +310,21 @@ class FasterRCNN(RCNN): ...@@ -248,11 +310,21 @@ class FasterRCNN(RCNN):
""" """
super(FasterRCNN, self).reset_class(classes, reuse_weights) super(FasterRCNN, self).reset_class(classes, reuse_weights)
self._target_generator = RCNNTargetGenerator(self.num_class, self.sampler._max_pos, self._target_generator = RCNNTargetGenerator(
self._batch_size) self.num_class, self.sampler._max_pos, self._batch_size
)
def _pyramid_roi_feats(self, F, features, rpn_rois, roi_size, strides, roi_mode='align', def _pyramid_roi_feats(
roi_canonical_scale=224.0, eps=1e-6): self,
F,
features,
rpn_rois,
roi_size,
strides,
roi_mode="align",
roi_canonical_scale=224.0,
eps=1e-6,
):
"""Assign rpn_rois to specific FPN layers according to its area """Assign rpn_rois to specific FPN layers according to its area
and then perform `ROIPooling` or `ROIAlign` to generate final and then perform `ROIPooling` or `ROIAlign` to generate final
region proposals aggregated features. region proposals aggregated features.
...@@ -281,7 +353,9 @@ class FasterRCNN(RCNN): ...@@ -281,7 +353,9 @@ class FasterRCNN(RCNN):
_, x1, y1, x2, y2 = F.split(rpn_rois, axis=-1, num_outputs=5) _, x1, y1, x2, y2 = F.split(rpn_rois, axis=-1, num_outputs=5)
h = y2 - y1 + 1 h = y2 - y1 + 1
w = x2 - x1 + 1 w = x2 - x1 + 1
roi_level = F.floor(4 + F.log2(F.sqrt(w * h) / roi_canonical_scale + eps)) roi_level = F.floor(
4 + F.log2(F.sqrt(w * h) / roi_canonical_scale + eps)
)
roi_level = F.squeeze(F.clip(roi_level, self._min_stage, max_stage)) roi_level = F.squeeze(F.clip(roi_level, self._min_stage, max_stage))
# [2,2,..,3,3,...,4,4,...,5,5,...] ``Prohibit swap order here`` # [2,2,..,3,3,...,4,4,...,5,5,...] ``Prohibit swap order here``
# roi_level_sorted_args = F.argsort(roi_level, is_ascend=True) # roi_level_sorted_args = F.argsort(roi_level, is_ascend=True)
...@@ -289,23 +363,44 @@ class FasterRCNN(RCNN): ...@@ -289,23 +363,44 @@ class FasterRCNN(RCNN):
# rpn_rois = F.take(rpn_rois, roi_level_sorted_args, axis=0) # rpn_rois = F.take(rpn_rois, roi_level_sorted_args, axis=0)
pooled_roi_feats = [] pooled_roi_feats = []
for i, l in enumerate(range(self._min_stage, max_stage + 1)): for i, l in enumerate(range(self._min_stage, max_stage + 1)):
if roi_mode == 'pool': if roi_mode == "pool":
# Pool features with all rois first, and then set invalid pooled features to zero, # Pool features with all rois first, and then set invalid pooled features to zero,
# at last ele-wise add together to aggregate all features. # at last ele-wise add together to aggregate all features.
pooled_feature = F.ROIPooling(features[i], rpn_rois, roi_size, 1. / strides[i]) pooled_feature = F.ROIPooling(
pooled_feature = F.where(roi_level == l, pooled_feature, features[i], rpn_rois, roi_size, 1.0 / strides[i]
F.zeros_like(pooled_feature)) )
elif roi_mode == 'align': pooled_feature = F.where(
if 'box_encode' in F.contrib.__dict__ and 'box_decode' in F.contrib.__dict__: roi_level == l, pooled_feature, F.zeros_like(pooled_feature)
)
elif roi_mode == "align":
if (
"box_encode" in F.contrib.__dict__
and "box_decode" in F.contrib.__dict__
):
# TODO(jerryzcn): clean this up for once mx 1.6 is released. # TODO(jerryzcn): clean this up for once mx 1.6 is released.
masked_rpn_rois = F.where(roi_level == l, rpn_rois, F.ones_like(rpn_rois) * -1.) masked_rpn_rois = F.where(
pooled_feature = F.contrib.ROIAlign(features[i], masked_rpn_rois, roi_size, roi_level == l, rpn_rois, F.ones_like(rpn_rois) * -1.0
1. / strides[i], sample_ratio=2) )
pooled_feature = F.contrib.ROIAlign(
features[i],
masked_rpn_rois,
roi_size,
1.0 / strides[i],
sample_ratio=2,
)
else: else:
pooled_feature = F.contrib.ROIAlign(features[i], rpn_rois, roi_size, pooled_feature = F.contrib.ROIAlign(
1. / strides[i], sample_ratio=2) features[i],
pooled_feature = F.where(roi_level == l, pooled_feature, rpn_rois,
F.zeros_like(pooled_feature)) roi_size,
1.0 / strides[i],
sample_ratio=2,
)
pooled_feature = F.where(
roi_level == l,
pooled_feature,
F.zeros_like(pooled_feature),
)
else: else:
raise ValueError("Invalid roi mode: {}".format(roi_mode)) raise ValueError("Invalid roi mode: {}".format(roi_mode))
pooled_roi_feats.append(pooled_feature) pooled_roi_feats.append(pooled_feature)
...@@ -341,7 +436,9 @@ class FasterRCNN(RCNN): ...@@ -341,7 +436,9 @@ class FasterRCNN(RCNN):
""" """
def _split(x, axis, num_outputs, squeeze_axis): def _split(x, axis, num_outputs, squeeze_axis):
x = F.split(x, axis=axis, num_outputs=num_outputs, squeeze_axis=squeeze_axis) x = F.split(
x, axis=axis, num_outputs=num_outputs, squeeze_axis=squeeze_axis
)
if isinstance(x, list): if isinstance(x, list):
return x return x
else: else:
...@@ -361,9 +458,16 @@ class FasterRCNN(RCNN): ...@@ -361,9 +458,16 @@ class FasterRCNN(RCNN):
rpn_box = m_rpn_box rpn_box = m_rpn_box
self.nms_thresh = 1 self.nms_thresh = 1
else: else:
rpn_score, rpn_box, raw_rpn_score, raw_rpn_box, anchors = \ (
self.rpn(F.zeros_like(x), *feat) rpn_score,
rpn_box, samples, matches = self.sampler(rpn_box, rpn_score, gt_box) rpn_box,
raw_rpn_score,
raw_rpn_box,
anchors,
) = self.rpn(F.zeros_like(x), *feat)
rpn_box, samples, matches = self.sampler(
rpn_box, rpn_score, gt_box
)
else: else:
if manual_rpn_box: if manual_rpn_box:
rpn_box = m_rpn_box rpn_box = m_rpn_box
...@@ -373,7 +477,11 @@ class FasterRCNN(RCNN): ...@@ -373,7 +477,11 @@ class FasterRCNN(RCNN):
# create batchid for roi # create batchid for roi
if not manual_rpn_box: if not manual_rpn_box:
num_roi = self._num_sample if autograd.is_training() else self._rpn_test_post_nms num_roi = (
self._num_sample
if autograd.is_training()
else self._rpn_test_post_nms
)
batch_size = self._batch_size if autograd.is_training() else 1 batch_size = self._batch_size if autograd.is_training() else 1
else: else:
num_roi = m_rpn_box.shape[1] num_roi = m_rpn_box.shape[1]
...@@ -383,20 +491,36 @@ class FasterRCNN(RCNN): ...@@ -383,20 +491,36 @@ class FasterRCNN(RCNN):
roi_batchid = F.arange(0, batch_size) roi_batchid = F.arange(0, batch_size)
roi_batchid = F.repeat(roi_batchid, num_roi) roi_batchid = F.repeat(roi_batchid, num_roi)
# remove batch dim because ROIPooling require 2d input # remove batch dim because ROIPooling require 2d input
rpn_roi = F.concat(*[roi_batchid.reshape((-1, 1)), rpn_box.reshape((-1, 4))], dim=-1) rpn_roi = F.concat(
*[roi_batchid.reshape((-1, 1)), rpn_box.reshape((-1, 4))],
dim=-1
)
rpn_roi = F.stop_gradient(rpn_roi) rpn_roi = F.stop_gradient(rpn_roi)
if self.num_stages > 1: if self.num_stages > 1:
# using FPN # using FPN
pooled_feat = self._pyramid_roi_feats(F, feat, rpn_roi, self._roi_size, pooled_feat = self._pyramid_roi_feats(
self._strides, roi_mode=self._roi_mode) F,
feat,
rpn_roi,
self._roi_size,
self._strides,
roi_mode=self._roi_mode,
)
else: else:
# ROI features # ROI features
if self._roi_mode == 'pool': if self._roi_mode == "pool":
pooled_feat = F.ROIPooling(feat[0], rpn_roi, self._roi_size, 1. / self._strides) pooled_feat = F.ROIPooling(
elif self._roi_mode == 'align': feat[0], rpn_roi, self._roi_size, 1.0 / self._strides
pooled_feat = F.contrib.ROIAlign(feat[0], rpn_roi, self._roi_size, )
1. / self._strides, sample_ratio=2) elif self._roi_mode == "align":
pooled_feat = F.contrib.ROIAlign(
feat[0],
rpn_roi,
self._roi_size,
1.0 / self._strides,
sample_ratio=2,
)
else: else:
raise ValueError("Invalid roi mode: {}".format(self._roi_mode)) raise ValueError("Invalid roi mode: {}".format(self._roi_mode))
...@@ -413,30 +537,79 @@ class FasterRCNN(RCNN): ...@@ -413,30 +537,79 @@ class FasterRCNN(RCNN):
# cls_pred (B * N, C) -> (B, N, C) # cls_pred (B * N, C) -> (B, N, C)
cls_pred = cls_pred.reshape((batch_size, num_roi, self.num_class + 1)) cls_pred = cls_pred.reshape((batch_size, num_roi, self.num_class + 1))
if manual_rpn_box: if manual_rpn_box:
spatial_feat = top_feat.mean(axis=1).reshape((-4, rpn_box.shape[0], rpn_box.shape[1], -3)) spatial_feat = top_feat.mean(axis=1).reshape(
(-4, rpn_box.shape[0], rpn_box.shape[1], -3)
)
cls_ids, scores = self.cls_decoder(F.softmax(cls_pred, axis=-1)) cls_ids, scores = self.cls_decoder(F.softmax(cls_pred, axis=-1))
cls_ids = cls_ids.transpose((0, 2, 1)).reshape((0, 0, 0, 1)) cls_ids = cls_ids.transpose((0, 2, 1)).reshape((0, 0, 0, 1))
scores = scores.transpose((0, 2, 1)).reshape((0, 0, 0, 1)) scores = scores.transpose((0, 2, 1)).reshape((0, 0, 0, 1))
cls_ids = _split(cls_ids, axis=0, num_outputs=batch_size, squeeze_axis=True) cls_ids = _split(
scores = _split(scores, axis=0, num_outputs=batch_size, squeeze_axis=True) cls_ids, axis=0, num_outputs=batch_size, squeeze_axis=True
)
scores = _split(
scores, axis=0, num_outputs=batch_size, squeeze_axis=True
)
return cls_ids, scores, rpn_box, spatial_feat return cls_ids, scores, rpn_box, spatial_feat
# no need to convert bounding boxes in training, just return # no need to convert bounding boxes in training, just return
if autograd.is_training(): if autograd.is_training():
cls_targets, box_targets, box_masks, indices = \ (
self._target_generator(rpn_box, samples, matches, gt_label, gt_box) cls_targets,
box_targets,
box_masks,
indices,
) = self._target_generator(
rpn_box, samples, matches, gt_label, gt_box
)
box_feat = F.reshape(box_feat.expand_dims(0), (batch_size, -1, 0)) box_feat = F.reshape(box_feat.expand_dims(0), (batch_size, -1, 0))
box_pred = self.box_predictor(F.concat( box_pred = self.box_predictor(
*[F.take(F.slice_axis(box_feat, axis=0, begin=i, end=i + 1).squeeze(), F.concat(
F.slice_axis(indices, axis=0, begin=i, end=i + 1).squeeze()) *[
for i in range(batch_size)], dim=0)) F.take(
F.slice_axis(
box_feat, axis=0, begin=i, end=i + 1
).squeeze(),
F.slice_axis(
indices, axis=0, begin=i, end=i + 1
).squeeze(),
)
for i in range(batch_size)
],
dim=0
)
)
# box_pred (B * N, C * 4) -> (B, N, C, 4) # box_pred (B * N, C * 4) -> (B, N, C, 4)
box_pred = box_pred.reshape((batch_size, -1, self.num_class, 4)) box_pred = box_pred.reshape((batch_size, -1, self.num_class, 4))
if self._additional_output: if self._additional_output:
return (cls_pred, box_pred, rpn_box, samples, matches, raw_rpn_score, raw_rpn_box, return (
anchors, cls_targets, box_targets, box_masks, top_feat, indices) cls_pred,
return (cls_pred, box_pred, rpn_box, samples, matches, raw_rpn_score, raw_rpn_box, box_pred,
anchors, cls_targets, box_targets, box_masks, indices) rpn_box,
samples,
matches,
raw_rpn_score,
raw_rpn_box,
anchors,
cls_targets,
box_targets,
box_masks,
top_feat,
indices,
)
return (
cls_pred,
box_pred,
rpn_box,
samples,
matches,
raw_rpn_score,
raw_rpn_box,
anchors,
cls_targets,
box_targets,
box_masks,
indices,
)
box_pred = self.box_predictor(box_feat) box_pred = self.box_predictor(box_feat)
# box_pred (B * N, C * 4) -> (B, N, C, 4) # box_pred (B * N, C * 4) -> (B, N, C, 4)
...@@ -450,12 +623,20 @@ class FasterRCNN(RCNN): ...@@ -450,12 +623,20 @@ class FasterRCNN(RCNN):
box_pred = box_pred.transpose((0, 2, 1, 3)) box_pred = box_pred.transpose((0, 2, 1, 3))
# rpn_boxes (B, N, 4) -> B * (1, N, 4) # rpn_boxes (B, N, 4) -> B * (1, N, 4)
rpn_boxes = _split(rpn_box, axis=0, num_outputs=batch_size, squeeze_axis=False) rpn_boxes = _split(
rpn_box, axis=0, num_outputs=batch_size, squeeze_axis=False
)
# cls_ids, scores (B, C, N, 1) -> B * (C, N, 1) # cls_ids, scores (B, C, N, 1) -> B * (C, N, 1)
cls_ids = _split(cls_ids, axis=0, num_outputs=batch_size, squeeze_axis=True) cls_ids = _split(
scores = _split(scores, axis=0, num_outputs=batch_size, squeeze_axis=True) cls_ids, axis=0, num_outputs=batch_size, squeeze_axis=True
)
scores = _split(
scores, axis=0, num_outputs=batch_size, squeeze_axis=True
)
# box_preds (B, C, N, 4) -> B * (C, N, 4) # box_preds (B, C, N, 4) -> B * (C, N, 4)
box_preds = _split(box_pred, axis=0, num_outputs=batch_size, squeeze_axis=True) box_preds = _split(
box_pred, axis=0, num_outputs=batch_size, squeeze_axis=True
)
# per batch predict, nms, each class has topk outputs # per batch predict, nms, each class has topk outputs
results = [] results = []
...@@ -465,8 +646,14 @@ class FasterRCNN(RCNN): ...@@ -465,8 +646,14 @@ class FasterRCNN(RCNN):
# ind = mx.nd.array(list(range(sizes[1]))) # ind = mx.nd.array(list(range(sizes[1])))
ind = mx.nd.linspace(0, 999, 1000) ind = mx.nd.linspace(0, 999, 1000)
ind = mx.nd.repeat(ind, repeats=sizes[0]) ind = mx.nd.repeat(ind, repeats=sizes[0])
ind = ind.reshape(sizes[1], sizes[0]).transpose((1, 0)).expand_dims(axis=2) ind = (
for rpn_box, cls_id, score, box_pred in zip(rpn_boxes, cls_ids, scores, box_preds): ind.reshape(sizes[1], sizes[0])
.transpose((1, 0))
.expand_dims(axis=2)
)
for rpn_box, cls_id, score, box_pred in zip(
rpn_boxes, cls_ids, scores, box_preds
):
# box_pred (C, N, 4) rpn_box (1, N, 4) -> bbox (C, N, 4) # box_pred (C, N, 4) rpn_box (1, N, 4) -> bbox (C, N, 4)
bbox = self.box_decoder(box_pred, rpn_box) bbox = self.box_decoder(box_pred, rpn_box)
if self._additional_output: if self._additional_output:
...@@ -480,8 +667,15 @@ class FasterRCNN(RCNN): ...@@ -480,8 +667,15 @@ class FasterRCNN(RCNN):
res = res.reshape((1, -1, 0)) res = res.reshape((1, -1, 0))
# res (C, self.nms_topk, 6) # res (C, self.nms_topk, 6)
res = F.contrib.box_nms( res = F.contrib.box_nms(
res, overlap_thresh=self.nms_thresh, topk=self.nms_topk, valid_thresh=0.001, res,
id_index=0, score_index=1, coord_start=2, force_suppress=self.force_nms) overlap_thresh=self.nms_thresh,
topk=self.nms_topk,
valid_thresh=0.001,
id_index=0,
score_index=1,
coord_start=2,
force_suppress=self.force_nms,
)
# res (C * self.nms_topk, 6) # res (C * self.nms_topk, 6)
res = res.reshape((-3, 0)) res = res.reshape((-3, 0))
results.append(res) results.append(res)
...@@ -493,12 +687,21 @@ class FasterRCNN(RCNN): ...@@ -493,12 +687,21 @@ class FasterRCNN(RCNN):
bboxes = F.slice_axis(result, axis=-1, begin=2, end=6) bboxes = F.slice_axis(result, axis=-1, begin=2, end=6)
if self._additional_output: if self._additional_output:
feat_ind = F.slice_axis(result, axis=-1, begin=6, end=7) feat_ind = F.slice_axis(result, axis=-1, begin=6, end=7)
spatial_feat = top_feat.mean(axis=1).expand_dims(0).reshape(batch_size, 0, -1) spatial_feat = (
top_feat.mean(axis=1).expand_dims(0).reshape(batch_size, 0, -1)
)
return ids, scores, bboxes, feat, feat_ind, spatial_feat return ids, scores, bboxes, feat, feat_ind, spatial_feat
return ids, scores, bboxes return ids, scores, bboxes
def get_faster_rcnn(name, dataset, pretrained=False, ctx=mx.cpu(),
root=os.path.join('~', '.mxnet', 'models'), **kwargs): def get_faster_rcnn(
name,
dataset,
pretrained=False,
ctx=mx.cpu(),
root=os.path.join("~", ".mxnet", "models"),
**kwargs
):
r"""Utility function to return faster rcnn networks. r"""Utility function to return faster rcnn networks.
Parameters Parameters
...@@ -524,9 +727,14 @@ def get_faster_rcnn(name, dataset, pretrained=False, ctx=mx.cpu(), ...@@ -524,9 +727,14 @@ def get_faster_rcnn(name, dataset, pretrained=False, ctx=mx.cpu(),
net = FasterRCNN(**kwargs) net = FasterRCNN(**kwargs)
if pretrained: if pretrained:
from gluoncv.model_zoo.model_store import get_model_file from gluoncv.model_zoo.model_store import get_model_file
full_name = '_'.join(('faster_rcnn', name, dataset))
net.load_parameters(get_model_file(full_name, tag=pretrained, root=root), ctx=ctx, full_name = "_".join(("faster_rcnn", name, dataset))
ignore_extra=True, allow_missing=True) net.load_parameters(
get_model_file(full_name, tag=pretrained, root=root),
ctx=ctx,
ignore_extra=True,
allow_missing=True,
)
else: else:
for v in net.collect_params().values(): for v in net.collect_params().values():
try: try:
...@@ -535,7 +743,10 @@ def get_faster_rcnn(name, dataset, pretrained=False, ctx=mx.cpu(), ...@@ -535,7 +743,10 @@ def get_faster_rcnn(name, dataset, pretrained=False, ctx=mx.cpu(),
pass pass
return net return net
def faster_rcnn_resnet50_v1b_coco(pretrained=False, pretrained_base=True, **kwargs):
def faster_rcnn_resnet50_v1b_coco(
pretrained=False, pretrained_base=True, **kwargs
):
r"""Faster RCNN model from the paper r"""Faster RCNN model from the paper
"Ren, S., He, K., Girshick, R., & Sun, J. (2015). Faster r-cnn: Towards "Ren, S., He, K., Girshick, R., & Sun, J. (2015). Faster r-cnn: Towards
real-time object detection with region proposal networks" real-time object detection with region proposal networks"
...@@ -558,34 +769,73 @@ def faster_rcnn_resnet50_v1b_coco(pretrained=False, pretrained_base=True, **kwar ...@@ -558,34 +769,73 @@ def faster_rcnn_resnet50_v1b_coco(pretrained=False, pretrained_base=True, **kwar
>>> model = get_faster_rcnn_resnet50_v1b_coco(pretrained=True) >>> model = get_faster_rcnn_resnet50_v1b_coco(pretrained=True)
>>> print(model) >>> print(model)
""" """
from gluoncv.model_zoo.resnetv1b import resnet50_v1b
from gluoncv.data import COCODetection from gluoncv.data import COCODetection
from gluoncv.model_zoo.resnetv1b import resnet50_v1b
classes = COCODetection.CLASSES classes = COCODetection.CLASSES
pretrained_base = False if pretrained else pretrained_base pretrained_base = False if pretrained else pretrained_base
base_network = resnet50_v1b(pretrained=pretrained_base, dilated=False, base_network = resnet50_v1b(
use_global_stats=True, **kwargs) pretrained=pretrained_base,
dilated=False,
use_global_stats=True,
**kwargs
)
features = nn.HybridSequential() features = nn.HybridSequential()
top_features = nn.HybridSequential() top_features = nn.HybridSequential()
for layer in ['conv1', 'bn1', 'relu', 'maxpool', 'layer1', 'layer2', 'layer3']: for layer in [
"conv1",
"bn1",
"relu",
"maxpool",
"layer1",
"layer2",
"layer3",
]:
features.add(getattr(base_network, layer)) features.add(getattr(base_network, layer))
for layer in ['layer4']: for layer in ["layer4"]:
top_features.add(getattr(base_network, layer)) top_features.add(getattr(base_network, layer))
train_patterns = '|'.join(['.*dense', '.*rpn', '.*down(2|3|4)_conv', '.*layers(2|3|4)_conv']) train_patterns = "|".join(
[".*dense", ".*rpn", ".*down(2|3|4)_conv", ".*layers(2|3|4)_conv"]
)
return get_faster_rcnn( return get_faster_rcnn(
name='resnet50_v1b', dataset='coco', pretrained=pretrained, name="resnet50_v1b",
features=features, top_features=top_features, classes=classes, dataset="coco",
short=800, max_size=1333, train_patterns=train_patterns, pretrained=pretrained,
nms_thresh=0.7, nms_topk=-1, post_nms=-1, features=features,
roi_mode='align', roi_size=(14, 14), strides=16, clip=4.14, top_features=top_features,
rpn_channel=1024, base_size=16, scales=(2, 4, 8, 16, 32), classes=classes,
ratios=(0.5, 1, 2), alloc_size=(128, 128), rpn_nms_thresh=0.7, short=800,
rpn_train_pre_nms=12000, rpn_train_post_nms=2000, max_size=1333,
rpn_test_pre_nms=6000, rpn_test_post_nms=1000, rpn_min_size=1, train_patterns=train_patterns,
num_sample=128, pos_iou_thresh=0.5, pos_ratio=0.25, nms_thresh=0.7,
max_num_gt=3000, **kwargs) nms_topk=-1,
post_nms=-1,
def faster_rcnn_resnet50_v1b_custom(classes, transfer=None, pretrained_base=True, roi_mode="align",
pretrained=False, **kwargs): roi_size=(14, 14),
strides=16,
clip=4.14,
rpn_channel=1024,
base_size=16,
scales=(2, 4, 8, 16, 32),
ratios=(0.5, 1, 2),
alloc_size=(128, 128),
rpn_nms_thresh=0.7,
rpn_train_pre_nms=12000,
rpn_train_post_nms=2000,
rpn_test_pre_nms=6000,
rpn_test_post_nms=1000,
rpn_min_size=1,
num_sample=128,
pos_iou_thresh=0.5,
pos_ratio=0.25,
max_num_gt=3000,
**kwargs
)
def faster_rcnn_resnet50_v1b_custom(
classes, transfer=None, pretrained_base=True, pretrained=False, **kwargs
):
r"""Faster RCNN model with resnet50_v1b base network on custom dataset. r"""Faster RCNN model with resnet50_v1b base network on custom dataset.
Parameters Parameters
...@@ -612,39 +862,85 @@ def faster_rcnn_resnet50_v1b_custom(classes, transfer=None, pretrained_base=True ...@@ -612,39 +862,85 @@ def faster_rcnn_resnet50_v1b_custom(classes, transfer=None, pretrained_base=True
Hybrid faster RCNN network. Hybrid faster RCNN network.
""" """
if pretrained: if pretrained:
warnings.warn("Custom models don't provide `pretrained` weights, ignored.") warnings.warn(
"Custom models don't provide `pretrained` weights, ignored."
)
if transfer is None: if transfer is None:
from gluoncv.model_zoo.resnetv1b import resnet50_v1b from gluoncv.model_zoo.resnetv1b import resnet50_v1b
base_network = resnet50_v1b(pretrained=pretrained_base, dilated=False,
use_global_stats=True, **kwargs) base_network = resnet50_v1b(
pretrained=pretrained_base,
dilated=False,
use_global_stats=True,
**kwargs
)
features = nn.HybridSequential() features = nn.HybridSequential()
top_features = nn.HybridSequential() top_features = nn.HybridSequential()
for layer in ['conv1', 'bn1', 'relu', 'maxpool', 'layer1', 'layer2', 'layer3']: for layer in [
"conv1",
"bn1",
"relu",
"maxpool",
"layer1",
"layer2",
"layer3",
]:
features.add(getattr(base_network, layer)) features.add(getattr(base_network, layer))
for layer in ['layer4']: for layer in ["layer4"]:
top_features.add(getattr(base_network, layer)) top_features.add(getattr(base_network, layer))
train_patterns = '|'.join(['.*dense', '.*rpn', '.*down(2|3|4)_conv', train_patterns = "|".join(
'.*layers(2|3|4)_conv']) [".*dense", ".*rpn", ".*down(2|3|4)_conv", ".*layers(2|3|4)_conv"]
)
return get_faster_rcnn( return get_faster_rcnn(
name='resnet50_v1b', dataset='custom', pretrained=pretrained, name="resnet50_v1b",
features=features, top_features=top_features, classes=classes, dataset="custom",
short=600, max_size=1000, train_patterns=train_patterns, pretrained=pretrained,
nms_thresh=0.7, nms_topk=400, post_nms=100, features=features,
roi_mode='align', roi_size=(14, 14), strides=16, clip=4.14, top_features=top_features,
rpn_channel=1024, base_size=16, scales=(2, 4, 8, 16, 32), classes=classes,
ratios=(0.5, 1, 2), alloc_size=(128, 128), rpn_nms_thresh=0.7, short=600,
rpn_train_pre_nms=12000, rpn_train_post_nms=2000, max_size=1000,
rpn_test_pre_nms=6000, rpn_test_post_nms=300, rpn_min_size=16, train_patterns=train_patterns,
num_sample=128, pos_iou_thresh=0.5, pos_ratio=0.25, max_num_gt=3000, nms_thresh=0.7,
**kwargs) nms_topk=400,
post_nms=100,
roi_mode="align",
roi_size=(14, 14),
strides=16,
clip=4.14,
rpn_channel=1024,
base_size=16,
scales=(2, 4, 8, 16, 32),
ratios=(0.5, 1, 2),
alloc_size=(128, 128),
rpn_nms_thresh=0.7,
rpn_train_pre_nms=12000,
rpn_train_post_nms=2000,
rpn_test_pre_nms=6000,
rpn_test_post_nms=300,
rpn_min_size=16,
num_sample=128,
pos_iou_thresh=0.5,
pos_ratio=0.25,
max_num_gt=3000,
**kwargs
)
else: else:
from gluoncv.model_zoo import get_model from gluoncv.model_zoo import get_model
net = get_model('faster_rcnn_resnet50_v1b_' + str(transfer), pretrained=True, **kwargs)
net = get_model(
"faster_rcnn_resnet50_v1b_" + str(transfer),
pretrained=True,
**kwargs
)
reuse_classes = [x for x in classes if x in net.classes] reuse_classes = [x for x in classes if x in net.classes]
net.reset_class(classes, reuse_weights=reuse_classes) net.reset_class(classes, reuse_weights=reuse_classes)
return net return net
def faster_rcnn_resnet101_v1d_coco(pretrained=False, pretrained_base=True, **kwargs):
def faster_rcnn_resnet101_v1d_coco(
pretrained=False, pretrained_base=True, **kwargs
):
r"""Faster RCNN model from the paper r"""Faster RCNN model from the paper
"Ren, S., He, K., Girshick, R., & Sun, J. (2015). Faster r-cnn: Towards "Ren, S., He, K., Girshick, R., & Sun, J. (2015). Faster r-cnn: Towards
real-time object detection with region proposal networks" real-time object detection with region proposal networks"
...@@ -666,34 +962,73 @@ def faster_rcnn_resnet101_v1d_coco(pretrained=False, pretrained_base=True, **kwa ...@@ -666,34 +962,73 @@ def faster_rcnn_resnet101_v1d_coco(pretrained=False, pretrained_base=True, **kwa
>>> model = get_faster_rcnn_resnet101_v1d_coco(pretrained=True) >>> model = get_faster_rcnn_resnet101_v1d_coco(pretrained=True)
>>> print(model) >>> print(model)
""" """
from gluoncv.model_zoo.resnetv1b import resnet101_v1d
from gluoncv.data import COCODetection from gluoncv.data import COCODetection
from gluoncv.model_zoo.resnetv1b import resnet101_v1d
classes = COCODetection.CLASSES classes = COCODetection.CLASSES
pretrained_base = False if pretrained else pretrained_base pretrained_base = False if pretrained else pretrained_base
base_network = resnet101_v1d(pretrained=pretrained_base, dilated=False, base_network = resnet101_v1d(
use_global_stats=True, **kwargs) pretrained=pretrained_base,
dilated=False,
use_global_stats=True,
**kwargs
)
features = nn.HybridSequential() features = nn.HybridSequential()
top_features = nn.HybridSequential() top_features = nn.HybridSequential()
for layer in ['conv1', 'bn1', 'relu', 'maxpool', 'layer1', 'layer2', 'layer3']: for layer in [
"conv1",
"bn1",
"relu",
"maxpool",
"layer1",
"layer2",
"layer3",
]:
features.add(getattr(base_network, layer)) features.add(getattr(base_network, layer))
for layer in ['layer4']: for layer in ["layer4"]:
top_features.add(getattr(base_network, layer)) top_features.add(getattr(base_network, layer))
train_patterns = '|'.join(['.*dense', '.*rpn', '.*down(2|3|4)_conv', '.*layers(2|3|4)_conv']) train_patterns = "|".join(
[".*dense", ".*rpn", ".*down(2|3|4)_conv", ".*layers(2|3|4)_conv"]
)
return get_faster_rcnn( return get_faster_rcnn(
name='resnet101_v1d', dataset='coco', pretrained=pretrained, name="resnet101_v1d",
features=features, top_features=top_features, classes=classes, dataset="coco",
short=800, max_size=1333, train_patterns=train_patterns, pretrained=pretrained,
nms_thresh=0.5, nms_topk=-1, post_nms=100, features=features,
roi_mode='align', roi_size=(14, 14), strides=16, clip=4.14, top_features=top_features,
rpn_channel=1024, base_size=16, scales=(2, 4, 8, 16, 32), classes=classes,
ratios=(0.5, 1, 2), alloc_size=(128, 128), rpn_nms_thresh=0.7, short=800,
rpn_train_pre_nms=12000, rpn_train_post_nms=2000, max_size=1333,
rpn_test_pre_nms=6000, rpn_test_post_nms=1000, rpn_min_size=1, train_patterns=train_patterns,
num_sample=128, pos_iou_thresh=0.5, pos_ratio=0.25, max_num_gt=3000, nms_thresh=0.5,
**kwargs) nms_topk=-1,
post_nms=100,
def faster_rcnn_resnet101_v1d_custom(classes, transfer=None, pretrained_base=True, roi_mode="align",
pretrained=False, **kwargs): roi_size=(14, 14),
strides=16,
clip=4.14,
rpn_channel=1024,
base_size=16,
scales=(2, 4, 8, 16, 32),
ratios=(0.5, 1, 2),
alloc_size=(128, 128),
rpn_nms_thresh=0.7,
rpn_train_pre_nms=12000,
rpn_train_post_nms=2000,
rpn_test_pre_nms=6000,
rpn_test_post_nms=1000,
rpn_min_size=1,
num_sample=128,
pos_iou_thresh=0.5,
pos_ratio=0.25,
max_num_gt=3000,
**kwargs
)
def faster_rcnn_resnet101_v1d_custom(
classes, transfer=None, pretrained_base=True, pretrained=False, **kwargs
):
r"""Faster RCNN model with resnet101_v1d base network on custom dataset. r"""Faster RCNN model with resnet101_v1d base network on custom dataset.
Parameters Parameters
...@@ -717,31 +1052,69 @@ def faster_rcnn_resnet101_v1d_custom(classes, transfer=None, pretrained_base=Tru ...@@ -717,31 +1052,69 @@ def faster_rcnn_resnet101_v1d_custom(classes, transfer=None, pretrained_base=Tru
Hybrid faster RCNN network. Hybrid faster RCNN network.
""" """
if pretrained: if pretrained:
warnings.warn("Custom models don't provide `pretrained` weights, ignored.") warnings.warn(
"Custom models don't provide `pretrained` weights, ignored."
)
if transfer is None: if transfer is None:
from gluoncv.model_zoo.resnetv1b import resnet101_v1d from gluoncv.model_zoo.resnetv1b import resnet101_v1d
base_network = resnet101_v1d(pretrained=pretrained_base, dilated=False,
use_global_stats=True, **kwargs) base_network = resnet101_v1d(
pretrained=pretrained_base,
dilated=False,
use_global_stats=True,
**kwargs
)
features = nn.HybridSequential() features = nn.HybridSequential()
top_features = nn.HybridSequential() top_features = nn.HybridSequential()
for layer in ['conv1', 'bn1', 'relu', 'maxpool', 'layer1', 'layer2', 'layer3']: for layer in [
"conv1",
"bn1",
"relu",
"maxpool",
"layer1",
"layer2",
"layer3",
]:
features.add(getattr(base_network, layer)) features.add(getattr(base_network, layer))
for layer in ['layer4']: for layer in ["layer4"]:
top_features.add(getattr(base_network, layer)) top_features.add(getattr(base_network, layer))
train_patterns = '|'.join(['.*dense', '.*rpn', '.*down(2|3|4)_conv', train_patterns = "|".join(
'.*layers(2|3|4)_conv']) [".*dense", ".*rpn", ".*down(2|3|4)_conv", ".*layers(2|3|4)_conv"]
)
return get_faster_rcnn( return get_faster_rcnn(
name='resnet101_v1d', dataset='custom', pretrained=pretrained, name="resnet101_v1d",
features=features, top_features=top_features, classes=classes, dataset="custom",
short=600, max_size=1000, train_patterns=train_patterns, pretrained=pretrained,
nms_thresh=0.5, nms_topk=400, post_nms=100, features=features,
roi_mode='align', roi_size=(14, 14), strides=16, clip=4.14, top_features=top_features,
rpn_channel=1024, base_size=16, scales=(2, 4, 8, 16, 32), classes=classes,
ratios=(0.5, 1, 2), alloc_size=(128, 128), rpn_nms_thresh=0.7, short=600,
rpn_train_pre_nms=12000, rpn_train_post_nms=2000, max_size=1000,
rpn_test_pre_nms=6000, rpn_test_post_nms=300, rpn_min_size=16, train_patterns=train_patterns,
num_sample=128, pos_iou_thresh=0.5, pos_ratio=0.25, max_num_gt=3000, nms_thresh=0.5,
**kwargs) nms_topk=400,
post_nms=100,
roi_mode="align",
roi_size=(14, 14),
strides=16,
clip=4.14,
rpn_channel=1024,
base_size=16,
scales=(2, 4, 8, 16, 32),
ratios=(0.5, 1, 2),
alloc_size=(128, 128),
rpn_nms_thresh=0.7,
rpn_train_pre_nms=12000,
rpn_train_post_nms=2000,
rpn_test_pre_nms=6000,
rpn_test_post_nms=300,
rpn_min_size=16,
num_sample=128,
pos_iou_thresh=0.5,
pos_ratio=0.25,
max_num_gt=3000,
**kwargs
)
else: else:
net = faster_rcnn_resnet101_v1d_coco(pretrained=True) net = faster_rcnn_resnet101_v1d_coco(pretrained=True)
reuse_classes = [x for x in classes if x in net.classes] reuse_classes = [x for x in classes if x in net.classes]
......
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