def process_step(self, adj_transform="normalize_adj", attr_transform=None, graph_transform=None, K=2): graph = gf.get(graph_transform)(self.graph) adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) X, A = gf.astensors(node_attr, adj_matrix, device=self.device) X = SGConvolution(K=K)(X, A) # ``A`` and ``X`` are cached for later use self.register_cache(X=X, A=A)
def data_step(self, adj_transform=("normalize_adj", ("adj_power", dict(power=2)), "to_dense"), feat_transform=None): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) attr_matrix = gf.get(feat_transform)(graph.attr_matrix) feat, adj = gf.astensors(attr_matrix, adj_matrix, device=self.data_device) # ``adj`` and ``feat`` are cached for later use self.register_cache(feat=feat, adj=adj)
def process_step(self, adj_transform="normalize_adj", attr_transform=None, graph_transform=None): graph = gf.get(graph_transform)(self.graph) adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) X, A = gf.astensors(node_attr, adj_matrix.tolil().rows, device=self.device) # ``A`` and ``X`` are cached for later use self.register_cache(X=X, A=A)
def data_step(self, adj_transform="normalize_adj", feat_transform=None, K=2): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) attr_matrix = gf.get(feat_transform)(graph.attr_matrix) feat, adj = gf.astensors(attr_matrix, adj_matrix, device=self.data_device) feat = SGConv(K=K)(feat, adj) # ``adj`` and ``feat`` are cached for later use self.register_cache(feat=feat, adj=adj)
def data_step(self, adj_transform="neighbor_sampler", attr_transform=None): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) # pad with a dummy zero vector node_attr = np.vstack([node_attr, np.zeros(node_attr.shape[1], dtype=self.floatx)]) X, A = gf.astensors(node_attr, device=self.data_device), adj_matrix # ``A`` and ``X`` are cached for later use self.register_cache(X=X, A=A)
def data_step(self, edge_transform=None, attr_transform=None, edge_attr_transform=None): graph = self.graph edge_index, edge_weight = gf.get(edge_transform)(graph.edge_index, graph.edge_weight) node_attr = gf.get(attr_transform)(graph.node_attr) edge_attr = gf.get(edge_attr_transform)(graph.edge_attr) X, edge_index, edge_x = gf.astensors(node_attr, edge_index, edge_attr, device=self.data_device) self.register_cache(X=X, edge_index=edge_index, edge_x=edge_x)
def process_step(self): graph = self.transform.graph_transform(self.graph) graph.node_attr = self.transform.attr_transform(graph.node_attr) batch_adj, batch_x, cluster_member = gf.graph_partition( graph, n_clusters=self.cache.n_clusters) batch_adj = self.transform.adj_transform(*batch_adj) batch_adj, batch_x = gf.astensors(batch_adj, batch_x, device=self.device) # ``A`` and ``X`` and ``cluster_member`` are cached for later use self.register_cache("batch_x", batch_x) self.register_cache("batch_adj", batch_adj) self.register_cache("cluster_member", cluster_member)
def process_step(self, adj_transform="normalize_adj", attr_transform=None, graph_transform=None, label_transform="onehot"): graph = gf.get(graph_transform)(self.graph) adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) label = gf.get(label_transform)(graph.node_label) X, A = gf.astensors(node_attr, adj_matrix, device=self.device) # ``A`` and ``X`` are cached for later use self.register_cache(X=X, A=A, Y=label, idx_all=tf.range(graph.num_nodes, dtype=self.intx))
def data_step(self, adj_transform="normalize_adj", attr_transform=None, num_clusters=10): graph = self.graph batch_adj, batch_x, cluster_member = gf.graph_partition( graph, num_clusters=num_clusters, metis_partition=True) batch_adj = gf.get(adj_transform)(*batch_adj) batch_x = gf.get(attr_transform)(*batch_x) batch_adj, batch_x = gf.astensors(batch_adj, batch_x, device=self.data_device) # ``A`` and ``X`` and ``cluster_member`` are cached for later use self.register_cache(batch_x=batch_x, batch_adj=batch_adj, cluster_member=cluster_member)
def process_step(self, re_decompose=False): graph = self.graph adj_matrix = self.adj_transform(graph.adj_matrix) node_attr = self.attr_transform(graph.node_attr) if re_decompose or not hasattr(self, "U"): V, U = sp.linalg.eigs(adj_matrix.astype('float64'), k=self.k) U, V = U.real, V.real else: U, V = self.U, self.V adj_matrix = (U * V) @ U.T adj_matrix = self.adj_transform(adj_matrix) with tf.device(self.device): self.feature_inputs, self.structure_inputs, self.U, self.V = gf.astensors( node_attr, adj_matrix, U, V, device=self.device)
def attack(self, target, num_budgets=None, direct_attack=True, structure_attack=True, feature_attack=False, disable=False): super().attack(target, num_budgets, direct_attack, structure_attack, feature_attack) if not direct_attack: raise NotImplementedError( f'{self.name} does NOT support indirect attack.') target_index, target_label = gf.astensors([self.target], self.target_label) adj_matrix = self.graph.adj_matrix for it in tqdm(range(self.num_budgets), desc='Peturbing Graph', disable=disable): with tf.device(self.device): gradients = self.compute_gradients(self.modified_adj, self.adj_changes, target_index, target_label) modified_row = tf.gather(self.modified_adj, target_index) gradients = (gradients * (-2 * modified_row + 1)).numpy().ravel() sorted_index = np.argsort(-gradients) for index in sorted_index: u = target v = index % adj_matrix.shape[0] exist = adj_matrix[u, v] if exist and not self.allow_singleton and ( self.modified_degree[u] <= 1 or self.modified_degree[v] <= 1): continue if not self.is_modified(u, v): self.adj_flips[(u, v)] = it self.flip_edge(u, v, exist) break return self
def __init__(self, inputs, y=None, out_index=None, device='cpu', escape=None, **kwargs): dataset = gf.astensors(inputs, y, out_index, device=device, escape=escape) super().__init__([dataset], batch_size=None, collate_fn=lambda feat: feat, device=device, escape=escape, **kwargs)
def data_step(self, adj_transform="normalize_adj", feat_transform=None, num_neighbors=2): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) attr_matrix = gf.get(feat_transform)(graph.attr_matrix) feat, adj = gf.astensors(attr_matrix, adj_matrix, device=self.data_device) self.sampler = gf.ToNeighborMatrix(num_neighbors, self_loop=False, add_dummy=False) # ``adj`` and ``feat`` are cached for later use self.register_cache(feat=feat, adj=adj, adjacency=adj_matrix)
def data_step(self, edge_transform=None, feat_transform=None, edge_feat_transform=None): graph = self.graph edge_index, edge_weight = gf.get(edge_transform)(graph.edge_index, graph.edge_weight) attr_matrix = gf.get(feat_transform)(graph.attr_matrix) edge_attr = gf.get(edge_feat_transform)(graph.edge_attr) feat, edge_index, edge_feat = gf.astensors(attr_matrix, edge_index, edge_attr, device=self.data_device) self.register_cache(feat=feat, edge_index=edge_index, edge_feat=edge_feat)
def __init__(self, inputs, y=None, out_index=None, block_size=2000, device='cpu', escape=None, **kwargs): dataset = gf.astensors(inputs, y, out_index, device=device, escape=escape) super().__init__([dataset], batch_size=None, collate_fn=self.collate_fn, device=device, escape=escape, **kwargs) self.block_size = block_size
def data_step(self, adj_transform="normalize_adj", attr_transform=None, k=35): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) V, U = sp.linalg.eigsh(adj_matrix, k=k) adj_matrix = (U * V) @ U.T adj_matrix = gf.get(adj_transform)(adj_matrix) X, A, U, V = gf.astensors(node_attr, adj_matrix, U, V, device=self.data_device) # ``A`` , ``X`` , U`` and ``V`` are cached for later use self.register_cache(X=X, A=A, U=U, V=V)
def data_step(self, adj_transform="normalize_adj", feat_transform=None, num_clusters=10, partition='louvain'): assert partition in {'metis', 'random', 'louvain'} graph = self.graph batch_adj, batch_feat, cluster_member = gf.graph_partition( graph, num_clusters=num_clusters, partition=partition) batch_adj = gf.get(adj_transform)(*batch_adj) batch_feat = gf.get(feat_transform)(*batch_feat) batch_adj, batch_feat = gf.astensors(batch_adj, batch_feat, device=self.data_device) self.register_cache(batch_feat=batch_feat, batch_adj=batch_adj, cluster_member=cluster_member) # for louvain clustering self.num_clusters = len(cluster_member)
def __init__(self, inputs, neighbors, y=None, out_index=None, sizes=50, device='cpu', escape=None, **kwargs): dataset = gf.astensors(inputs, y, out_index, device=device, escape=escape) super().__init__([dataset], batch_size=None, collate_fn=self.collate_fn, **kwargs) self.neighbors = neighbors self.num_nodes = inputs[0].shape[0] self.sizes = sizes
def process_step(self): graph = self.graph adj_matrix = self.adj_transform(graph.adj_matrix) node_attr = self.attr_transform(graph.node_attr) feature_inputs, structure_inputs = gf.astensors(node_attr, adj_matrix, device=self.device) # To avoid this tensorflow error in large dataset: # InvalidArgumentError: Cannot use GPU when output.shape[1] * nnz(a) > 2^31 [Op:SparseTensorDenseMatMul] if self.graph.num_node_attrs * adj_matrix.nnz > 2**31: device = "CPU" else: device = self.device with tf.device(device): feature_inputs = SGConvolution(order=self.order)( [feature_inputs, structure_inputs]) with tf.device(self.device): self.feature_inputs, self.structure_inputs = feature_inputs, structure_inputs
def process_step(self): graph = self.transform.graph_transform(self.graph) adj_matrix = self.transform.adj_transform(graph.adj_matrix) node_attr = self.transform.attr_transform(graph.node_attr) X, A = gf.astensors(node_attr, adj_matrix, device=self.device) # To avoid this tensorflow error in large dataset: # InvalidArgumentError: Cannot use GPU when output.shape[1] * nnz(a) > 2^31 [Op:SparseTensorDenseMatMul] if X.shape[1] * adj_matrix.nnz > 2**31: device = "CPU" else: device = self.device with tf.device(device): X = SGConvolution(order=self.cache.order)([X, A]) with tf.device(self.device): # ``A`` and ``X`` are cached for later use self.register_cache("X", X) self.register_cache("A", A)
def data_step(self, adj_transform="normalize_adj", feat_transform=None, k=35): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) attr_matrix = gf.get(feat_transform)(graph.attr_matrix) V, U = sp.linalg.eigsh(adj_matrix, k=k) adj_matrix = (U * V) @ U.T adj_matrix[adj_matrix < 0] = 0. adj_matrix = gf.get(adj_transform)(adj_matrix) feat, adj, U, V = gf.astensors(attr_matrix, adj_matrix, U, V, device=self.data_device) # ``adj`` , ``feat`` , U`` and ``V`` are cached for later use self.register_cache(feat=feat, adj=adj, U=U, V=V)
def data_step(self, adj_transform="normalize_adj", attr_transform=None, K=2): graph = self.graph adj_matrix = gf.get(adj_transform)(graph.adj_matrix) node_attr = gf.get(attr_transform)(graph.node_attr) X, A = gf.astensors(node_attr, adj_matrix, device=self.data_device) # To avoid this tensorflow error in large dataset: # InvalidArgumentError: Cannot use GPU when output.shape[1] * nnz(a) > 2^31 [Op:SparseTensorDenseMatMul] if X.shape[1] * adj_matrix.nnz > 2**31: device = "CPU" else: device = self.device with tf.device(device): X = SGConv(K=K)([X, A]) with tf.device(self.device): # ``A`` and ``X`` are cached for later use self.register_cache(X=X, A=A)
def train(self, idx_train, idx_val=None, pre_train_epochs=100, epochs=100, early_stopping=None, verbose=1, save_best=True, ckpt_path=None, as_model=False, monitor='val_accuracy', early_stop_metric='val_loss'): histories = [] index_all = tf.range(self.graph.num_nodes, dtype=self.intx) # pre train model_q self.model = self.model_q history = super().train(idx_train, idx_val, epochs=pre_train_epochs, early_stopping=early_stopping, verbose=verbose, save_best=save_best, ckpt_path=ckpt_path, as_model=True, monitor=monitor, early_stop_metric=early_stop_metric) histories.append(history) label_predict = self.predict(index_all).argmax(1) label_predict[idx_train] = self.graph.node_label[idx_train] label_predict = tf.one_hot(label_predict, depth=self.graph.num_node_classes) # train model_p fitst train_sequence = FullBatchNodeSequence( [label_predict, self.structure_inputs, index_all], label_predict, device=self.device) if idx_val is not None: val_sequence = FullBatchNodeSequence( [label_predict, self.structure_inputs, idx_val], self.label_onehot[idx_val], device=self.device) else: val_sequence = None self.model = self.model_p history = super().train(train_sequence, val_sequence, epochs=epochs, early_stopping=early_stopping, verbose=verbose, save_best=save_best, ckpt_path=ckpt_path, as_model=as_model, monitor=monitor, early_stop_metric=early_stop_metric) histories.append(history) # then train model_q again label_predict = self.model.predict_on_batch( gf.astensors(label_predict, self.structure_inputs, index_all, device=self.device)) label_predict = softmax(label_predict) if tf.is_tensor(label_predict): label_predict = label_predict.numpy() label_predict[idx_train] = self.label_onehot[idx_train] self.model = self.model_q train_sequence = FullBatchNodeSequence( [self.feature_inputs, self.structure_inputs, index_all], label_predict, device=self.device) history = super().train(train_sequence, idx_val, epochs=epochs, early_stopping=early_stopping, verbose=verbose, save_best=save_best, ckpt_path=ckpt_path, as_model=as_model, monitor=monitor, early_stop_metric=early_stop_metric) histories.append(history) return histories