def is_tensor(x, kind=None): """Check whether `x` is tf.Tensor, tf.Variable, tf.RaggedTensor, tf.sparse.SparseTensor, torch.Tensor, torch.sparse.Tensor. Parameters: ---------- x: A python object to check. kind: str, optional. "T" for TensorFlow "P" for PyTorch if not specified, using `backend().kind` instead. Returns: ---------- `True` iff `x` is a (tf or torch) (sparse-)tensor. """ if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return is_tf_tensor(x) else: return is_th_tensor(x)
def astensors(*xs, device=None, kind=None): """Convert input matrices to Tensor(s) or SparseTensor(s). Parameters: ---------- xs: tf.Tensor, tf.Variable, Scipy sparse matrix, Numpy array-like, or a list of them, etc. device (:class:`torch.device`, optional): the desired device of returned tensor. Default: if ``None``, uses the current device for the default tensor type (see :func:`torch.set_default_tensor_type`). :attr:`device` will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. kind: str, optional. "T" for TensorFlow "P" for PyTorch if not specified, using `backend().kind` instead. Returns: ---------- Tensor(s) or SparseTensor(s) with dtype: 1. `graphgallery.floatx()` if `x` in `xs` is floating 2. `graphgallery.intx() ` if `x` in `xs` is integer 3. `Bool` if `x` in `xs` is bool. """ if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.astensors(*xs, device=device) else: return T.th_tensor.astensors(*xs, device=device)
def is_strided_tensor(x, kind=None): """Check whether `x` is a strided (dense) Tensor. Parameters: ---------- x: A python object to check. kind: str, optional. "T" for TensorFlow "P" for PyTorch if not specified, using `backend().kind` instead. Returns: ---------- `True` iff `x` is a (tf or torch) strided (dense) Tensor. """ if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return is_tf_strided_tensor(x) else: return is_th_strided_tensor(x)
def sparse_adj_to_sparse_tensor(x, kind=None): """Converts a Scipy sparse matrix to a TensorFlow/PyTorch SparseTensor. Parameters ---------- x: Scipy sparse matrix Matrix in Scipy sparse format. kind: str, optional. "T" for TensorFlow "P" for PyTorch if not specified, using `backend().kind` instead. Returns ------- S: SparseTensor Matrix as a sparse tensor. """ if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.sparse_adj_to_sparse_tensor(x) else: return T.th_tensor.sparse_adj_to_sparse_tensor(x)
def sparse_tensor_to_sparse_adj(x, *, kind=None): """Converts a SparseTensor to a Scipy sparse matrix (CSR matrix).""" if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.sparse_tensor_to_sparse_adj(x) else: return T.th_tensor.sparse_tensor_to_sparse_adj(x)
def parse_device(device: str, kind: str = None) -> str: if kind is None: kind = backend().kind else: assert_kind(kind) if device is None: # by default, return CPU device if kind == "T": return 'CPU:0' else: return torch.device('cpu') # tensorflow defice if ((hasattr(device, '_device_name') and kind == "T") # pytorch device or (isinstance(device, torch.device) and kind == "P")): return device if hasattr(device, '_device_name'): # tensorflow device meets pytorch backend _device = _device_name.split('/')[-1] elif isinstance(device, torch.device): # pytorch device meets tensorflow backend _device = str(device) else: _device = str(device).lower().split('/')[-1] if not any((_device.startswith("cpu"), _device.startswith("cuda"), _device.startswith("gpu"))): raise RuntimeError( f" Expected one of cpu (CPU), cuda (CUDA), gpu (GPU) at the start of device string, bot got {device}.") if _device.startswith("cuda"): if kind == "T": # tensorflow uses GPU instead of cuda _device = "GPU" + _device[4:] elif _device.startswith("gpu"): if kind == "P": # pytorch uses cuda instead of GPU _device = "cuda" + _device[3:] if kind == "P": if _device.startswith('cuda'): if not torch.cuda.is_available(): raise RuntimeError(f"CUDA is unavailable for PyTorch backend.") # empty cache to avoid unnecessary memory usage # TODO: is this necessary? torch.cuda.empty_cache() return torch.device(_device) if _device.startswith('gpu') and not tf.config.list_physical_devices('GPU'): raise RuntimeError(f"GPU is unavailable for TensorFlow backend.") return _device.upper()
def normalize_adj_tensor(adj, rate=-0.5, fill_weight=1.0, kind=None): if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.normalize_adj_tensor(adj, rate=rate, fill_weight=fill_weight) else: # TODO return T.th_tensor.normalize_adj_tensor(adj, rate=rate, fill_weight=fill_weight)
def sparse_edges_to_sparse_tensor(edge_index: np.ndarray, edge_weight: np.ndarray = None, shape: tuple = None, kind=None): if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.sparse_edges_to_sparse_tensor( edge_index, edge_weight, shape) else: return T.th_tensor.sparse_edges_to_sparse_tensor( edge_index, edge_weight, shape)
def add_selfloops_edge(edge_index, edge_weight, n_nodes=None, fill_weight=1.0, kind=None): if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.normalize_adj_tensor(edge_index, edge_weight, n_nodes=n_nodes, fill_weight=fill_weight) else: # TODO return T.th_tensor.normalize_adj_tensor(edge_index, edge_weight, n_nodes=n_nodes, fill_weight=fill_weight)
def normalize_edge_tensor(edge_index, edge_weight=None, n_nodes=None, fill_weight=1.0, rate=-0.5, kind=None): if kind is None: kind = backend().kind else: assert_kind(kind) if kind == "T": return T.tf_tensor.normalize_adj_tensor(edge_index, edge_weight=edge_weight, n_nodes=n_nodes, fill_weight=fill_weight, rate=rate) else: # TODO return T.th_tensor.normalize_adj_tensor(edge_index, edge_weight=edge_weight, n_nodes=n_nodes, fill_weight=fill_weight, rate=rate)
def astensor(x, *, dtype=None, device=None, kind=None): """Convert input matrices to Tensor or SparseTensor. Parameters: ---------- x: tf.Tensor, tf.Variable, Scipy sparse matrix, Numpy array-like, etc. dtype: The type of Tensor `x`, if not specified, it will automatically using appropriate data type. See `graphgallery.infer_type`. device (:class:`torch.device` or `tf.device`, optional): the desired device of returned tensor. Default: if ``None``, uses the current device for the default tensor type kind: str, optional. "T" for TensorFlow "P" for PyTorch if not specified, using `backend().kind` instead. Returns: ---------- Tensor or SparseTensor with dtype: 1. `graphgallery.floatx()` if `x` is floating 2. `graphgallery.intx() ` if `x` is integer 3. `Bool` if `x` is bool. """ if kind is None: kind = backend().kind else: assert_kind(kind) device = parse_device(device, kind) if kind == "T": return T.tf_tensor.astensor(x, dtype=dtype, device=device) else: return T.th_tensor.astensor(x, dtype=dtype, device=device)
def parse_device(device: Device = None, kind: Optional[str] = None) -> Device: """ Specify the device for corresponding kind Parameters ---------- device : (string, tf.device, torch.device, None) device name such as 'cpu', 'gpu', 'cuda' or an instance of tf.device/torch.device kind : string kind of backend for device 'T' for tensorflow, 'P' for pytorch Returns ------- return string for tf backend return torch.device instance for torch backend """ if kind is None: kind = backend().kind else: assert_kind(kind) if device is None: # by default, return CPU device if kind == "T": return 'CPU:0' else: return torch.device('cpu:0') # existing tensorflow device if hasattr(device, '_device_name') and kind == "T": return device._device_name # existing pytorch device if isinstance(device, torch.device) and kind == "P": return device if hasattr(device, '_device_name'): # tensorflow device meets pytorch backend _device = device._device_name.split('/')[-1] elif isinstance(device, torch.device): # pytorch device meets tensorflow backend _device = str(device) else: _device = str(device).lower().split('/')[-1] if not any( (_device.startswith("cpu"), _device.startswith("cuda"), _device.startswith("gpu"))): raise RuntimeError( f" Expected one of cpu (CPU), cuda (CUDA), gpu (GPU) at the start of device string, but got {device}." ) # modify _device name if _device.startswith("cuda") and kind == "T": _device = "GPU" + _device[4:] # tensorflow uses 'GPU' instead of 'cuda' elif _device.startswith("gpu") and kind == "P": _device = "cuda" + _device[3:] # pytorch uses 'cuda' instead of 'GPU' # pytorch return torch.device if kind == "P": if _device.startswith('cuda'): if not torch.cuda.is_available(): raise RuntimeError(f"CUDA is unavailable for PyTorch backend.") # empty cache to avoid unnecessary memory usage # TODO: is this necessary? torch.cuda.empty_cache() return torch.device(_device) # tf return string if _device.startswith('gpu') and not tf.config.list_physical_devices('GPU'): raise RuntimeError(f"GPU is unavailable for TensorFlow backend.") return _device.upper()