Exemplo n.º 1
0
    def __init__(self, args):
        self.dataset = args.dataset
        self.device = torch.device(f'cuda:{args.cuda_num}' if args.cuda else 'cpu')
        if self.dataset in ["Cora", "Citeseer", "Pubmed", 'CoauthorCS']:
            self.data = load_data(self.dataset)
            self.loss_fn = torch.nn.functional.nll_loss
        else:
            raise Exception(f'the dataset of {self.dataset} has not been implemented')

        self.miss_rate = args.miss_rate
        if self.miss_rate > 0.:
            self.data.x = remove_feature(self.data, self.miss_rate)

        self.type_model = args.type_model
        self.epochs = args.epochs
        self.grad_clip = args.grad_clip
        self.weight_decay = args.weight_decay
        if self.type_model == 'GCN':
            self.model = GCN(args)
        elif self.type_model == 'simpleGCN':
            self.model = simpleGCN(args)
        elif self.type_model == 'GAT':
            self.model = GAT(args)
        else:
            raise Exception(f'the model of {self.type_model} has not been implemented')

        self.data.to(self.device)
        self.model.to(self.device)

        self.optimizer = torch.optim.Adam(self.model.parameters(), lr=args.lr, weight_decay=args.weight_decay)
        self.seed = args.random_seed
        self.type_norm = args.type_norm
        self.skip_weight = args.skip_weight
Exemplo n.º 2
0
 def __init__(self, input_dim, hidden, output_dim):
     super(SpatialBlock, self).__init__()
     self.input_dim = input_dim
     self.output_dim = output_dim
     self.homogeneousGAT = GAT(output_dim,
                               hidden,
                               output_dim,
                               nheads=3,
                               conv=False)
     self.residual = nn.Linear(input_dim, output_dim)
Exemplo n.º 3
0
if args.cuda:
    torch.cuda.manual_seed(args.seed)

# Load data
adj, features, labels, idx_train, idx_val, idx_test = load_data()

# Model and optimizer
if args.model == 'GCN':
    model = GCN(nfeat=features.shape[1],
            nhid=args.hidden,
            nclass=labels.max().item() + 1,
            dropout=args.dropout)
else:
    model = GAT(nfeat=features.shape[1],
                nhid=args.hidden,
                nclass=labels.max().item()+1,
                dropout=args.dropout,
                num_head=args.num_head)

optimizer = optim.Adam(model.parameters(),
                       lr=args.lr, weight_decay=args.weight_decay)

if args.cuda:
    model.cuda()
    features = features.cuda()
    adj = adj.cuda()
    labels = labels.cuda()
    idx_train = idx_train.cuda()
    idx_val = idx_val.cuda()
    idx_test = idx_test.cuda()
