def augment_feat(attr_matrix: np.ndarray, N: int, fill_weight: Union[float, list, np.ndarray] = 0.): """Augment a specified node feature matrix. Examples ---------- >>> augment_feat(attr_matrix, 10, fill_weight=1.0) >>> augment_feat(attr_matrix, 10, fill_weight=attr_matrix[-1]) Parameters ---------- attr_matrix: shape [num_nodes, num_nodes]. A Scipy sparse adjacency matrix. N: number of added nodes. node ids [num_nodes, ..., num_nodes+N-1]. fill_weight: float or 1D array. + float scalar: the weight for the augmented matrix + 1D array: repeated N times to augment the matrix. """ if gg.is_scalar(fill_weight): M = np.zeros([N, attr_matrix.shape[1]], dtype=attr_matrix.dtype) + fill_weight elif isinstance(fill_weight, (list, np.ndarray)): fill_weight = fill_weight.astype(attr_matrix.dtype, copy=False) M = np.tile(fill_weight, N).reshape([N, -1]) else: raise ValueError(f"Unrecognized input: {fill_weight}.") augmented_feat = np.vstack([attr_matrix, M]) return augmented_feat
def repeat(src: Any, length: int) -> Any: if src == [] or src == (): return [] if any((gg.is_scalar(src), isinstance(src, str), src is None)): return list(itertools.repeat(src, length)) if len(src) > length: return src[:length] if len(src) < length: return list(src) + list(itertools.repeat(src[-1], length - len(src))) return src
def astensor(x, *, dtype=None, device=None, escape=None): try: if x is None or (escape is not None and isinstance(x, escape)): return x except TypeError: raise TypeError(f"argument 'escape' must be a type or tuple of types.") if dtype is None: dtype = gf.infer_type(x) if isinstance(dtype, (np.dtype, str)): dtype = data_type_dict().get(str(dtype), dtype) elif not isinstance(dtype, torch.dtype): raise TypeError( f"argument 'dtype' must be torch.dtype, np.dtype or str, but got {type(dtype)}." ) if is_tensor(x): tensor = x.to(dtype) elif gf.is_tensor(x, backend='tensorflow'): return astensor(gf.tensoras(x), dtype=dtype, device=device, escape=escape) elif sp.isspmatrix(x): if gg.backend() == "dgl_torch": import dgl tensor = dgl.from_scipy(x, idtype=getattr(torch, gg.intx())) elif gg.backend() == "pyg": edge_index, edge_weight = gf.sparse_adj_to_edge(x) return (astensor(edge_index, dtype=gg.intx(), device=device, escape=escape), astensor(edge_weight, dtype=gg.floatx(), device=device, escape=escape)) else: tensor = sparse_adj_to_sparse_tensor(x, dtype=dtype) elif any((isinstance(x, (np.ndarray, np.matrix)), gg.is_listlike(x), gg.is_scalar(x))): tensor = torch.tensor(x, dtype=dtype, device=device) else: raise TypeError( f"Invalid type of inputs. Allowed data type (Tensor, SparseTensor, Numpy array, Scipy sparse tensor, None), but got {type(x)}." ) return tensor.to(device)
def budget_as_int(self, num_budgets, max_perturbations): max_perturbations = max(max_perturbations, self.max_perturbations) if not gg.is_scalar(num_budgets) or num_budgets <= 0: raise ValueError( f"'num_budgets' must be a postive integer scalar. but got '{num_budgets}'." ) if num_budgets > max_perturbations: raise ValueError( f"'num_budgets' should be less than or equal the maximum allowed perturbations: {max_perturbations}." "if you want to use larget budgets, you could set 'attacker.set_max_perturbations(a_large_budgets)'." ) if num_budgets < 1.: num_budgets = max_perturbations * num_budgets return int(num_budgets)
def astensor(x, *, dtype=None, device=None, escape=None): try: if x is None or (escape is not None and isinstance(x, escape)): return x except TypeError: raise TypeError(f"argument 'escape' must be a type or tuple of types.") if dtype is None: dtype = gf.infer_type(x) elif isinstance(dtype, tf.dtypes.DType): dtype = dtype.name elif isinstance(dtype, (np.dtype, str)): dtype = str(dtype) else: raise TypeError( f"argument 'dtype' must be tf.dtypes.DType, np.dtype or str, but got {type(dtype)}." ) with tf.device(device): if is_tensor(x): if x.dtype != dtype: return tf.cast(x, dtype=dtype) return tf.identity(x) elif gf.is_tensor(x, backend='torch'): return astensor(gf.tensoras(x), dtype=dtype, device=device, escape=escape) elif sp.isspmatrix(x): if gg.backend() == "dgl_tf": import dgl return dgl.from_scipy(x, idtype=getattr(tf, gg.intx())).to(device) else: return sparse_adj_to_sparse_tensor(x, dtype=dtype) elif any((isinstance(x, (np.ndarray, np.matrix)), gg.is_listlike(x), gg.is_scalar(x))): return tf.convert_to_tensor(x, dtype=dtype) else: raise TypeError( f"Invalid type of inputs. Allowed data type(Tensor, SparseTensor, Numpy array, Scipy sparse matrix, None), but got {type(x)}." )
def set_max_perturbations(self, max_perturbations=np.inf, verbose=True): assert gg.is_scalar(max_perturbations), max_perturbations self._max_perturbations = max_perturbations if verbose: print(f"Set maximum perturbations: {max_perturbations}")
def astensor(x, *, dtype=None, device=None, escape=None) -> torch.Tensor: try: if x is None or (escape is not None and isinstance(x, escape)): return x except TypeError: raise TypeError(f"argument 'escape' must be a type or tuple of types.") device = torch.device(device) if device is not None else torch.device( "cpu") # update: accept `dict` instance if isinstance(x, dict): for k, v in x.items(): try: x[k] = astensor(v, dtype=dtype, device=device, escape=escape) except TypeError: pass return x if dtype is None: dtype = gf.infer_type(x) if isinstance(dtype, (np.dtype, str)): dtype = data_type_dict().get(str(dtype), dtype) elif not isinstance(dtype, torch.dtype): raise TypeError( f"argument 'dtype' must be torch.dtype, np.dtype or str, but got {type(dtype)}." ) if is_tensor(x): tensor = x.to(dtype) elif sp.isspmatrix(x): if gg.backend() == "dgl": import dgl if x.sum() != x.nnz: warnings.warn( "Got a weighted sparse matrix with elements not equal to 1. " "The element weights can be accessed by `g.edata['_edge_weight'].`" ) tensor = dgl.from_scipy(x, idtype=torch.int64, eweight_name="_edge_weight") else: tensor = dgl.from_scipy(x, idtype=torch.int64) elif gg.backend() == "pyg": edge_index, edge_weight = gf.sparse_adj_to_edge(x) return (astensor(edge_index, dtype=torch.int64, device=device, escape=escape), astensor(edge_weight, dtype=torch.float32, device=device, escape=escape)) else: tensor = sparse_adj_to_sparse_tensor(x, dtype=dtype) elif any((isinstance(x, (np.ndarray, np.matrix)), gg.is_listlike(x), gg.is_scalar(x))): tensor = torch.tensor(x, dtype=dtype, device=device) else: raise TypeError( f"Invalid type of inputs. Allowed data type (Tensor, SparseTensor, Numpy array, Scipy sparse tensor, None), but got {type(x)}." ) return tensor.to(device)