def test_transform(): g = create_test_heterograph() x = F.randn((3, 5)) g.nodes['user'].data['h'] = x new_g = dgl.metapath_reachable_graph(g, ['follows', 'plays']) assert new_g.ntypes == ['user', 'game'] assert new_g.number_of_edges() == 3 assert F.asnumpy(new_g.has_edges_between([0, 0, 1], [0, 1, 1])).all() new_g = dgl.metapath_reachable_graph(g, ['follows']) assert new_g.ntypes == ['user'] assert new_g.number_of_edges() == 2 assert F.asnumpy(new_g.has_edges_between([0, 1], [1, 2])).all()
def train(args): set_random_seed(args.seed) device = get_device(args.device) data, g, feats, labels, predict_ntype, relations, neighbor_sizes, \ pos, pos_threshold, train_mask, val_mask, test_mask = load_data(args.dataset, device) bgs = [g[rel] for rel in relations] # 邻居-目标顶点二分图 mgs = [ dgl.add_self_loop( dgl.remove_self_loop(dgl.metapath_reachable_graph(g, mp))).to(device) for mp in data.metapaths ] # 基于元路径的邻居同构图 model = HeCo([feat.shape[1] for feat in feats], args.num_hidden, args.feat_drop, args.attn_drop, neighbor_sizes, len(data.metapaths), args.tau, args.lambda_).to(device) optimizer = optim.Adam(model.parameters(), lr=args.lr) for epoch in range(args.epochs): model.train() loss = model(bgs, mgs, feats, pos) optimizer.zero_grad() loss.backward() optimizer.step() print('Epoch {:d} | Train Loss {:.4f}'.format(epoch, loss.item())) evaluate(model, mgs, feats[0], labels, data.num_classes, train_mask, test_mask, args.seed)
def train(args): set_random_seed(args.seed) if args.hetero: data = HETERO_DATASET[args.dataset]() g = data[0] gs = [ dgl.metapath_reachable_graph(g, metapath) for metapath in data.metapaths ] for i in range(len(gs)): gs[i] = dgl.add_self_loop(dgl.remove_self_loop(gs[i])) ntype = data.predict_ntype num_classes = data.num_classes features = g.nodes[ntype].data['feat'] labels = g.nodes[ntype].data['label'] train_mask = g.nodes[ntype].data['train_mask'] val_mask = g.nodes[ntype].data['val_mask'] test_mask = g.nodes[ntype].data['test_mask'] else: data = DATASET[args.dataset]() gs = data[0] num_classes = data.num_classes features = gs[0].ndata['feat'] labels = gs[0].ndata['label'] train_mask = gs[0].ndata['train_mask'] val_mask = gs[0].ndata['val_mask'] test_mask = gs[0].ndata['test_mask'] model = HAN(len(gs), features.shape[1], args.num_hidden, num_classes, args.num_heads, args.dropout) optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay) score = micro_macro_f1_score if args.task == 'clf' else nmi_ari_score if args.task == 'clf': metrics = 'Epoch {:d} | Train Loss {:.4f} | Train Micro-F1 {:.4f} | Train Macro-F1 {:.4f}' \ ' | Val Micro-F1 {:.4f} | Val Macro-F1 {:.4f}' else: metrics = 'Epoch {:d} | Train Loss {:.4f} | Train NMI {:.4f} | Train ARI {:.4f}' \ ' | Val NMI {:.4f} | Val ARI {:.4f}' for epoch in range(args.epochs): model.train() logits = model(gs, features) loss = F.cross_entropy(logits[train_mask], labels[train_mask]) optimizer.zero_grad() loss.backward() optimizer.step() train_metrics = score(logits[train_mask], labels[train_mask]) val_metrics = score(logits[val_mask], labels[val_mask]) print(metrics.format(epoch, loss.item(), *train_metrics, *val_metrics)) test_metrics = evaluate(model, gs, features, labels, test_mask, score) if args.task == 'clf': print('Test Micro-F1 {:.4f} | Test Macro-F1 {:.4f}'.format( *test_metrics)) else: print('Test NMI {:.4f} | Test ARI {:.4f}'.format(*test_metrics))
def forward(self, g, h): semantic_embeddings = {'movie': [], 'actor': [], 'director': []} if self._cached_graph is None or self._cached_graph is not g: self._cached_graph = g self._cached_coalesced_graph.clear() for meta_path in self.meta_paths: if len(meta_path) > 1: self._cached_coalesced_graph[ meta_path] = dgl.metapath_reachable_graph( g, meta_path ) # return a homogeneous or unidirectional bipartite graphs elif len(meta_path) == 1: if meta_path in { ('am', ), }: print('******************am**********************') self._cached_coalesced_graph[ meta_path] = dgl.edge_type_subgraph( g, [('actor', 'am', 'movie')]) elif meta_path in {('dm', )}: print('******************dm**********************') self._cached_coalesced_graph[ meta_path] = dgl.edge_type_subgraph( g, [('director', 'dm', 'movie')]) for i, meta_path in enumerate(self.meta_paths): new_g = self._cached_coalesced_graph[meta_path] if new_g.is_homogeneous: ntype = new_g.ntypes[0] semantic_embeddings[ntype].append(self.hsmg_layers[i]( new_g, h[ntype]).flatten(1)) else: if meta_path in { ('am', ), }: h_ = (h['actor'], h['movie']) semantic_embeddings['movie'].append(self.hsmg_layers[i]( new_g, h_)) elif meta_path in {('dm', )}: h_ = (h['director'], h['movie']) semantic_embeddings['movie'].append(self.hsmg_layers[i]( new_g, h_)) embedings = {} for ntype in semantic_embeddings.keys(): if ntype == 'movie': semantic_embeddings[ntype] = torch.stack( semantic_embeddings[ntype], dim=1) embedings[ntype] = self.semantic_attention_m( semantic_embeddings[ntype]) # elif ntype=='actor' and semantic_embeddings[ntype]: # semantic_embeddings[ntype] = torch.stack(semantic_embeddings[ntype], dim=1) # embedings[ntype] = self.semantic_attention_a(semantic_embeddings[ntype]) # elif ntype=='director' and semantic_embeddings[ntype]: # semantic_embeddings[ntype] = torch.stack(semantic_embeddings[ntype], dim=1) # embedings[ntype] = self.semantic_attention_d(semantic_embeddings[ntype]) return embedings
def forward(self, g, h): semantic_embeddings = [] if self._cached_graph is None or self._cached_graph is not g: # 第一次,建立一张metapath下的异构图 self._cached_graph = g self._cached_coalesced_graph.clear() for meta_path in self.meta_paths: self._cached_coalesced_graph[meta_path] = dgl.metapath_reachable_graph( g, meta_path) # 构建异构图的邻居; # self._cached_coalesced_graph 多个metapath下的异构图 for i, meta_path in enumerate(self.meta_paths): new_g = self._cached_coalesced_graph[meta_path] # meta-path下的节点邻居图 semantic_embeddings.append(self.gat_layers[i](new_g, h).flatten(1)) # 图attention semantic_embeddings = torch.stack(semantic_embeddings, dim=1) # (N, M, D * K) return self.semantic_attention(semantic_embeddings) # (N, D * K)
def forward(self, g, h): semantic_embeddings = [] #obtain metapath reachable graph if self._cached_graph is None or self._cached_graph is not g: self._cached_graph = g self._cached_coalesced_graph.clear() for meta_path_pattern in self.meta_path_patterns: self._cached_coalesced_graph[ meta_path_pattern] = dgl.metapath_reachable_graph( g, meta_path_pattern) for i, meta_path_pattern in enumerate(self.meta_path_patterns): new_g = self._cached_coalesced_graph[meta_path_pattern] semantic_embeddings.append(self.gat_layers[i](new_g, h).flatten(1)) semantic_embeddings = torch.stack(semantic_embeddings, dim=1) # (N, M, D * K) return self.semantic_attention(semantic_embeddings) # (N, D * K)
def forward(self, g, h): semantic_embeddings = {'user':[], 'item':[]} if self._cached_graph is None or self._cached_graph is not g: self._cached_graph = g self._cached_coalesced_graph.clear() for meta_path in self.meta_paths: if len(meta_path) > 1: self._cached_coalesced_graph[meta_path] = dgl.metapath_reachable_graph(g, meta_path) # return a homogeneous or unidirectional bipartite graphs elif len(meta_path) == 1: if meta_path in {('ui',)}: print('******************ui**********************') self._cached_coalesced_graph[meta_path] = dgl.edge_type_subgraph(g, [('user', 'ui', 'item')]) elif meta_path in {('iu',)}: print('******************iu**********************') self._cached_coalesced_graph[meta_path] = dgl.edge_type_subgraph(g, [('item', 'iu', 'user')]) for i, meta_path in enumerate(self.meta_paths): new_g = self._cached_coalesced_graph[meta_path] if new_g.is_homogeneous: ntype = new_g.ntypes[0] if ntype == 'user': h_ = h['user'] elif ntype == 'item': h_ = h['item'] semantic_embeddings[ntype].append(self.gat_layers[i](new_g, h_).flatten(1)) else: if meta_path in {('ui',), }: semantic_embeddings['item'].append(self.gat_layers[i](new_g, (h['user'], h['item']))) elif meta_path in {('iu',)}: semantic_embeddings['user'].append(self.gat_layers[i](new_g, (h['item'], h['user']))) embedings = {} for ntype in semantic_embeddings.keys(): if ntype=='user': semantic_embeddings[ntype] = torch.stack(semantic_embeddings[ntype], dim=1) embedings[ntype] = self.semantic_attention_u(semantic_embeddings[ntype]) elif ntype=='item' and semantic_embeddings[ntype]: semantic_embeddings[ntype] = torch.stack(semantic_embeddings[ntype], dim=1) embedings[ntype] = self.semantic_attention_i(semantic_embeddings[ntype]) return embedings