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
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
    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)
Exemple #5
0
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)}."
            )
Exemple #6
0
 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}")
Exemple #7
0
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)