def test(self, test_data: List[GraphData], best_model_file: Optional[str] = None) -> Tuple[Loss, MicroF1]: print("##### Test Model #####") with torch.no_grad(): if best_model_file: self._net.load_state_dict(torch.load(best_model_file)) self._net.eval() results = [] for graph in test_data: adjs = [sample_neighbors(graph.adj_coo_matrix,size) for size in [25,10]] output = self._net(graph.features_vectors, *adjs) labels = graph.labels loss = self._loss_fn(output, labels) f1 = MicroF1.calc(output, labels) results.append((loss.item(), f1)) avg_loss, avg_f1 = self._avg_results(results) result = Loss("Test Loss", avg_loss), MicroF1("Test F1", avg_f1) print(f"{result[0]}, {result[1]}") return result
def test_given_an_adj_matrix_it_should_sample_a_fixed_number_of_neighbors_with_replacement(setup): adj = torch.tensor([[0, 2, 0, 1, 2, 2, 1, 0, 0, 1, 2, 0, 1, 1, 0], [3, 5, 4, 7, 6, 2, 8, 9, 4, 6, 3, 7, 4, 4, 2]]) sample_size = 5 result = sample_neighbors(adj, sample_size) for idx in range(3): by_idx = result[1][result[0] == idx] assert len(by_idx) == sample_size candidates = torch.unique(adj[1][adj[0] == idx]) for sampled_id in by_idx: assert sampled_id in candidates
def _sample_needed_neighbors(self, node_idxs_batch: List[int]): trg_idx = torch.tensor(node_idxs_batch, device=self._adj.device) batch_idxs = trg_idx.clone() adjs = [] for step_size in reversed(self._neighborhood_sizes): step_adj = self._select_adj_by_src_idxs(batch_idxs) if step_size != -1: step_adj = sample_neighbors(step_adj, step_size) adjs.append(step_adj) batch_idxs = torch.unique(step_adj, sorted=True) adjs = [map_tensor_to_new_idxs(adj, batch_idxs) for adj in adjs] return BatchStep(trg_idx, batch_idxs, map_tensor_to_new_idxs(trg_idx.clone(), batch_idxs), reversed(adjs))
def _evaluate(self) -> Tuple[Loss, MicroF1]: with torch.no_grad(): self._net.eval() results = [] for graph in self._validation_data: adjs = [sample_neighbors(graph.adj_coo_matrix,size) for size in [25,10]] output = self._net(graph.features_vectors, *adjs) labels = graph.labels loss = self._loss_fn(output, labels) f1 = MicroF1.calc(output, labels) results.append((loss.item(), f1)) avg_loss, avg_f1 = self._avg_results(results) return Loss("Validation Loss", avg_loss), MicroF1("Validation F1", avg_f1)
def _train(self) -> Tuple[Loss, MicroF1]: self._net.train() results = [] for train_graph in tqdm(self._train_data): self._optim.zero_grad() adjs = [sample_neighbors(train_graph.adj_coo_matrix,size) for size in [25,10]] output = self._net(train_graph.features_vectors, *adjs) labels = train_graph.labels loss = self._loss_fn(output, labels) f1 = MicroF1.calc(output, labels) loss.backward() torch.nn.utils.clip_grad_value_(self._net.parameters(), 5) self._optim.step() results.append((loss.item(), f1)) avg_loss, avg_f1 = self._avg_results(results) return Loss("Train Loss", avg_loss), MicroF1("Train F1", avg_f1)
def transform_adj_coo_matrix(self, adj_coo_matrix: torch.Tensor, graph: GraphData): return sample_neighbors(adj_coo_matrix, self._sample_size)
def _run_net(self, graph: GraphData) -> torch.Tensor: adjs = [ sample_neighbors(graph.adj_coo_matrix, size) for size in [25, 10] ] return self._net(graph.features_vectors, *adjs)