def remove_self_loop_edges(graph: DGLGraph): g_src, g_dest = graph.all_edges() s2d_loop = g_src - g_dest src, dest = g_src[s2d_loop != 0], g_dest[s2d_loop != 0] graph_with_out_loop = DGLGraph() graph_with_out_loop.add_nodes(graph.number_of_nodes()) graph_with_out_loop.add_edges(src, dest) for key, value in graph.ndata.items(): graph_with_out_loop.ndata[key] = value return graph_with_out_loop
def reorginize_self_loop_edges(graph: DGLGraph): g_src, g_dest = graph.all_edges() s2d_loop = g_src - g_dest src, dest = g_src[s2d_loop != 0], g_dest[s2d_loop != 0] graph_reorg = DGLGraph() graph_reorg.add_nodes(graph.number_of_nodes()) graph_reorg.add_edges(src, dest) self_loop_edge_number = (s2d_loop ==0).sum().item() if self_loop_edge_number > 0: self_src, self_dest = g_src[s2d_loop == 0], g_dest[s2d_loop == 0] graph_reorg.add_edges(self_src, self_dest) for key, value in graph.ndata.items(): graph_reorg.ndata[key] = value return graph_reorg, self_loop_edge_number
def graph_to_undirected(graph: DGLGraph): g_src, g_dest = graph.all_edges() s2d_loop = g_src - g_dest src, dest = g_src[s2d_loop != 0], g_dest[s2d_loop != 0] self_loop_edge_number = s2d_loop == 0 undirected_graph = DGLGraph() undirected_graph.add_nodes(graph.number_of_nodes()) undirected_graph.add_edges(src, dest) undirected_graph.add_edges(dest, src) if self_loop_edge_number.sum() > 0: self_src, self_dest = g_src[s2d_loop == 0], g_dest[s2d_loop == 0] undirected_graph.add_edges(self_src, self_dest) for key, value in graph.ndata.items(): undirected_graph.ndata[key] = value return undirected_graph
def edge_sparsemax(graph: dgl.DGLGraph, logits, eids=ALL, norm_by="dst"): r""" Description ----------- Compute edge sparsemax. For a node :math:`i`, edge sparsemax is an operation that computes .. math:: a_{ij} = \text{ReLU}(z_{ij} - \tau(\z_{i,:})) where :math:`z_{ij}` is a signal of edge :math:`j\rightarrow i`, also called logits in the context of sparsemax. :math:`\tau` is a function that can be found at the `From Softmax to Sparsemax <https://arxiv.org/pdf/1602.02068.pdf>` paper. NOTE: currently only homogeneous graphs are supported. Parameters ---------- graph : DGLGraph The graph to perform edge sparsemax on. logits : torch.Tensor The input edge feature. eids : torch.Tensor or ALL, optional A tensor of edge index on which to apply edge sparsemax. If ALL, apply edge sparsemax on all edges in the graph. Default: ALL. norm_by : str, could be 'src' or 'dst' Normalized by source nodes of destination nodes. Default: `dst`. Returns ------- Tensor Sparsemax value. """ # we get edge index tensors here since it is # hard to get edge index with HeteroGraphIndex # object without other information like edge_type. row, col = graph.all_edges(order="eid") assert norm_by in ["dst", "src"] end_n_ids = col if norm_by == "dst" else row if not is_all(eids): eids = astype(eids, graph.idtype) end_n_ids = end_n_ids[eids] return EdgeSparsemaxFunction.apply(graph._graph, logits, eids, end_n_ids, norm_by)
def load_cora_data(): data = citegrh.load_cora() features = th.FloatTensor(data.features) labels = th.LongTensor(data.labels) mask = th.ByteTensor(data.train_mask) g = DGLGraph(data.graph) print("g: ") print(g.all_edges()) print(g.edata) print("features: ") print(features.size()) print(features) print("labels: ") print(labels.size()) print(labels) print("mask: ") print(mask.size()) print(mask) return g, features, labels, mask
def main(args): # graph coo_adj = sp.load_npz("reddit_self_loop/reddit_self_loop_graph.npz") graph = DGLGraph(coo_adj, readonly=True) # features and labels reddit_data = np.load("reddit_self_loop/reddit_data.npz") features = reddit_data["feature"] labels = reddit_data["label"] num_labels = 41 # tarin/val/test indices node_ids = reddit_data["node_ids"] node_types = reddit_data["node_types"] train_mask = (node_types == 1) val_mask = (node_types == 2) test_mask = (node_types == 3) graph.ndata['train_mask'] = train_mask graph.ndata['val_mask'] = val_mask graph.ndata['test_mask'] = test_mask graph.ndata['feat'] = features graph.ndata['label'] = labels features = torch.Tensor(features) in_feats = features.shape[1] labels = torch.LongTensor(labels) train_nid = torch.LongTensor(np.where(train_mask == True)[0]) train_mask = torch.BoolTensor(train_mask) val_nid = torch.LongTensor(np.where(val_mask == True)[0]) val_mask = torch.BoolTensor(val_mask) test_nid = torch.LongTensor(np.where(test_mask == True)[0]) test_mask = torch.BoolTensor(test_mask) g = dgl.graph(graph.all_edges()) # 转为HetroGraph g.ndata['features'] = features gpu = args.gpu use_cuda = gpu >= 0 and torch.cuda.is_available() if use_cuda: torch.cuda.set_device(gpu) g.to(torch.device('cuda:{}'.format(gpu))) labels = labels.cuda() fanouts = list(map(int, args.fan_out.split(','))) sampler = Sample(g, fanouts, args.num_neg) # 将数据集打乱顺序,分多个batch,每个batch采样两个B batch_size = args.batch_size num_workers = args.num_workers train_ids = torch.LongTensor(np.arange(g.number_of_edges())) dataloader = DataLoader(dataset=train_ids, batch_size=batch_size, collate_fn=sampler.obtain_Bs, shuffle=True, drop_last=False, num_workers=num_workers, pin_memory=True) # 设定模型 num_hid = args.num_hidden ks = args.num_layers dropout_r = args.dropout agg = args.agg bias = args.bias norm = args.norm model = GraphSAGE(in_feats, num_hid, num_labels, ks, bias=bias, aggregator=agg, activation=F.relu, norm=norm, dropout=dropout_r, use_cuda=use_cuda) if use_cuda: model.cuda() loss_fcn = Unsuper_Cross_Entropy() # use optimizer optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # acc def compute_acc(logits, labels, train_nids, val_nids, test_nids, num_labels): # 输出标准化 print('Computing accuracy...') logits = (logits - logits.mean(0)) / logits.std( 0, unbiased=False) # unbiased=False结果与numpy相同 clf = LR_classification(num_labels, num_labels) if use_cuda: clf.cuda() criterion = nn.NLLLoss() optimizer = torch.optim.Adam(clf.parameters(), lr=0.003, weight_decay=1e-4) for epoch in range(10000): y_pred = clf(logits[train_nids]) loss = criterion(y_pred, labels[train_nids]) #if epoch % 500 == 0: #print('epoch: {} | loss: {}'.format(epoch, loss.item())) optimizer.zero_grad() loss.backward() optimizer.step() #print('epoch: {} | loss: {}'.format(epoch, loss.item())) clf.eval() with torch.no_grad(): pred = clf.forward(logits) f1_micro_eval = (torch.argmax(pred[val_nids], dim=1) == labels[val_nids]).float().sum() / val_nids.shape[0] f1_micro_test = (torch.argmax( pred[test_nids], dim=1) == labels[test_nids]).float().sum() / test_nids.shape[0] return f1_micro_eval, f1_micro_test # eval def evaluation(model, g, labels, train_nids, val_nids, test_nids, batch_size, num_labels): model.eval() with torch.no_grad(): logits = model.infer(g, batch_size) model.train() return compute_acc(logits, labels, train_nids, val_nids, test_nids, num_labels) # link-prediction def link_prediction(model, g, batch_size): model.eval() with torch.no_grad(): logits = model.infer(g, batch_size) model.train() # 计算精度... precise = 0 for start in tqdm.trange(0, g.number_of_edges(), batch_size): end = start + batch_size if end > g.number_of_edges(): end = g.number_of_edges() ed_ids = torch.LongTensor(np.arange(start, end)) heads, tails = g.find_edges(ed_ids) src = g.ndata['z'][heads, :] dst = g.ndata['z'][tails, :] y_pred = nn.Sigmoid()((src * dst).sum(dim=1)) prec = (y_pred >= 0.5).float().sum() precise = precise + prec precision = precise / g.number_of_edges() return precision # 训练、验证与测试 n_epochs = args.num_epochs log_every = args.log_every eval_every = args.eval_every iter_pos = [] iter_neg = [] iter_d = [] iter_t = [] best_eval_acc = 0 best_test_acc = 0 best_precision = 0 for epoch in range(n_epochs): time_epoch_0 = time.time() time_step = time.time() for step, (pos_graph, neg_graph, blocks) in enumerate(dataloader): input_nodes = blocks[0].srcdata[dgl.NID] batch_inputs = g.ndata['features'][input_nodes] if use_cuda: batch_inputs = batch_inputs.cuda() time_load = time.time() batch_pred = model(batch_inputs, blocks) loss = loss_fcn(batch_pred, pos_graph, neg_graph, use_cuda) optimizer.zero_grad() loss.backward() optimizer.step() time_train = time.time() edge_pos = pos_graph.number_of_edges() edge_neg = neg_graph.number_of_edges() iter_pos.append(edge_pos / (time_train - time_step)) iter_neg.append(edge_neg / (time_train - time_step)) iter_d.append(time_load - time_step) iter_t.append(time_train - time_load) if step % log_every == 0: if step == 0: print( 'Epoch {:05d} | Step {:05d} | Loss {:.4f} | ' 'Speed (samples/sec) {:.4f} & {:.4f} | Load Time(sec) {:.4f} | Train Time(sec) {:.4f}' .format(epoch, step, loss.item(), np.mean(iter_pos), np.mean(iter_neg), np.mean(iter_d), np.mean(iter_t))) else: print( 'Epoch {:05d} | Step {:05d} | Loss {:.4f} | ' 'Speed (samples/sec) {:.4f} & {:.4f} | Load Time(sec) {:.4f} | Train Time(sec) {:.4f}' .format(epoch, step, loss.item(), np.mean(iter_pos[3:]), np.mean(iter_neg[3:]), np.mean(iter_d[3:]), np.mean(iter_t[3:]))) time_step = time.time() if step % eval_every == 0: print('\n') print('Eval-ing...') time_ev_0 = time.time() if args.link: precision = link_prediction(model, g, batch_size) if precision > best_precision: best_precision = precision time_ev_1 = time.time() print('Precision {:.4f} | Eval Time(s): {:.4f}'.format( precision, time_ev_1 - time_ev_0)) print('Best Precision {:.4f}'.format(best_precision)) else: eval_acc, test_acc = evaluation(model, g, labels, train_nid, val_nid, test_nid, batch_size, num_labels) if eval_acc > best_eval_acc: best_eval_acc = eval_acc best_test_acc = test_acc time_ev_1 = time.time() print('Eval Acc {:.4f} | Eval Time(s): {:.4f}'.format( eval_acc, time_ev_1 - time_ev_0)) print('Best Eval Acc {:.4f} | Best Test Acc {:.4f}'.format( best_eval_acc, best_test_acc)) time_step = time.time() #if step == 2: #break time_epoch_1 = time.time() print('Epoch Time(s): {:.4f}'.format(time_epoch_1 - time_epoch_0)) #if epoch == 1: #break print('\n') print('Finish!')
def main(args): # graph coo_adj = sp.load_npz("reddit_self_loop/reddit_self_loop_graph.npz") graph = DGLGraph(coo_adj, readonly=True) # features and labels reddit_data = np.load("reddit_self_loop/reddit_data.npz") features = reddit_data["feature"] labels = reddit_data["label"] num_labels = 41 # tarin/val/test indices node_ids = reddit_data["node_ids"] node_types = reddit_data["node_types"] train_mask = (node_types == 1) val_mask = (node_types == 2) test_mask = (node_types == 3) graph.ndata['train_mask'] = train_mask graph.ndata['val_mask'] = val_mask graph.ndata['test_mask'] = test_mask graph.ndata['feat'] = features graph.ndata['label'] = labels features = torch.Tensor(features) in_feats = features.shape[1] labels = torch.LongTensor(labels) train_nid = torch.LongTensor(np.where(train_mask == True)[0]) train_mask = torch.BoolTensor(train_mask) val_nid = torch.LongTensor(np.where(val_mask == True)[0]) val_mask = torch.BoolTensor(val_mask) test_nid = torch.LongTensor(np.where(test_mask == True)[0]) test_mask = torch.BoolTensor(test_mask) g = dgl.graph(graph.all_edges()) # 转为HetroGraph g.ndata['features'] = features gpu = args.gpu use_cuda = gpu >= 0 and torch.cuda.is_available() if use_cuda: torch.cuda.set_device(gpu) g.to(torch.device('cuda:{}'.format(gpu))) labels = labels.cuda() fanouts = list(map(int, args.fan_out.split(','))) sampler = Sample(g, fanouts) # 将数据集打乱顺序,分多个batch,每个batch采样两个B batch_size = args.batch_size num_workers = args.num_workers dataloader = DataLoader(dataset=train_nid.numpy(), batch_size=batch_size, collate_fn=sampler.obtain_Bs, shuffle=True, drop_last=False, num_workers=num_workers) # 设定模型 num_hid = args.num_hidden ks = args.num_layers dropout_r = args.dropout agg = args.agg bias = args.bias norm = args.norm model = GraphSAGE(in_feats, num_hid, num_labels, ks, bias=bias, aggregator=agg, activation=F.relu, norm=norm, dropout=dropout_r, use_cuda=use_cuda) if use_cuda: model.cuda() loss_fcn = torch.nn.CrossEntropyLoss() # use optimizer l_r = args.lr optimizer = torch.optim.Adam(model.parameters(), lr=l_r) # acc def compute_acc(pred, labels): acc = (torch.argmax(pred, dim=1) == labels).float().sum() / len(pred) return acc # eval def evaluation(model, g, labels, id, batch_size): model.eval() with torch.no_grad(): logits = model.infer(g, batch_size) pred = logits[id] label = labels[id] model.train() return compute_acc(pred, label) # 训练、验证与测试 n_epochs = args.num_epochs log_every = args.log_every eval_every = args.eval_every avg = 0 iter_tput = [] for epoch in range(n_epochs): time_epoch_0 = time.time() for step, blocks in enumerate(dataloader): time_step = time.time() input_nodes = blocks[0].srcdata[dgl.NID] seeds = blocks[-1].dstdata[dgl.NID] # 最后一个block的dst为batch中的节点 batch_inputs = g.ndata['features'][input_nodes] batch_labels = labels[seeds] if use_cuda: batch_inputs = batch_inputs.cuda() batch_labels = batch_labels.cuda() batch_pred = model(batch_inputs, blocks) loss = loss_fcn(batch_pred, batch_labels) optimizer.zero_grad() loss.backward() optimizer.step() iter_tput.append(len(seeds) / (time.time() - time_step)) if step % log_every == 0: acc = compute_acc(batch_pred, batch_labels) print( 'Epoch {:05d} | Step {:05d} | Loss {:.4f} | Train Acc {:.4f} | Speed (samples/sec) {:.4f}' .format(epoch, step, loss.item(), acc.item(), np.mean(iter_tput[3:]))) time_epoch_1 = time.time() print('Epoch Time(s): {:.4f}'.format(time_epoch_1 - time_epoch_0)) if epoch >= 5: avg += time_epoch_1 - time_epoch_0 if epoch % eval_every == 0 and epoch != 0: print('\n') print('Eval-ing...') time_ev_0 = time.time() eval_acc = evaluation(model, g, labels, val_mask, batch_size) time_ev_1 = time.time() print('Eval Acc {:.4f} | Eval Time(s): {:.4f}'.format( eval_acc, time_ev_1 - time_ev_0)) print('\n') print('Eval-ing...') time_ev_0 = time.time() eval_acc = evaluation(model, g, labels, val_mask, batch_size) time_ev_1 = time.time() print('Eval Acc {:.4f} | Eval Time(s): {:.4f}'.format( eval_acc, time_ev_1 - time_ev_0)) print('\n') print('Testing...') time_ev_0 = time.time() test_acc = evaluation(model, g, labels, test_mask, batch_size) time_ev_1 = time.time() print('Test Acc {:.4f} | Eval Time(s): {:.4f}'.format( test_acc, time_ev_1 - time_ev_0)) print('Finish!')
def forward(self, graph: DGLGraph, feat: Tensor, e_feat=None): # top-k pool first if e_feat is None: e_feat = torch.ones((graph.number_of_edges(), ), dtype=feat.dtype, device=feat.device) batch_num_nodes = graph.batch_num_nodes() x_score = self.calc_info_score(graph, feat, e_feat) perm, next_batch_num_nodes = topk(x_score, self.ratio, get_batch_id(batch_num_nodes), batch_num_nodes) feat = feat[perm] pool_graph = None if not self.sample or not self.sl: # pool graph graph.edata["e"] = e_feat pool_graph = dgl.node_subgraph(graph, perm) e_feat = pool_graph.edata.pop("e") pool_graph.set_batch_num_nodes(next_batch_num_nodes) # no structure learning layer, directly return. if not self.sl: return pool_graph, feat, e_feat, perm # Structure Learning if self.sample: # A fast mode for large graphs. # In large graphs, learning the possible edge weights between each # pair of nodes is time consuming. To accelerate this process, # we sample it's K-Hop neighbors for each node and then learn the # edge weights between them. # first build multi-hop graph row, col = graph.all_edges() num_nodes = graph.num_nodes() scipy_adj = scipy.sparse.coo_matrix( (e_feat.detach().cpu(), (row.detach().cpu(), col.detach().cpu())), shape=(num_nodes, num_nodes)) for _ in range(self.k_hop): two_hop = scipy_adj**2 two_hop = two_hop * (1e-5 / two_hop.max()) scipy_adj = two_hop + scipy_adj row, col = scipy_adj.nonzero() row = torch.tensor(row, dtype=torch.long, device=graph.device) col = torch.tensor(col, dtype=torch.long, device=graph.device) e_feat = torch.tensor(scipy_adj.data, dtype=torch.float, device=feat.device) # perform pooling on multi-hop graph mask = perm.new_full((num_nodes, ), -1) i = torch.arange(perm.size(0), dtype=torch.long, device=perm.device) mask[perm] = i row, col = mask[row], mask[col] mask = (row >= 0) & (col >= 0) row, col = row[mask], col[mask] e_feat = e_feat[mask] # add remaining self loops mask = row != col num_nodes = perm.size(0) # num nodes after pool loop_index = torch.arange(0, num_nodes, dtype=row.dtype, device=row.device) inv_mask = ~mask loop_weight = torch.full((num_nodes, ), 0, dtype=e_feat.dtype, device=e_feat.device) remaining_e_feat = e_feat[inv_mask] if remaining_e_feat.numel() > 0: loop_weight[row[inv_mask]] = remaining_e_feat e_feat = torch.cat([e_feat[mask], loop_weight], dim=0) row, col = row[mask], col[mask] row = torch.cat([row, loop_index], dim=0) col = torch.cat([col, loop_index], dim=0) # attention scores weights = (torch.cat([feat[row], feat[col]], dim=1) * self.att).sum(dim=-1) weights = F.leaky_relu(weights, self.negative_slop) + e_feat * self.lamb # sl and normalization sl_graph = dgl.graph((row, col)) if self.sparse: weights = edge_sparsemax(sl_graph, weights) else: weights = edge_softmax(sl_graph, weights) # get final graph mask = torch.abs(weights) > 0 row, col, weights = row[mask], col[mask], weights[mask] pool_graph = dgl.graph((row, col)) pool_graph.set_batch_num_nodes(next_batch_num_nodes) e_feat = weights else: # Learning the possible edge weights between each pair of # nodes in the pooled subgraph, relative slower. # construct complete graphs for all graph in the batch # use dense to build, then transform to sparse. # maybe there's more efficient way? batch_num_nodes = next_batch_num_nodes block_begin_idx = torch.cat([ batch_num_nodes.new_zeros(1), batch_num_nodes.cumsum(dim=0)[:-1] ], dim=0) block_end_idx = batch_num_nodes.cumsum(dim=0) dense_adj = torch.zeros( (pool_graph.num_nodes(), pool_graph.num_nodes()), dtype=torch.float, device=feat.device) for idx_b, idx_e in zip(block_begin_idx, block_end_idx): dense_adj[idx_b:idx_e, idx_b:idx_e] = 1. row, col = torch.nonzero(dense_adj).t().contiguous() # compute weights for node-pairs weights = (torch.cat([feat[row], feat[col]], dim=1) * self.att).sum(dim=-1) weights = F.leaky_relu(weights, self.negative_slop) dense_adj[row, col] = weights # add pooled graph structure to weight matrix pool_row, pool_col = pool_graph.all_edges() dense_adj[pool_row, pool_col] += self.lamb * e_feat weights = dense_adj[row, col] del dense_adj torch.cuda.empty_cache() # edge softmax/sparsemax complete_graph = dgl.graph((row, col)) if self.sparse: weights = edge_sparsemax(complete_graph, weights) else: weights = edge_softmax(complete_graph, weights) # get new e_feat and graph structure, clean up. mask = torch.abs(weights) > 1e-9 row, col, weights = row[mask], col[mask], weights[mask] e_feat = weights pool_graph = dgl.graph((row, col)) pool_graph.set_batch_num_nodes(next_batch_num_nodes) return pool_graph, feat, e_feat, perm
def main(args): # graph coo_adj = sp.load_npz("reddit_self_loop/reddit_self_loop_graph.npz") graph = DGLGraph(coo_adj, readonly=True) # features and labels reddit_data = np.load("reddit_self_loop/reddit_data.npz") features = reddit_data["feature"] labels = reddit_data["label"] num_labels = 41 # tarin/val/test indices node_ids = reddit_data["node_ids"] node_types = reddit_data["node_types"] train_mask = (node_types == 1) val_mask = (node_types == 2) test_mask = (node_types == 3) graph.ndata['train_mask'] = train_mask graph.ndata['val_mask'] = val_mask graph.ndata['test_mask'] = test_mask graph.ndata['feat'] = features graph.ndata['label'] = labels features = torch.Tensor(features) in_feats = features.shape[1] labels = torch.LongTensor(labels) train_nid = torch.LongTensor(np.where(train_mask == True)[0]) train_mask = torch.BoolTensor(train_mask) val_nid = torch.LongTensor(np.where(val_mask == True)[0]) val_mask = torch.BoolTensor(val_mask) test_nid = torch.LongTensor(np.where(test_mask == True)[0]) test_mask = torch.BoolTensor(test_mask) g = dgl.graph(graph.all_edges()) # 转为HetroGraph g.ndata['features'] = features gpu = args.gpu use_cuda = gpu >= 0 and torch.cuda.is_available() if use_cuda: torch.cuda.set_device(gpu) g.to(torch.device('cuda:{}'.format(gpu))) labels = labels.cuda() fanouts = list(map(int, args.fan_out.split(','))) sampler = Sample(g, fanouts, args.num_neg) # 将数据集打乱顺序,分多个batch,每个batch采样两个B batch_size = args.batch_size num_workers = args.num_workers # train_ids = torch.LongTensor(np.arange(g.number_of_edges())) dataloader = DataLoader(dataset=train_nid.numpy(), batch_size=batch_size, collate_fn=sampler.obtain_Bs, shuffle=True, drop_last=False, num_workers=num_workers) #print('Loading...') #t0 = time.time() #DLoaders = [] #for step, (pos_graph, neg_graph, blocks) in enumerate(dataloader): #DLoaders.append((step, (pos_graph, neg_graph, blocks))) #t1 = time.time() #print('Step {} | {} s'.format(step, t1-t0)) #t0 = time.time() # 设定模型 num_hid = args.num_hidden ks = args.num_layers dropout_r = args.dropout agg = args.agg bias = args.bias norm = args.norm model = GraphSAGE(in_feats, num_hid, num_labels, ks, bias=bias, aggregator=agg, activation=F.relu, norm=norm, dropout=dropout_r, use_cuda=use_cuda) if use_cuda: model.cuda() loss_fcn = Unsuper_Cross_Entropy() # use optimizer optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # acc def compute_acc(logits, labels, train_nids, val_nids, test_nids): logits = logits.cpu().numpy() labels = labels.cpu().numpy() train_nids = train_nids.cpu().numpy() val_nids = val_nids.cpu().numpy() test_nids = test_nids.cpu().numpy() # 输出标准化 logits = (logits - logits.mean(0)) / logits.std(0) clf = LogisticRegression(multi_class='multinomial', max_iter=10000) clf.fit(logits[train_nids], labels[train_nid]) pred = clf.predict(logits) ''' pred = torch.argmax(logits, dim=1) f1_micro_eval = ((pred[val_nids] == labels[val_nids]).float().sum() / pred[val_nids].shape[0]).item() f1_micro_test = ((pred[test_nids] == labels[test_nids]).float().sum() / pred[test_nids].shape[0]).item() ''' f1_micro_eval = metrics.f1_score(labels[val_nids], pred[val_nids], average='micro') f1_micro_test = metrics.f1_score(labels[test_nids], pred[test_nids], average='micro') return f1_micro_eval, f1_micro_test # eval def evaluation(model, g, labels, train_nids, val_nids, test_nids, batch_size): model.eval() with torch.no_grad(): logits = model.infer(g, batch_size) model.train() return compute_acc(logits, labels, train_nids, val_nids, test_nids) # 训练、验证与测试 n_epochs = args.num_epochs log_every = args.log_every eval_every = args.eval_every iter_pos = [] iter_neg = [] iter_d = [] iter_t = [] best_eval_acc = 0 best_test_acc = 0 for epoch in range(n_epochs): time_epoch_0 = time.time() time_step = time.time() for step, (pos_graph, neg_graph, blocks) in enumerate(dataloader): #for (step, (pos_graph, neg_graph, blocks)) in DLoaders: input_nodes = blocks[0].srcdata[dgl.NID] batch_inputs = g.ndata['features'][input_nodes] if use_cuda: batch_inputs = batch_inputs.cuda() time_load = time.time() batch_pred = model(batch_inputs, blocks) loss = loss_fcn(batch_pred, pos_graph, neg_graph, use_cuda) optimizer.zero_grad() loss.backward() optimizer.step() time_train = time.time() edge_pos = pos_graph.number_of_edges() edge_neg = neg_graph.number_of_edges() iter_pos.append(edge_pos / (time_train - time_step)) iter_neg.append(edge_neg / (time_train - time_step)) iter_d.append(time_load - time_step) iter_t.append(time_train - time_load) if step % log_every == 0: if step == 0: print( 'Epoch {:05d} | Step {:05d} | Loss {:.4f} | ' 'Speed (samples/sec) {:.4f} & {:.4f} | Load Time(sec) {:.4f} | Train Time(sec) {:.4f}' .format(epoch, step, loss.item(), np.mean(iter_pos), np.mean(iter_neg), np.mean(iter_d), np.mean(iter_t))) else: print( 'Epoch {:05d} | Step {:05d} | Loss {:.4f} | ' 'Speed (samples/sec) {:.4f} & {:.4f} | Load Time(sec) {:.4f} | Train Time(sec) {:.4f}' .format(epoch, step, loss.item(), np.mean(iter_pos[3:]), np.mean(iter_neg[3:]), np.mean(iter_d[3:]), np.mean(iter_t[3:]))) time_step = time.time() #if step == 2: #break if epoch % eval_every == 0: print('\n') print('Eval-ing...') time_ev_0 = time.time() eval_acc, test_acc = evaluation(model, g, labels, train_nid, val_nid, test_nid, batch_size) if eval_acc > best_eval_acc: best_eval_acc = eval_acc best_test_acc = test_acc time_ev_1 = time.time() print('Eval Acc {:.4f} | Eval Time(s): {:.4f}'.format( eval_acc, time_ev_1 - time_ev_0)) print('Best Eval Acc {:.4f} | Best Test Acc {:.4f}'.format( best_eval_acc, best_test_acc)) time_step = time.time() #if epoch == 1: #break time_epoch_1 = time.time() print('Epoch Time(s): {:.4f}'.format(time_epoch_1 - time_epoch_0)) if eval_every != 1: print('\n') print('Eval-ing...') time_ev_0 = time.time() eval_acc, test_acc = evaluation(model, g, labels, train_nid, val_nid, test_nid, batch_size) if eval_acc > best_eval_acc: best_eval_acc = eval_acc best_test_acc = test_acc time_ev_1 = time.time() print('Eval Acc {:.4f} | Eval Time(s): {:.4f}'.format( eval_acc, time_ev_1 - time_ev_0)) print('Best Eval Acc {:.4f} | Best Test Acc {:.4f}'.format( best_eval_acc, best_test_acc)) print('\n') print('Finish!')