Exemplo n.º 4
0
class trainer(object):
    def __init__(self, args):
        self.dataset = args.dataset
        self.device = torch.device(f'cuda:{args.cuda_num}' if args.cuda else 'cpu')
        if self.dataset in ["Cora", "Citeseer", "Pubmed", 'CoauthorCS']:
            self.data = load_data(self.dataset)
            self.loss_fn = torch.nn.functional.nll_loss
        else:
            raise Exception(f'the dataset of {self.dataset} has not been implemented')

        self.miss_rate = args.miss_rate
        if self.miss_rate > 0.:
            self.data.x = remove_feature(self.data, self.miss_rate)

        self.type_model = args.type_model
        self.epochs = args.epochs
        self.grad_clip = args.grad_clip
        self.weight_decay = args.weight_decay
        if self.type_model == 'GCN':
            self.model = GCN(args)
        elif self.type_model == 'simpleGCN':
            self.model = simpleGCN(args)
        elif self.type_model == 'GAT':
            self.model = GAT(args)
        else:
            raise Exception(f'the model of {self.type_model} has not been implemented')

        self.data.to(self.device)
        self.model.to(self.device)

        self.optimizer = torch.optim.Adam(self.model.parameters(), lr=args.lr, weight_decay=args.weight_decay)
        self.seed = args.random_seed
        self.type_norm = args.type_norm
        self.skip_weight = args.skip_weight


    def train_net(self):
        try:
            loss_train = self.run_trainSet()
            acc_train, acc_valid, acc_test = self.run_testSet()
            return loss_train, acc_train, acc_valid, acc_test
        except RuntimeError as e:
            if "cuda" in str(e) or "CUDA" in str(e):
                print(e)
            else:
                raise e

    def compute_MI(self):
        self.model.eval()
        data_x = self.data.x.data.cpu().numpy()
        with torch.no_grad():
            layers_self = self.model(self.data.x, self.data.edge_index)
        layer_self = layers_self.data.cpu().numpy()
        MI_XiX = mi_kde(layer_self, data_x, var=0.1)
        return MI_XiX



    def train_compute_MI(self):
        best_acc = 0
        for epoch in range(self.epochs):
            loss_train, acc_train, acc_valid, acc_test = self.train_net()
            print('Epoch: {:02d}, Loss: {:.4f}, val_acc: {:.4f}, test_acc:{:.4f}'.format(epoch, loss_train,
                                                                                         acc_valid, acc_test))
            if best_acc < acc_valid:
                best_acc = acc_valid
                self.model.cpu()
                self.save_model(self.type_model, self.dataset)
                self.model.to(self.device)

        # reload the best model
        state_dict = self.load_model(self.type_model, self.dataset)
        self.model.load_state_dict(state_dict)
        self.model.to(self.device)

        # evaluate the saved model
        acc_train, acc_valid, acc_test = self.run_testSet()
        print('val_acc: {:.4f}, test_acc:{:.4f}'.format(acc_valid, acc_test))

        # compute the instance information gain
        MI_XiX = self.compute_MI()

        # compute the intra-group and inter-group distances first
        # then obtain the group distance ratio
        dis_intra, dis_inter = self.dis_cluster()
        if self.dataset == 'CoauthorCS' and self.type_model == 'simpleGCN':
            # if the intra-group and inter-group distances are close, we assign them the same values
            # and have the distance ratio of 1.
            distance_gap = dis_inter - dis_intra
            dis_ratio = 1. if distance_gap < 0.35 else dis_inter / dis_intra
        else:
            dis_ratio = dis_inter / dis_intra
        # if both dis_inter and dis_intra are close to zero, the value of dis_ratio is nan
        # in this case, we assign the distance ratio to 1.
        dis_ratio = 1. if np.isnan(dis_ratio) else dis_ratio

        return acc_test, MI_XiX, dis_ratio




    def dis_cluster(self):
        self.model.eval()
        with torch.no_grad():
            X = self.model(self.data.x, self.data.edge_index)
        X_labels = []
        for i in range(self.model.num_classes):
            X_label = X[self.data.y == i].data.cpu().numpy()
            h_norm = np.sum(np.square(X_label), axis=1, keepdims=True)
            h_norm[h_norm == 0.] = 1e-3
            X_label = X_label / np.sqrt(h_norm)
            X_labels.append(X_label)

        dis_intra = 0.
        for i in range(self.model.num_classes):
            x2 = np.sum(np.square(X_labels[i]), axis=1, keepdims=True)
            dists = x2 + x2.T - 2 * np.matmul(X_labels[i], X_labels[i].T)
            dis_intra += np.mean(dists)
        dis_intra /= self.model.num_classes

        dis_inter = 0.
        for i in range(self.model.num_classes-1):
            for j in range(i+1, self.model.num_classes):
                x2_i = np.sum(np.square(X_labels[i]), axis=1, keepdims=True)
                x2_j = np.sum(np.square(X_labels[j]), axis=1, keepdims=True)
                dists = x2_i + x2_j.T - 2 * np.matmul(X_labels[i], X_labels[j].T)
                dis_inter += np.mean(dists)
        num_inter = float(self.model.num_classes * (self.model.num_classes-1) / 2)
        dis_inter /= num_inter

        print('dis_intra: ', dis_intra)
        print('dis_inter: ', dis_inter)
        return dis_intra, dis_inter

    def run_trainSet(self):
        self.model.train()
        logits = self.model(self.data.x, self.data.edge_index)
        logits = F.log_softmax(logits[self.data.train_mask], 1)
        loss = self.loss_fn(logits, self.data.y[self.data.train_mask])
        self.optimizer.zero_grad()
        loss.backward()
        if self.grad_clip > 0:
            torch.nn.utils.clip_grad_norm(self.model.parameters(), self.grad_clip)
        self.optimizer.step()
        return loss.item()

    def run_testSet(self):
        self.model.eval()
        # torch.cuda.empty_cache()
        with torch.no_grad():
            logits = self.model(self.data.x, self.data.edge_index)
        logits = F.log_softmax(logits, 1)
        acc_train = evaluate(logits, self.data.y, self.data.train_mask)
        acc_valid = evaluate(logits, self.data.y, self.data.val_mask)
        acc_test = evaluate(logits, self.data.y, self.data.test_mask)
        return acc_train, acc_valid, acc_test


    def filename(self, filetype='logs', type_model='GCN', dataset='PPI'):
        filedir = f'./{filetype}/{dataset}'
        if not os.path.exists(filedir):
            os.makedirs(filedir)

        num_layers = int(self.model.num_layers)
        type_norm = self.type_norm
        miss_rate = int(self.miss_rate * 10)
        seed = int(self.seed)

        if type_norm == 'group':
            group = self.model.num_groups
            skip_weight = int(self.model.skip_weight * 1e3)

            filename = f'{filetype}_{type_model}_{type_norm}' \
                f'L{num_layers}M{miss_rate}S{seed}G{group}S{skip_weight}.pth.tar'
        else:

            filename = f'{filetype}_{type_model}_{type_norm}' \
                       f'L{num_layers}M{miss_rate}S{seed}.pth.tar'

        filename = os.path.join(filedir, filename)
        return filename

    def get_saved_info(self, path=None):
        paths = glob.glob(path)
        paths.sort()

        def get_numbers(items, delimiter, idx, replace_word, must_contain=''):
            return list(set([int(
                name.split(delimiter)[idx].replace(replace_word, ''))
                for name in items if must_contain in name]))

        basenames = [os.path.basename(path.rsplit('.', 2)[0]) for path in paths]
        epochs = get_numbers(basenames, '_', 2, 'epoch')
        epochs.sort()
        return epochs

    def load_model(self, type_model='GCN', dataset='PPI'):
        filename = self.filename(filetype='params', type_model=type_model, dataset=dataset)
        if os.path.exists(filename):
            print('load model: ', type_model, filename)
            return torch.load(filename)
        else:
            return None

    def save_model(self, type_model='GCN', dataset='PPI'):
        filename = self.filename(filetype='params', type_model=type_model, dataset=dataset)
        state = self.model.state_dict()
        torch.save(state, filename)
        print('save model to', filename)
