From 0f773cd605c78213fb1248619837606068453681 Mon Sep 17 00:00:00 2001 From: Theheavens <34649403+Theheavens@users.noreply.github.com> Date: Tue, 14 Sep 2021 13:43:02 +0800 Subject: [PATCH] a nightly update --- README.md | 4 +- openhgnn/output/RHGNN/README.md | 2 +- openhgnn/trainerflow/node_classification.py | 10 +- space4hgnn/__init__.py | 0 space4hgnn/config.yaml | 595 -------------------- space4hgnn/generate_yaml.py | 84 --- space4hgnn/homo_models/GAT.py | 90 --- space4hgnn/homo_models/GCN.py | 75 --- space4hgnn/homo_models/__init__.py | 0 space4hgnn/homo_models/homo_GNN.py | 66 --- space4hgnn/metapath_models/__init__.py | 0 space4hgnn/metapath_models/layers.py | 0 space4hgnn/metapath_models/mp_GNN.py | 81 --- space4hgnn/models/MLP.py | 37 -- space4hgnn/models/__init__.py | 0 space4hgnn/models/activate.py | 16 - space4hgnn/models/layers.py | 204 ------- space4hgnn/models/skipgnn.py | 104 ---- space4hgnn/node_classification.py | 38 -- space4hgnn/relation_models/__init__.py | 1 - space4hgnn/relation_models/layers.py | 62 -- space4hgnn/relation_models/rel_HGNN.py | 169 ------ space4hgnn/utils.py | 47 -- 23 files changed, 11 insertions(+), 1674 deletions(-) delete mode 100644 space4hgnn/__init__.py delete mode 100644 space4hgnn/config.yaml delete mode 100644 space4hgnn/generate_yaml.py delete mode 100644 space4hgnn/homo_models/GAT.py delete mode 100644 space4hgnn/homo_models/GCN.py delete mode 100644 space4hgnn/homo_models/__init__.py delete mode 100644 space4hgnn/homo_models/homo_GNN.py delete mode 100644 space4hgnn/metapath_models/__init__.py delete mode 100644 space4hgnn/metapath_models/layers.py delete mode 100644 space4hgnn/metapath_models/mp_GNN.py delete mode 100644 space4hgnn/models/MLP.py delete mode 100644 space4hgnn/models/__init__.py delete mode 100644 space4hgnn/models/activate.py delete mode 100644 space4hgnn/models/layers.py delete mode 100644 space4hgnn/models/skipgnn.py delete mode 100644 space4hgnn/node_classification.py delete mode 100644 space4hgnn/relation_models/__init__.py delete mode 100644 space4hgnn/relation_models/layers.py delete mode 100644 space4hgnn/relation_models/rel_HGNN.py delete mode 100644 space4hgnn/utils.py diff --git a/README.md b/README.md index e04aaccf..b395a756 100644 --- a/README.md +++ b/README.md @@ -120,9 +120,9 @@ The link will give some basic usage. ## Contributors -**[GAMMA LAB](https://github.com/BUPT-GAMMA) [BUPT]**: [Tianyu Zhao](https://github.com/Theheavens), Cheng Yang, Xiao Wang, [Chuan Shi](http://shichuan.org/) +**[GAMMA LAB](https://github.com/BUPT-GAMMA) [BUPT]**: [Tianyu Zhao](https://github.com/Theheavens), Yaoqi Liu, Fengqi Liang, Yibo Li, Yanhu Mo, Donglin Xia, Xinlong Zhai, Siyuan Zhang, Qi Zhang, [Chuan Shi](http://shichuan.org/), Cheng Yang, Xiao Wang -**BUPT**: Jiahang Li +**BUPT**: Jiahang Li, Anke Hu **DGL Team**: Quan Gan, [Jian Zhang](https://github.com/zhjwy9343) diff --git a/openhgnn/output/RHGNN/README.md b/openhgnn/output/RHGNN/README.md index f24db31c..2a756035 100644 --- a/openhgnn/output/RHGNN/README.md +++ b/openhgnn/output/RHGNN/README.md @@ -29,7 +29,7 @@ Node classification | |accuracy| |----|----| -|imdb4GTN|xxx| +|imdb4GTN|0.5883| ## TrainerFlow: node_classification diff --git a/openhgnn/trainerflow/node_classification.py b/openhgnn/trainerflow/node_classification.py index 80b3df5b..3fd202a2 100644 --- a/openhgnn/trainerflow/node_classification.py +++ b/openhgnn/trainerflow/node_classification.py @@ -13,9 +13,9 @@ class NodeClassification(BaseFlow): r""" Node classification flow means - The task is to classify the nodes of HIN(Heterogeneous Information Network). + The task is to classify the nodes of Heterogeneous graph. - Note: If the output dim is not equal the number of classes, a MLP will follow the gnn model. + Note: If the output dim is not equal the number of classes, we will modify the output dim with the number of classes. """ def __init__(self, args): @@ -53,6 +53,12 @@ def __init__(self, args): batch_size=self.args.batch_size, device=self.device, shuffle=True, num_workers=0) def preprocess(self): + r""" + Preprocess for different models, e.g.: different optimizer for GTN. + And prepare the dataloader foe train validation and test. + Last, we will call preprocess_feature. + + """ if self.args.model == 'GTN': if hasattr(self.args, 'adaptive_lr_flag') and self.args.adaptive_lr_flag == True: self.optimizer = torch.optim.Adam([{'params': self.model.gcn.parameters()}, diff --git a/space4hgnn/__init__.py b/space4hgnn/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/space4hgnn/config.yaml b/space4hgnn/config.yaml deleted file mode 100644 index 236289fb..00000000 --- a/space4hgnn/config.yaml +++ /dev/null @@ -1,595 +0,0 @@ -node_classification: - HGBn-ACM: - homo_GNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - gcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - relation_HGNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - rgcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - mp_GNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - hanconv - macro_func: - attention - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - GCN: - hidden_dim: - 64 - num_layers: - 2 - dropout: - 0.5 - lr: - 0.0005 - weight_decay: - 0.0001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - activation: - relu - GAT: - hidden_dim: - 64 - num_layers: - 2 - dropout: - 0.5 - slope: - 0.05 - num_heads: - 8 - lr: - 0.0005 - weight_decay: - 0.0001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - HGBn-DBLP: - homo_GNN: - hidden_dim: - 64 - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - activation: - relu - dropout: - 0.5 - has_l2norm: - False - has_bn: - True - stage_type: - skipsum - gnn_type: - gcnconv - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - - mp_GNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - hanconv - macro_func: - attention - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - relation_HGNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - rgcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - GCN: - hidden_dim: - 64 - num_layers: - 2 - dropout: - 0.5 - lr: - 0.0005 - weight_decay: - 0.0001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - activation: - relu - HGBn-Freebase: - homo_GNN: - hidden_dim: - 64 - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 2 - activation: - relu - dropout: - 0.5 - has_l2norm: - False - has_bn: - False - stage_type: - stack - gnn_type: - gcnconv - lr: - 0.001 - weight_decay: - 0.0001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - relation_HGNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - rgcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - mp_GNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - hanconv - macro_func: - attention - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - HGBn-IMDB: - homo_GNN: - hidden_dim: - 64 - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 2 - activation: - relu - dropout: - 0.5 - has_l2norm: - False - has_bn: - False - stage_type: - stack - gnn_type: - gcnconv - lr: - 0.001 - weight_decay: - 0.0001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - mp_GNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - hanconv - macro_func: - attention - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - relation_HGNN: - hidden_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - rgcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - -link_prediction: - HGBl-amazon: - homo_GNN: - hidden_dim: - 64 - out_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - gcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - HGBl-PubMed: - homo_GNN: - hidden_dim: - 64 - out_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - gcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False - - HGBl-LastFM: - homo_GNN: - hidden_dim: - 64 - out_dim: - 64 - - layers_pre_mp: - 1 - layers_post_mp: - 1 - layers_gnn: - 3 - stage_type: - stack - - activation: - relu - dropout: - 0.5 - has_bn: - False - gnn_type: - gcnconv - - has_l2norm: - False - lr: - 0.001 - weight_decay: - 0.000001 - patience: - 30 - max_epoch: - 300 - mini_batch_flag: - False diff --git a/space4hgnn/generate_yaml.py b/space4hgnn/generate_yaml.py deleted file mode 100644 index e828422e..00000000 --- a/space4hgnn/generate_yaml.py +++ /dev/null @@ -1,84 +0,0 @@ -import yaml -from random import choice -from random import randint -from random import random -from random import uniform -import argparse -import os -hidden_dim = [64] -layers_pre_mp = [1,2,3] -layers_post_mp = [1,2,3] -layers_gnn = [2,4,6,8] -stage_type = ['stack','skipsum','skipconcat'] -activation = ['relu'] -has_bn = [True, False] -has_l2norm = [True, False] -mini_batch_flag = [False] -macro_func = ['attention', 'sum', 'mean','max'] -dropout = [0.0, 0.3, 0.6] -lr = [0.1, 0.01, 0.001] -weight_decay = 0.0001 -patience = 40 -max_epoch = 5 - - -def makeDict(aggr, key, value): - dict = { - 'hidden_dim': choice(hidden_dim), - 'layers_pre_mp': choice(layers_pre_mp), - 'layers_post_mp': choice(layers_post_mp), - 'layers_gnn': choice(layers_gnn), - 'stage_type': choice(stage_type), - 'activation': choice(activation), - 'dropout': choice(dropout), - 'has_bn': choice(has_bn), - - 'has_l2norm': choice(has_l2norm), - 'lr': choice(lr), - 'weight_decay': weight_decay, - 'patience': patience, - 'max_epoch': max_epoch, - 'mini_batch_flag': choice(mini_batch_flag), - 'macro_func': choice(macro_func), - 'gnn_type': aggr, - } - dict[key] = value - return dict - -def generate(aggr, i, key, value): - datasets = ['HGBn-ACM', 'HGBn-IMDB', 'HGBn-DBLP', 'HGBn-Freebase'] - models = ['homo_GNN', 'relation_HGNN', 'mp_GNN'] - dicts = {} - if key == 'has_bn' or key == 'has_l2norm' or key == mini_batch_flag: - value = value == "True" - elif key == 'stage_type' or key == 'activation' or key == 'macro_func': - value = value - else: - value = float(value) - for a in datasets: - dict = {} - for b in models: - dict[b] = makeDict(aggr, key, value) - dicts[a] = dict - aproject = {'node_classification': dicts - } - - fileNamePath = os.path.split(os.path.realpath(__file__))[0] - if not os.path.exists('./space4hgnn/config'): - os.makedirs('./space4hgnn/config') - if not os.path.exists('./space4hgnn/config/{}_{}'.format(key, value)): - os.makedirs('./space4hgnn/config/{}_{}'.format(key, value)) - name = 'config/{}_{}/'.format(key, value) + aggr + '_' + i + '.yaml' - yamlPath = os.path.join(fileNamePath, name) - - f = open(yamlPath,'w') - print(yaml.dump(aproject,f)) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--aggr', '-a', default='gcnconv', type=str, help='gnn type') - parser.add_argument('--times', '-s', default='1', type=str, help='times') - parser.add_argument('--key', '-k', default='has_bn', type=str, help='attribute') - parser.add_argument('--value', '-v', default='', type=str, help='choice') - args = parser.parse_args() - generate(args.aggr, args.times, args.key, args.value) \ No newline at end of file diff --git a/space4hgnn/homo_models/GAT.py b/space4hgnn/homo_models/GAT.py deleted file mode 100644 index 36f120bb..00000000 --- a/space4hgnn/homo_models/GAT.py +++ /dev/null @@ -1,90 +0,0 @@ - -import torch -import torch.nn as nn -import dgl -import torch.nn.functional as F -import dgl.function as fn -from dgl.nn.pytorch import edge_softmax, GATConv -from openhgnn.models import BaseModel, register_model, hetero_linear - - -@register_model('GAT') -class GAT(BaseModel): - @classmethod - def build_model_from_args(cls, args, hg): - heads = [args.num_heads] * args.num_layers + [1] - return cls(hg, - args.hidden_dim, - args.out_dim, - args.num_layers, - heads, - F.elu, - args.dropout, - args.dropout, - args.slope, - False) - - def __init__(self, - hg, - num_hidden, - num_classes, - num_layers, - heads, - activation, - feat_drop, - attn_drop, - negative_slope, - residual): - super(GAT, self).__init__() - self.hg = hg - self.num_layers = num_layers - self.gat_layers = nn.ModuleList() - self.activation = activation - - # input projection (no residual) - self.gat_layers.append(GATConv( - num_hidden, num_hidden, heads[0], - feat_drop, attn_drop, negative_slope, False, self.activation)) - # hidden layers - for l in range(1, num_layers): - # due to multi-head, the in_dim = num_hidden * num_heads - self.gat_layers.append(GATConv( - num_hidden * heads[l - 1], num_hidden, heads[l], - feat_drop, attn_drop, negative_slope, residual, self.activation)) - # output projection - self.gat_layers.append(GATConv( - num_hidden * heads[-2], num_classes, heads[-1], - feat_drop, attn_drop, negative_slope, residual, None)) - - - linear_list1 = [] - for ntype in self.hg.ntypes: - in_dim = self.hg.nodes[ntype].data['h'].shape[1] - linear_list1.append((ntype, in_dim, num_hidden)) - # * ================== Project feature Layer================== - self.hetero_linear = hetero_linear(linear_list1) - - - def forward(self, hg): - with hg.local_scope(): - hg.ndata['h'] = self.hetero_linear(hg.ndata['h']) - homo_g = dgl.to_homogeneous(hg, ndata=['h']) - homo_g = dgl.remove_self_loop(homo_g) - homo_g = dgl.add_self_loop(homo_g) - h = homo_g.ndata.pop('h') - - for l in range(self.num_layers): - h = self.gat_layers[l](homo_g, h).flatten(1) - # output projection - h = self.gat_layers[-1](homo_g, h).mean(1) - # homo_g.ndata['out_h'] = h - # out_h = dgl.to_heterogeneous(homo_g, hg.ntypes, hg.etypes).ndata['out_h'] - out_h = self.h2dict(h, hg.ndata['h']) - return out_h - - def h2dict(self, h, hdict): - pre = 0 - for i, value in hdict.items(): - hdict[i] = h[pre:value.shape[0]+pre] - pre += value.shape[0] - return hdict \ No newline at end of file diff --git a/space4hgnn/homo_models/GCN.py b/space4hgnn/homo_models/GCN.py deleted file mode 100644 index e1183569..00000000 --- a/space4hgnn/homo_models/GCN.py +++ /dev/null @@ -1,75 +0,0 @@ -import dgl -import torch.nn as nn -import torch.nn.functional as F -from dgl.nn.pytorch import GraphConv -from openhgnn.models import BaseModel, register_model, hetero_linear - - -@register_model('GCN') -class GCN(BaseModel): - @classmethod - def build_model_from_args(cls, args, hg): - - return cls(hg, - args.in_dim, - args.hidden_dim, - args.out_dim, - args.num_layers, - F.elu, - args.dropout) - - def __init__(self, - hg, - in_feats, - n_hidden, - n_classes, - n_layers, - activation, - dropout): - super(GCN, self).__init__() - self.hg = hg - self.layers = nn.ModuleList() - # input layer - #self.layers.append(GraphConv(n_hidden, n_hidden, activation=activation)) - # hidden layers - for i in range(n_layers): - self.layers.append(GraphConv(n_hidden, n_hidden, activation=activation)) - # output layer - self.layers.append(GraphConv(n_hidden, n_classes)) - self.dropout = nn.Dropout(p=dropout) - - - linear_list1 = [] - for ntype in self.hg.ntypes: - in_dim = self.hg.nodes[ntype].data['h'].shape[1] - linear_list1.append((ntype, in_dim, n_hidden)) - # * ================== Project feature Layer================== - self.hetero_linear = hetero_linear(linear_list1) - #self.preprocess() - - def preprocess(self): - self.g = dgl.to_homogeneous(self.hg) - self.h = self.g.ndata.pop('h') - - def forward(self, hg): - with hg.local_scope(): - hg.ndata['h'] = self.hetero_linear(hg.ndata['h']) - homo_g = dgl.to_homogeneous(hg, ndata=['h']) - homo_g = dgl.remove_self_loop(homo_g) - homo_g = dgl.add_self_loop(homo_g) - h = homo_g.ndata.pop('h') - for i, layer in enumerate(self.layers): - if i != 0: - h = self.dropout(h) - h = layer(homo_g, h) - # homo_g.ndata['out_h'] = h - # out_h = dgl.to_heterogeneous(homo_g, hg.ntypes, hg.etypes).ndata['out_h'] - out_h = self.h2dict(h, hg.ndata['h']) - return out_h - - def h2dict(self, h, hdict): - pre = 0 - for i, value in hdict.items(): - hdict[i] = h[pre:value.shape[0]+pre] - pre += value.shape[0] - return hdict \ No newline at end of file diff --git a/space4hgnn/homo_models/__init__.py b/space4hgnn/homo_models/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/space4hgnn/homo_models/homo_GNN.py b/space4hgnn/homo_models/homo_GNN.py deleted file mode 100644 index 0170a462..00000000 --- a/space4hgnn/homo_models/homo_GNN.py +++ /dev/null @@ -1,66 +0,0 @@ -import dgl -from space4hgnn.models.MLP import HGNNPostMP, HGNNPreMP -from openhgnn.models import BaseModel, register_model -from space4hgnn.models.skipgnn import stage_dict - - -@register_model('homo_GNN') -class homo_GNN(BaseModel): - r""" - General homogeneous GNN model for HGNN - HeteroMLP + HomoGNN + HeteroMLP - """ - @classmethod - def build_model_from_args(cls, args, hg): - out_node_type = args.out_node_type - return cls(args, hg, out_node_type) - - def __init__(self, args, hg, out_node_type, **kwargs): - super(homo_GNN, self).__init__() - self.out_node_type = out_node_type - if args.layers_pre_mp - 1 > 0: - self.pre_mp = HGNNPreMP(args, hg.ntypes, args.layers_pre_mp, args.hidden_dim, args.hidden_dim) - - if args.layers_gnn > 0: - GNNStage = stage_dict[args.stage_type] - self.gnn = GNNStage(gnn_type=args.gnn_type, - stage_type=args.stage_type, - dim_in=args.hidden_dim, - dim_out=args.hidden_dim, - num_layers=args.layers_gnn, - skip_every=1, - dropout=args.dropout, - act=args.activation, - has_bn=args.has_bn, - has_l2norm=args.has_l2norm) - - gnn_out_dim = self.gnn.dim_out - self.post_mp = HGNNPostMP(args, self.out_node_type, args.layers_post_mp, gnn_out_dim, args.out_dim) - - def forward(self, hg, h_dict): - with hg.local_scope(): - if hasattr(self, 'pre_mp'): - h_dict = self.pre_mp(h_dict) - if len(hg.ntypes) == 1: - hg.ndata['h'] = h_dict[hg.ntypes[0]] - else: - hg.ndata['h'] = h_dict - homo_g = dgl.to_homogeneous(hg, ndata=['h']) - homo_g = dgl.remove_self_loop(homo_g) - homo_g = dgl.add_self_loop(homo_g) - h = homo_g.ndata.pop('h') - if hasattr(self, 'gnn'): - h = self.gnn(homo_g, h) - out_h = self.h2dict(h, h_dict, self.out_node_type) - if hasattr(self, 'post_mp'): - out_h = self.post_mp(out_h) - return out_h - - def h2dict(self, h, hdict, node_list): - pre = 0 - out_h = {} - for i, value in hdict.items(): - if i in node_list: - out_h[i] = h[pre:value.shape[0]+pre] - pre += value.shape[0] - return out_h \ No newline at end of file diff --git a/space4hgnn/metapath_models/__init__.py b/space4hgnn/metapath_models/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/space4hgnn/metapath_models/layers.py b/space4hgnn/metapath_models/layers.py deleted file mode 100644 index e69de29b..00000000 diff --git a/space4hgnn/metapath_models/mp_GNN.py b/space4hgnn/metapath_models/mp_GNN.py deleted file mode 100644 index ee00529b..00000000 --- a/space4hgnn/metapath_models/mp_GNN.py +++ /dev/null @@ -1,81 +0,0 @@ -import dgl -import torch.nn as nn -from openhgnn.models import BaseModel, register_model -from openhgnn.utils.utils import extract_metapaths -from space4hgnn.models.skipgnn import stage_dict -from space4hgnn.models.MLP import HGNNPostMP, HGNNPreMP - -@register_model('mp_GNN') -class mp_GNN(BaseModel): - r""" - General MetaPath GNN model, e.g.: HAN, HPN - """ - @classmethod - def build_model_from_args(cls, args, hg): - return cls(args, hg) - - def __init__(self, args, hg, **kwargs): - """ - """ - super(mp_GNN, self).__init__() - self.out_node_type = args.out_node_type - self.category = list(self.out_node_type) - self.meta_paths_dict = {key: [] for key in self.category} - if args.meta_paths is None: - for key in self.category: - self.meta_paths_dict[key].append(extract_metapaths(key, hg.canonical_etypes)) - else: - for mp in args.meta_paths: - self.meta_paths_dict[mp[0][0]].append(mp) - - if args.layers_pre_mp - 1 > 0: - self.pre_mp = HGNNPreMP(args, self.out_node_type, args.layers_pre_mp, args.hidden_dim, args.hidden_dim) - - if args.layers_gnn > 0: - GNNStage = stage_dict[args.stage_type] - self.gnn = nn.ModuleDict() - for key in self.category: - self.gnn[key] = GNNStage(gnn_type=args.gnn_type, - stage_type=args.stage_type, - dim_in=args.hidden_dim, - dim_out=args.hidden_dim, - num_layers=args.layers_gnn, - skip_every=1, - dropout=args.dropout, - act=args.activation, - has_bn=args.has_bn, - has_l2norm=args.has_l2norm, - macro_func=args.macro_func, - meta_paths=self.meta_paths_dict[key]) - # d_in = self.mp.dim_out - - gnn_out_dim = self.gnn[self.category[0]].dim_out - self.post_mp = HGNNPostMP(args, self.out_node_type, args.layers_post_mp, gnn_out_dim, args.out_dim) - - self._cached_graph = None - self._cached_coalesced_graph = {} - - def forward(self, hg, h_dict): - with hg.local_scope(): - - if self._cached_graph is None or self._cached_graph is not hg: - self._cached_graph = hg - self._cached_coalesced_graph.clear() - for key, metapaths in self.meta_paths_dict.items(): - self._cached_coalesced_graph[key] = {} - for meta_path in metapaths: - mp_g = dgl.metapath_reachable_graph(hg, meta_path) - mp_g = dgl.remove_self_loop(mp_g) - mp_g = dgl.add_self_loop(mp_g) - self._cached_coalesced_graph[key][meta_path] = mp_g - out_h = {} - for key in self.category: - if hasattr(self, 'pre_mp'): - h = self.pre_mp({key: h_dict[key]}) - else: - h = {key: h_dict[key]} - if hasattr(self, 'gnn'): - h = self.gnn[key](self._cached_coalesced_graph[key], h[key]) - if hasattr(self, 'post_mp'): - out_h[key] = self.post_mp({key: h})[key] - return out_h diff --git a/space4hgnn/models/MLP.py b/space4hgnn/models/MLP.py deleted file mode 100644 index 1b1e0999..00000000 --- a/space4hgnn/models/MLP.py +++ /dev/null @@ -1,37 +0,0 @@ -from openhgnn.layers.HeteroLinear import HeteroMLPLayer -from space4hgnn.models.layers import MultiLinearLayer - - -def HGNNPreMP(args, node_types, num_pre_mp, in_dim, hidden_dim): - if num_pre_mp > 0: - linear_dict = {} - for ntype in node_types: - linear_dict[ntype] = [in_dim] - for _ in range(num_pre_mp): - linear_dict[ntype].append(hidden_dim) - return HeteroMLPLayer(linear_dict, act=args.activation, dropout=args.dropout, - has_l2norm=args.has_l2norm, has_bn=args.has_bn, final_act=True) - - -def HGNNPostMP(args, node_types, num_post_mp, hidden_dim, out_dim): - if num_post_mp > 0: - linear_dict = {} - for ntype in node_types: - linear_dict[ntype] = [hidden_dim] - for _ in range(num_post_mp-1): - linear_dict[ntype].append(hidden_dim) - linear_dict[ntype].append(out_dim) - return HeteroMLPLayer(linear_dict, act=args.activation, dropout=args.dropout, - has_l2norm=args.has_l2norm, has_bn=args.has_bn, final_act=False) - - -def GNNPreMP(args, in_dim, hidden_dim): - linear_list = [in_dim] + args.layers_pre_mp * [hidden_dim] - return MultiLinearLayer(linear_list, dropout=args.dropout, act=args.activation, has_bn=args.has_bn, - has_l2norm=args.has_l2norm) - - -def GNNPostMP(args, hidden_dim, out_dim): - linear_list = args.layers_pre_mp * [hidden_dim] + [out_dim] - return MultiLinearLayer(linear_list, dropout=args.dropout, act=args.activation, has_bn=args.has_bn, - has_l2norm=args.has_l2norm) \ No newline at end of file diff --git a/space4hgnn/models/__init__.py b/space4hgnn/models/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/space4hgnn/models/activate.py b/space4hgnn/models/activate.py deleted file mode 100644 index 195eb7ab..00000000 --- a/space4hgnn/models/activate.py +++ /dev/null @@ -1,16 +0,0 @@ -import torch.nn as nn -from space4hgnn.config import cfg -from graphgym.contrib.act import * -import graphgym.register as register - -act_dict = { - 'relu': nn.ReLU(inplace=cfg.mem.inplace), - 'selu': nn.SELU(inplace=cfg.mem.inplace), - 'prelu': nn.PReLU(), - 'elu': nn.ELU(inplace=cfg.mem.inplace), - 'lrelu_01': nn.LeakyReLU(negative_slope=0.1, inplace=cfg.mem.inplace), - 'lrelu_025': nn.LeakyReLU(negative_slope=0.25, inplace=cfg.mem.inplace), - 'lrelu_05': nn.LeakyReLU(negative_slope=0.5, inplace=cfg.mem.inplace), -} - -act_dict = {**register.act_dict, **act_dict} \ No newline at end of file diff --git a/space4hgnn/models/layers.py b/space4hgnn/models/layers.py deleted file mode 100644 index b68d7413..00000000 --- a/space4hgnn/models/layers.py +++ /dev/null @@ -1,204 +0,0 @@ -import dgl -import torch -import torch.nn as nn -import torch.nn.functional as F - -from openhgnn.layers.MetapathConv import MetapathConv -from openhgnn.models.macro_layer.SemanticConv import SemanticAttention - - -class MPConv(nn.Module): - def __init__(self, name, dim_in, dim_out, bias=False, **kwargs): - super(MPConv, self).__init__() - macro_func = kwargs['macro_func'] - meta_paths = kwargs['meta_paths'] - if macro_func == 'attention': - macro_func = SemanticAttention(dim_out) - elif macro_func == 'sum': - macro_func = Aggr_sum - elif macro_func == 'mean': - macro_func = Aggr_mean - elif macro_func == 'max': - macro_func = Aggr_max - self.model = MetapathConv( - meta_paths, - [homo_layer_dict[name](dim_in, dim_out, bias=bias) - for _ in meta_paths], - macro_func - ) - self.meta_paths = meta_paths - - def forward(self, mp_g_list, h): - h = self.model(mp_g_list, h) - return h - - -def Aggr_sum(z): - z = torch.stack(z, dim=1) - return z.sum(1) - - -def Aggr_max(z): - z = torch.stack(z, dim=1) - return z.max(1)[0] - - -def Aggr_mean(z): - z = torch.stack(z, dim=1) - return z.mean(1) - - -class GeneralLayer(nn.Module): - '''General wrapper for layers''' - - def __init__(self, name, dim_in, dim_out, dropout, act=None, has_bn=True, - has_l2norm=False, **kwargs): - super(GeneralLayer, self).__init__() - self.has_l2norm = has_l2norm - if kwargs.get('meta_paths') is not None: - self.layer = MPConv(name, dim_in, dim_out, - bias=not has_bn, **kwargs) - else: - self.layer = homo_layer_dict[name](dim_in, dim_out, - bias=not has_bn, **kwargs) - layer_wrapper = [] - if has_bn: - layer_wrapper.append(nn.BatchNorm1d(dim_out)) - if dropout > 0: - layer_wrapper.append(nn.Dropout(p=dropout)) - if act is not None: - layer_wrapper.append(act) - self.post_layer = nn.Sequential(*layer_wrapper) - - def forward(self, homo_g, h): - h = self.layer(homo_g, h) - h = self.post_layer(h) - if self.has_l2norm: - h = F.normalize(h, p=2, dim=1) - return h - - -class MultiLinearLayer(nn.Module): - def __init__(self, linear_list, dropout, act=None, has_bn=True, - has_l2norm=False, **kwargs): - super(MultiLinearLayer, self).__init__() - for i in range(len(linear_list) - 1): - d_in = linear_list[i] - d_out = linear_list[i+1] - layer = Linear(d_in, d_out, dropout, act, has_bn, has_l2norm) - self.add_module('Layer_{}'.format(i), layer) - - def forward(self, h): - for layer in self.children(): - h = layer(h) - return h - - -class Linear(nn.Module): - def __init__(self, dim_in, dim_out, dropout, act=None, has_bn=True, - has_l2norm=False, **kwargs): - super(Linear, self).__init__() - self.has_l2norm = has_l2norm - self.layer = nn.Linear(dim_in, dim_out, bias=not has_bn, **kwargs) - layer_wrapper = [] - if has_bn: - layer_wrapper.append(nn.BatchNorm1d(dim_out)) - if dropout > 0: - layer_wrapper.append(nn.Dropout(p=dropout)) - if act is not None: - layer_wrapper.append(act) - self.post_layer = nn.Sequential(*layer_wrapper) - - def forward(self, h): - h = self.layer(h) - h = self.post_layer(h) - if self.has_l2norm: - h = F.normalize(h, p=2, dim=1) - return h - - -class BatchNorm1dNode(nn.Module): - '''General wrapper for layers''' - - def __init__(self, dim_in): - super(BatchNorm1dNode, self).__init__() - self.bn = nn.BatchNorm1d(dim_in) - - def forward(self, h): - h = self.bn(h) - return h - - -# class BatchNorm1dEdge(nn.Module): -# '''General wrapper for layers''' -# -# def __init__(self, dim_in): -# super(BatchNorm1dEdge, self).__init__() -# self.bn = nn.BatchNorm1d(dim_in, eps=cfg.bn.eps, momentum=cfg.bn.mom) -# -# def forward(self, batch): -# batch.edge_feature = self.bn(batch.edge_feature) -# return batch - - -class GCNConv(nn.Module): - def __init__(self, dim_in, dim_out, bias=False, **kwargs): - super(GCNConv, self).__init__() - self.model = dgl.nn.pytorch.GraphConv(dim_in, dim_out, bias=bias, allow_zero_in_degree=True) - - def forward(self, g, h): - h = self.model(g, h) - return h - - -class SAGEConv(nn.Module): - def __init__(self, dim_in, dim_out, bias=False, **kwargs): - super(SAGEConv, self).__init__() - self.model = dgl.nn.pytorch.SAGEConv(dim_in, dim_out, aggregator_type='mean', bias=bias) - - def forward(self, g, h): - h = self.model(g, h) - return h - - -class GATConv(nn.Module): - def __init__(self, dim_in, dim_out, bias=False, **kwargs): - super(GATConv, self).__init__() - self.model = dgl.nn.pytorch.GATConv(dim_in, dim_out, num_heads=1, bias=bias, allow_zero_in_degree=True) - - def forward(self, g, h): - # Note, falatten - h = self.model(g, h).flatten(1) - return h - - -class GINConv(nn.Module): - def __init__(self, dim_in, dim_out, bias=False, **kwargs): - super(GINConv, self).__init__() - lin = nn.Sequential(nn.Linear(dim_in, dim_out, bias), nn.ReLU(), - nn.Linear(dim_out, dim_out)) - self.model = dgl.nn.pytorch.GINConv(lin, 'max') - - def forward(self, g, h): - h = self.model(g, h) - return h - - -class APPNPConv(nn.Module): - def __init__(self, dim_in, dim_out, bias=False, **kwargs): - super(APPNPConv, self).__init__() - self.model = dgl.nn.pytorch.APPNPConv(k=3, alpha=0.5) - self.lin = nn.Linear(dim_in, dim_out, bias, ) - def forward(self, g, h): - h = self.model(g, h) - h = self.lin(h) - return h - - -homo_layer_dict = { - 'gcnconv': GCNConv, - 'sageconv': SAGEConv, - 'gatconv': GATConv, - 'ginconv': GINConv, - 'appnpconv': APPNPConv -} diff --git a/space4hgnn/models/skipgnn.py b/space4hgnn/models/skipgnn.py deleted file mode 100644 index 0d8e8fba..00000000 --- a/space4hgnn/models/skipgnn.py +++ /dev/null @@ -1,104 +0,0 @@ -import torch -import torch.nn as nn -import torch.nn.functional as F -from space4hgnn.models.layers import GeneralLayer - - -def GNNLayer(gnn_type, dim_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs): - return GeneralLayer(gnn_type, dim_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs) - - -class GNNSkipBlock(nn.Module): - r""" - Skip block for HGNN - """ - - def __init__(self, gnn_type, dim_in, dim_out, num_layers, stage_type, dropout, act, has_bn, has_l2norm, *args, **kwargs): - super(GNNSkipBlock, self).__init__() - self.stage_type = stage_type - self.f = nn.ModuleList() - if num_layers == 1: - self.f.append(GNNLayer(gnn_type, dim_in, - dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - else: - for i in range(num_layers - 1): - d_in = dim_in if i == 0 else dim_out - self.f.append(GNNLayer(gnn_type, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - d_in = dim_in if num_layers == 1 else dim_out - self.f.append(GNNLayer(gnn_type, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - self.act = act - if stage_type == 'skipsum': - assert dim_in == dim_out, 'Sum skip must have same dim_in, dim_out' - - def forward(self, g, h): - h_0 = h - for layer in self.f: - h = layer(g, h) - if self.stage_type == 'skipsum': - h = h + h_0 - elif self.stage_type == 'skipconcat': - h = torch.cat((h_0, h), 1) - else: - raise ValueError('stage_type must in [skipsum, skipconcat]') - h = self.act(h) - return h - - -########### Stage: NN except start and head ############ - -class GNNStackStage(nn.Module): - '''Simple Stage that stack GNN layers''' - - def __init__(self, gnn_type, dim_in, dim_out, - num_layers, dropout, act, has_bn, has_l2norm, *args, **kwargs): - super(GNNStackStage, self).__init__() - - for i in range(num_layers): - d_in = dim_in if i == 0 else dim_out - layer = GNNLayer(gnn_type, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs) - self.add_module('layer{}'.format(i), layer) - self.dim_out = dim_out - self.has_l2norm = has_l2norm - - def forward(self, g, h): - for layer in self.children(): - h = layer(g, h) - if self.has_l2norm: - h = F.normalize(h, p=2, dim=-1) - return h - - -class GNNSkipStage(nn.Module): - ''' Stage with skip connections''' - - def __init__(self, gnn_type, stage_type,dim_in, dim_out, num_layers, - skip_every, dropout, act, has_bn, has_l2norm, *args, **kwargs): - super(GNNSkipStage, self).__init__() - assert num_layers % skip_every == 0, \ - 'cfg.gnn.skip_every must be multiples of cfg.gnn.layer_mp' \ - '(excluding head layer)' - for i in range(num_layers // skip_every): - if stage_type == 'skipsum': - d_in = dim_in if i == 0 else dim_out - elif stage_type == 'skipconcat': - d_in = dim_in if i == 0 else dim_in + i * dim_out - block = GNNSkipBlock(gnn_type, d_in, dim_out, skip_every, stage_type, dropout, act, has_bn, has_l2norm, **kwargs) - self.add_module('block{}'.format(i), block) - if stage_type == 'skipconcat': - self.dim_out = d_in + dim_out - else: - self.dim_out = dim_out - self.has_l2norm = has_l2norm - - def forward(self, g, h): - for layer in self.children(): - h = layer(g, h) - if self.has_l2norm: - h = F.normalize(h, p=2, dim=-1) - return h - -stage_dict = { - 'stack': GNNStackStage, - 'skipsum': GNNSkipStage, - 'skipconcat': GNNSkipStage, -} \ No newline at end of file diff --git a/space4hgnn/node_classification.py b/space4hgnn/node_classification.py deleted file mode 100644 index 62caa5b9..00000000 --- a/space4hgnn/node_classification.py +++ /dev/null @@ -1,38 +0,0 @@ -import argparse -from openhgnn.utils import set_random_seed, set_best_config -from openhgnn.trainerflow import build_flow -from openhgnn.auto import hpo_experiment -from space4hgnn.utils import read_config - -def OpenHGNN(args): - if not getattr(args, 'seed', False): - args.seed = 0 - set_random_seed(args.seed) - - if getattr(args, "use_best_config", False): - args = set_best_config(args) - - print(args) - if getattr(args, "use_hpo", False): - # hyper-parameter search - hpo_experiment(args, 'node_classification') - else: - flow = build_flow(args, 'node_classification') - result = flow.train() - return result - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--model', '-m', default='GCN', type=str, help='name of models') - parser.add_argument('--task', '-t', default='node_classification', type=str, help='name of task') - # link_prediction / node_classification - parser.add_argument('--dataset', '-d', default='HGBn-dblp', type=str, help='name of datasets') - parser.add_argument('--gpu', '-g', default='0', type=int, help='-1 means cpu') - parser.add_argument('--use_best_config', action='store_true', help='use best config') - parser.add_argument('--use_hpo', action='store_true', help='use hpo') - args = parser.parse_args() - - args = read_config(args) - #config = Config(file_path=config_file, model=args.model, dataset=args.dataset, task=args.task, gpu=args.gpu) - OpenHGNN(args=args) diff --git a/space4hgnn/relation_models/__init__.py b/space4hgnn/relation_models/__init__.py deleted file mode 100644 index f9f28701..00000000 --- a/space4hgnn/relation_models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .rel_HGNN import relation_HGNN \ No newline at end of file diff --git a/space4hgnn/relation_models/layers.py b/space4hgnn/relation_models/layers.py deleted file mode 100644 index 030ba380..00000000 --- a/space4hgnn/relation_models/layers.py +++ /dev/null @@ -1,62 +0,0 @@ -import torch -import torch.nn as nn -import torch.nn.functional as F - -import dgl -from dgl.nn.pytorch import GraphConv, HeteroGraphConv -from openhgnn.models.macro_layer.SemanticConv import SemanticAttention -from ..models.layers import homo_layer_dict - -class HeteroGeneralLayer(nn.Module): - '''General wrapper for layers''' - - def __init__(self, name, rel_names, dim_in, dim_out, dropout, act=None, has_bn=True, - has_l2norm=False, **kwargs): - super(HeteroGeneralLayer, self).__init__() - self.has_l2norm = has_l2norm - has_bn = has_bn - self.layer = RelationConv(name, rel_names, dim_in, dim_out, - bias=not has_bn, **kwargs) - layer_wrapper = [] - if has_bn: - layer_wrapper.append(nn.BatchNorm1d(dim_out)) - if dropout > 0: - layer_wrapper.append(nn.Dropout(p=dropout)) - if act is not None: - layer_wrapper.append(act) - self.post_layer = nn.Sequential(*layer_wrapper) - - def forward(self, g, h_dict): - h_dict = self.layer(g, h_dict) - if self.has_l2norm: - for name, batch_h in h_dict.items(): - h_dict[name] = F.normalize(self.post_layer(batch_h), p=2, dim=-1) - return h_dict - - -class BatchNorm1dNode(nn.Module): - '''General wrapper for layers''' - - def __init__(self, dim_in): - super(BatchNorm1dNode, self).__init__() - self.bn = nn.BatchNorm1d(dim_in) - - def forward(self, h): - h = self.bn(h) - return h - - -class RelationConv(nn.Module): - def __init__(self, name, rel_names, dim_in, dim_out, bias=False, **kwargs): - super(RelationConv, self).__init__() - macro_func = kwargs['macro_func'] - if macro_func == 'attention': - macro_func = SemanticAttention(dim_out) - self.model = HeteroGraphConv({ - rel: homo_layer_dict[name](dim_in, dim_out, bias=bias) - for rel in rel_names - }, aggregate=macro_func) - - def forward(self, g, h_dict): - h_dict = self.model(g, h_dict) - return h_dict diff --git a/space4hgnn/relation_models/rel_HGNN.py b/space4hgnn/relation_models/rel_HGNN.py deleted file mode 100644 index d11419b8..00000000 --- a/space4hgnn/relation_models/rel_HGNN.py +++ /dev/null @@ -1,169 +0,0 @@ -import dgl -import torch -import torch.nn as nn -import torch.nn.functional as F - -from .layers import HeteroGeneralLayer -from openhgnn.models import BaseModel, register_model -from space4hgnn.models.MLP import HGNNPostMP, HGNNPreMP -########### Layer ############ - -def HGNNLayer(gnn_type, rel_names, dim_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs): - return HeteroGeneralLayer(gnn_type, rel_names, dim_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs) - - -########### Block: multiple layers ############ - -class HGNNSkipBlock(nn.Module): - '''Skip block for HGNN''' - - def __init__(self, gnn_type, rel_names, dim_in, dim_out, num_layers, - stage_type, dropout, act, has_bn, has_l2norm, **kwargs): - super(HGNNSkipBlock, self).__init__() - self.stage_type = stage_type - self.f = nn.ModuleList() - if num_layers == 1: - self.f.append(HGNNLayer(gnn_type, rel_names, dim_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - else: - self.f = [] - for i in range(num_layers - 1): - d_in = dim_in if i == 0 else dim_out - self.f.append(HGNNLayer(gnn_type, rel_names, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - d_in = dim_in if num_layers == 1 else dim_out - self.f.append(HGNNLayer(gnn_type, rel_names, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs)) - self.act = act - if stage_type == 'skipsum': - assert dim_in == dim_out, 'Sum skip must have same dim_in, dim_out' - - def forward(self, g, h): - h_0 = h - for layer in self.f: - h = layer(g, h) - out_h = {} - for key, value in h_0.items(): - - if self.stage_type == 'skipsum': - out_h[key] = self.act(h[key] + h_0[key]) - elif self.stage_type == 'skipconcat': - out_h[key] = self.act(torch.cat((h[key], h_0[key]), 1)) - else: - raise ValueError('stage_type must in [skipsum, skipconcat]') - - return out_h - - -########### Stage: NN except start and head ############ - -class HGNNStackStage(nn.Module): - '''Simple Stage that stack GNN layers''' - - def __init__(self, gnn_type, rel_names, stage_type, dim_in, dim_out, - num_layers, skip_every, dropout, act, has_bn, has_l2norm, **kwargs): - super(HGNNStackStage, self).__init__() - - for i in range(num_layers): - d_in = dim_in if i == 0 else dim_out - layer = HGNNLayer(gnn_type, rel_names, d_in, dim_out, dropout, act, has_bn, has_l2norm, **kwargs) - self.add_module('layer{}'.format(i), layer) - self.dim_out = dim_out - self.has_l2norm = has_l2norm - - def forward(self, g, h_dict): - for layer in self.children(): - h_dict = layer(g, h_dict) - if self.has_l2norm: - for name, batch_h in h_dict.items(): - h_dict[name] = F.normalize(batch_h, p=2, dim=-1) - return h_dict - - -class HGNNSkipStage(nn.Module): - ''' Stage with skip connections''' - - def __init__(self, gnn_type, rel_names, stage_type, dim_in, dim_out, - num_layers, skip_every, dropout, act, has_bn, has_l2norm, **kwargs): - super(HGNNSkipStage, self).__init__() - assert num_layers % skip_every == 0, \ - 'cfg.gnn.skip_every must be multiples of cfg.gnn.layer_mp' \ - '(excluding head layer)' - for i in range(num_layers // skip_every): - if stage_type == 'skipsum': - d_in = dim_in if i == 0 else dim_out - elif stage_type == 'skipconcat': - d_in = dim_in if i == 0 else dim_in + i * dim_out - block = HGNNSkipBlock(gnn_type, rel_names, d_in, dim_out, skip_every, stage_type, dropout, act, has_bn, has_l2norm, **kwargs) - self.add_module('block{}'.format(i), block) - if stage_type == 'skipconcat': - self.dim_out = d_in + dim_out - else: - self.dim_out = dim_out - self.has_l2norm = has_l2norm - - def forward(self, g, h_dict): - for layer in self.children(): - h_dict = layer(g, h_dict) - if self.has_l2norm: - for name, batch_h in h_dict.items(): - h_dict[name] = F.normalize(batch_h, p=2, dim=-1) - return h_dict - - -stage_dict = { - 'stack': HGNNStackStage, - 'skipsum': HGNNSkipStage, - 'skipconcat': HGNNSkipStage, -} - - -########### Model: start + stage + head ############ - -@register_model('relation_HGNN') -class relation_HGNN(BaseModel): - '''General homogeneous GNN model''' - @classmethod - def build_model_from_args(cls, args, hg): - out_node_type = args.out_node_type - return cls(args, hg, out_node_type) - - def __init__(self, args, hg, out_node_type, **kwargs): - """ - """ - super(relation_HGNN, self).__init__() - self.out_node_type = out_node_type - if args.layers_pre_mp - 1 > 0: - self.pre_mp = HGNNPreMP(args, hg.ntypes, args.layers_pre_mp, args.hidden_dim, args.hidden_dim) - - if args.layers_gnn > 0: - HGNNStage = stage_dict[args.stage_type] - self.hgnn = HGNNStage(gnn_type=args.gnn_type, - rel_names=hg.etypes, - stage_type=args.stage_type, - dim_in=args.hidden_dim, - dim_out=args.hidden_dim, - num_layers=args.layers_gnn, - skip_every=1, - dropout=args.dropout, - act=args.activation, - has_bn=args.has_bn, - has_l2norm=args.has_l2norm, - macro_func=args.macro_func) - # d_in = self.mp.dim_out - - gnn_out_dim = self.hgnn.dim_out - self.post_mp = HGNNPostMP(args, self.out_node_type, args.layers_post_mp, gnn_out_dim, args.out_dim) - # - # self.apply(init_weights) - - def forward(self, hg, h_dict): - with hg.local_scope(): - if hasattr(self, 'pre_mp'): - h_dict = self.pre_mp(h_dict) - if hasattr(self, 'hgnn'): - h_dict = self.hgnn(hg, h_dict) - if hasattr(self, 'post_mp'): - out_h = {} - for key, value in h_dict.items(): - if key in self.out_node_type: - out_h[key] = value - out_h = self.post_mp(out_h) - return out_h \ No newline at end of file diff --git a/space4hgnn/utils.py b/space4hgnn/utils.py deleted file mode 100644 index 47bd29bb..00000000 --- a/space4hgnn/utils.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -import yaml -import torch as th -import torch.nn as nn -import numpy as np - -act_dict = { - 'relu': nn.ReLU(), - 'selu': nn.SELU(), - 'prelu': nn.PReLU(), - 'elu': nn.ELU(), - 'lrelu_01': nn.LeakyReLU(negative_slope=0.1), - 'lrelu_025': nn.LeakyReLU(negative_slope=0.25), - 'lrelu_05': nn.LeakyReLU(negative_slope=0.5), -} - - -def load_act(act): - act = act_dict.get(act, None) - if act is None: - raise ValueError('No corresponding activation') - return act - - -def read_config(args): - fileNamePath = os.path.split(os.path.realpath(__file__))[0] - yamlPath = os.path.join(fileNamePath, 'config/{}_{}/{}_{}.yaml'.format(args.key, args.value, args.aggregation, args.times)) - print(yamlPath) - with open(yamlPath, 'r', encoding='utf-8') as f: - cont = f.read() - config_dict = yaml.safe_load(cont)[args.task][args.dataset][args.model] - - if args.gpu == -1: - device = th.device('cpu') - elif args.gpu >= 0: - if th.cuda.is_available(): - device = th.device('cuda', int(args.gpu)) - else: - print("cuda is not available, please set 'gpu' -1") - for key, value in config_dict.items(): - args.__setattr__(key, value) - args.__setattr__('device', device) - args.__setattr__('_checkpoint', './space4hgnn/') - args.__setattr__('HGB_results_path', None) - args.activation = load_act(args.activation) - return args -