Exemplo n.º 5
0
def choose_model(conf):
    if conf['model_name'] == 'GCN':
        model = GCN(g=G,
                    in_feats=features.shape[1],
                    n_hidden=conf['hidden'],
                    n_classes=labels.max().item() + 1,
                    n_layers=1,
                    activation=F.relu,
                    dropout=conf['dropout']).to(conf['device'])
    elif conf['model_name'] in ['GAT', 'SGAT']:
        if conf['model_name'] == 'GAT':
            num_heads = 8
        else:
            num_heads = 1
        num_layers = 1
        num_out_heads = 1
        heads = ([num_heads] * num_layers) + [num_out_heads]
        model = GAT(
            g=G,
            num_layers=num_layers,
            in_dim=features.shape[1],
            num_hidden=8,
            num_classes=labels.max().item() + 1,
            heads=heads,
            activation=F.relu,
            feat_drop=0.6,
            attn_drop=0.6,
            negative_slope=0.2,  # negative slope of leaky relu
            residual=False).to(conf['device'])
    elif conf['model_name'] == 'GraphSAGE':
        model = GraphSAGE(in_feats=features.shape[1],
                          n_hidden=conf['embed_dim'],
                          n_classes=labels.max().item() + 1,
                          n_layers=2,
                          activation=F.relu,
                          dropout=0.5,
                          aggregator_type=conf['agg_type']).to(conf['device'])
    elif conf['model_name'] == 'APPNP':
        model = APPNP(g=G,
                      in_feats=features.shape[1],
                      hiddens=[64],
                      n_classes=labels.max().item() + 1,
                      activation=F.relu,
                      feat_drop=0.5,
                      edge_drop=0.5,
                      alpha=0.1,
                      k=10).to(conf['device'])
    elif conf['model_name'] == 'MoNet':
        model = MoNet(g=G,
                      in_feats=features.shape[1],
                      n_hidden=64,
                      out_feats=labels.max().item() + 1,
                      n_layers=1,
                      dim=2,
                      n_kernels=3,
                      dropout=0.7).to(conf['device'])
    elif conf['model_name'] == 'SGC':
        model = SGConv(in_feats=features.shape[1],
                       out_feats=labels.max().item() + 1,
                       k=2,
                       cached=True,
                       bias=False).to(conf['device'])
    elif conf['model_name'] == 'GCNII':
        if conf['dataset'] == 'citeseer':
            conf['layer'] = 32
            conf['hidden'] = 256
            conf['lamda'] = 0.6
            conf['dropout'] = 0.7
        elif conf['dataset'] == 'pubmed':
            conf['hidden'] = 256
            conf['lamda'] = 0.4
            conf['dropout'] = 0.5
        model = GCNII(nfeat=features.shape[1],
                      nlayers=conf['layer'],
                      nhidden=conf['hidden'],
                      nclass=labels.max().item() + 1,
                      dropout=conf['dropout'],
                      lamda=conf['lamda'],
                      alpha=conf['alpha'],
                      variant=False).to(conf['device'])
    return model
Exemplo n.º 6
0
def choose_model(conf, G, features, labels, byte_idx_train, labels_one_hot):
    if conf['model_name'] == 'GCN':
        model = GCN(g=G,
                    in_feats=features.shape[1],
                    n_hidden=conf['hidden'],
                    n_classes=labels.max().item() + 1,
                    n_layers=1,
                    activation=F.relu,
                    dropout=conf['dropout']).to(conf['device'])
    elif conf['model_name'] == 'GAT':
        num_heads = 8
        num_layers = 1
        num_out_heads = 1
        heads = ([num_heads] * num_layers) + [num_out_heads]
        model = GAT(
            g=G,
            num_layers=num_layers,
            in_dim=G.ndata['feat'].shape[1],
            num_hidden=8,
            num_classes=labels.max().item() + 1,
            heads=heads,
            activation=F.relu,
            feat_drop=0.6,
            attn_drop=0.6,
            negative_slope=0.2,  # negative slope of leaky relu
            residual=False).to(conf['device'])
    elif conf['model_name'] == 'PLP':
        model = PLP(g=G,
                    num_layers=conf['num_layers'],
                    in_dim=G.ndata['feat'].shape[1],
                    emb_dim=conf['emb_dim'],
                    num_classes=labels.max().item() + 1,
                    activation=F.relu,
                    feat_drop=conf['feat_drop'],
                    attn_drop=conf['attn_drop'],
                    residual=False,
                    byte_idx_train=byte_idx_train,
                    labels_one_hot=labels_one_hot,
                    ptype=conf['ptype'],
                    mlp_layers=conf['mlp_layers']).to(conf['device'])
    elif conf['model_name'] == 'GraphSAGE':
        model = GraphSAGE(in_feats=G.ndata['feat'].shape[1],
                          n_hidden=16,
                          n_classes=labels.max().item() + 1,
                          n_layers=1,
                          activation=F.relu,
                          dropout=0.5,
                          aggregator_type=conf['agg_type']).to(conf['device'])
    elif conf['model_name'] == 'APPNP':
        model = APPNP(g=G,
                      in_feats=G.ndata['feat'].shape[1],
                      hiddens=[64],
                      n_classes=labels.max().item() + 1,
                      activation=F.relu,
                      feat_drop=0.5,
                      edge_drop=0.5,
                      alpha=0.1,
                      k=10).to(conf['device'])
    elif conf['model_name'] == 'LogReg':
        model = MLP(num_layers=1,
                    input_dim=G.ndata['feat'].shape[1],
                    hidden_dim=None,
                    output_dim=labels.max().item() + 1,
                    dropout=0).to(conf['device'])
    elif conf['model_name'] == 'MLP':
        model = MLP(num_layers=2,
                    input_dim=G.ndata['feat'].shape[1],
                    hidden_dim=conf['hidden'],
                    output_dim=labels.max().item() + 1,
                    dropout=conf['dropout']).to(conf['device'])
    else:
        raise ValueError(f'Undefined Model.')
    return model
Exemplo n.º 7
0
        
        # Build graph classification model
        if model_name == 'GCN':
            model = GCN(n_feat=datareader.data['features_dim'],
                    n_class=datareader.data['n_classes'],
                    n_layer=args.n_agg_layer,
                    agg_hidden=args.agg_hidden,
                    fc_hidden=args.fc_hidden,
                    dropout=args.dropout,
                    readout=readout_name,
                    device=device).to(device)
        elif model_name == 'GAT':
            model = GAT(n_feat=datareader.data['features_dim'],
                    n_class=datareader.data['n_classes'],
                    n_layer=args.n_agg_layer,
                    agg_hidden=args.agg_hidden,
                    fc_hidden=args.fc_hidden,
                    dropout=args.dropout,
                    readout=readout_name,
                    device=device).to(device)
#        elif model_name == 'GraphWaveletNet':
#            model = GraphWaveletNet(n_feat=datareader.data['features_dim'],
#                    n_class=datareader.data['n_classes'],
#                    n_layer=args.n_agg_layer,
#                    agg_hidden=args.agg_hidden,
#                    fc_hidden=args.fc_hidden,
#                    dropout=args.dropout,
#                    readout=readout_name,
#                    device=device,
#                    n_node=datareader.data['N_nodes_max']).to(device)
        elif model_name == 'GraphSAGE':
            model = GraphUNet(n_feat=datareader.data['features_dim'],
Exemplo n.º 8
0
    def __init__(self, args):
        self.dataset = args.dataset
        self.device = torch.device(
            f"cuda:{args.cuda_num}" if args.cuda else "cpu")
        if self.dataset in ["Cora", "Citeseer", "Pubmed", "CoauthorCS"]:
            if args.ptb:
                self.data = load_perterbued_data(self.dataset, args.ptb_rate,
                                                 args.ptb_type)
                self.loss_fn = torch.nn.functional.nll_loss
            else:
                self.data = load_data(self.dataset)
                self.loss_fn = torch.nn.functional.nll_loss
        elif self.dataset in ["PPI"]:
            self.data = load_ppi_data()
            self.loss_fn = torch.nn.BCEWithLogitsLoss()
        else:
            raise Exception(
                f"the dataset of {self.dataset} has not been implemented")

        self.entropy_loss = torch.nn.functional.binary_cross_entropy_with_logits

        self.type_model = args.type_model
        self.epochs = args.epochs
        self.weight_decay = args.weight_decay
        self.alpha = args.alpha
        self.gamma = args.gamma
        self.beta = args.beta
        self.lamb = args.lamb
        self.num_classes = args.num_classes
        self.ptb_rate = args.ptb_rate
        self.ptb_type = args.ptb_type
        self.metric = args.metric
        self.num_layers = args.num_layers

        if self.type_model == "GCN":
            self.model = GCN(args)
        elif self.type_model == "GAT":
            self.model = GAT(args)
        elif self.type_model == "NLGCN":
            self.model = NLGCN(args)
        elif self.type_model == "g_U_Net":
            self.model = gunet(args)
        elif self.type_model == "JKNet":
            self.model = JKNetMaxpool(args)
        elif self.type_model == "SGC":
            self.model = simpleGCN(args)
        elif self.type_model == "APPNP":
            self.model = APPNP(args)
        else:
            raise Exception(
                f"the model of {self.type_model} has not been implemented")

        if self.dataset in ["Cora", "Citeseer", "Pubmed", "CoauthorCS"]:
            if args.ptb:
                self.data.edge_index, self.data.x, self.data.y = utils.preprocess(
                    self.data.edge_index,
                    self.data.x,
                    self.data.y,
                    preprocess_adj=False,
                    sparse=False,
                    device=self.device)

            else:
                self.data.to(self.device)
        self.model.to(self.device)

        self.optimizer = torch.optim.Adam(self.model.parameters(),
                                          lr=args.lr,
                                          weight_decay=args.weight_decay)

        wandb.init(project="Gref", config=args)
        wandb.watch(self.model)
Exemplo n.º 9
0
                              num_workers=3,
                              batch_size=BATCH_SIZE)

    #
    # g = datasets.GraphDataset(load_cora_data(args.e))
    with open("test_data.pkl", 'rb') as f:
        # pickle.dump(g, f)
        g = pickle.load(f)

    test_loader = DataLoader(g,
                             collate_fn=datasets.graph_collate,
                             shuffle=True,
                             num_workers=3,
                             batch_size=BATCH_SIZE)

    net = GAT(133, 14).to(dev)
    print("TOTAL PARMS",
          sum(p.numel() for p in net.parameters() if p.requires_grad))

    # create optimizer
    optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)

    dur = []

    lossf = F.mse_loss
    second_lossf = torch.nn.MSELoss(reduction='none')
    for epoch in range(50):
        net.train()
        train_avg = Avg()
        train2_avg = Avg()
        # if epoch < 10: