class_docstr: Random node/edge/walk sampler from
  `GraphSAINT: Graph Sampling Based Inductive Learning Method
  <https://arxiv.org/abs/1907.04931>`__
  
  For each call, the sampler samples a node subset and then returns a node induced subgraph.
  There are three options for sampling node subsets:
  
  - For :attr:`'node'` sampler, the probability to sample a node is in proportion
    to its out-degree.
  - The :attr:`'edge'` sampler first samples an edge subset and then use the
    end nodes of the edges.
  - The :attr:`'walk'` sampler uses the nodes visited by random walks. It uniformly selects
    a number of root nodes and then performs a fixed-length random walk from each root node.
  
  Parameters
  ----------
  mode : str
      The sampler to use, which can be :attr:`'node'`, :attr:`'edge'`, or :attr:`'walk'`.
  budget : int or tuple[int]
      Sampler configuration.
  
      - For :attr:`'node'` sampler, budget specifies the number of nodes
        in each sampled subgraph.
      - For :attr:`'edge'` sampler, budget specifies the number of edges
        to sample for inducing a subgraph.
      - For :attr:`'walk'` sampler, budget is a tuple. budget[0] specifies
        the number of root nodes to generate random walks. budget[1] specifies
        the length of a random walk.
  
  cache : bool, optional
      If False, it will not cache the probability arrays for sampling. Setting
      it to False is required if you want to use the sampler across different graphs.
  prefetch_ndata : list[str], optional
      The node data to prefetch for the subgraph.
  
      See :ref:`guide-minibatch-prefetching` for a detailed explanation of prefetching.
  prefetch_edata : list[str], optional
      The edge data to prefetch for the subgraph.
  
      See :ref:`guide-minibatch-prefetching` for a detailed explanation of prefetching.
  output_device : device, optional
      The device of the output subgraphs.
  
  Examples
  --------
  
  >>> import torch
  >>> from dgl.dataloading import SAINTSampler, DataLoader
  >>> num_iters = 1000
  >>> sampler = SAINTSampler(mode='node', budget=6000)
  >>> # Assume g.ndata['feat'] and g.ndata['label'] hold node features and labels
  >>> dataloader = DataLoader(g, torch.arange(num_iters), sampler, num_workers=4)
  >>> for subg in dataloader:
  ...     train_on(subg)
class_docstr_tok: ["Random","node\/edge\/walk","sampler","from","`","GraphSAINT",":","Graph","Sampling","Based","Inductive","Learning","Method","<","https",":","\/\/arxiv.org\/abs\/1907.04931",">","`","__","For","each","call",",","the","sampler","samples","a","node","subset","and","then","returns","a","node","induced","subgraph",".","There","are","three","options","for","sampling","node","subsets",":","-","For",":","attr",":","`","'node","'","`","sampler",",","the","probability","to","sample","a","node","is","in","proportion","to","its","out-degree",".","-","The",":","attr",":","`","'edge","'","`","sampler","first","samples","an","edge","subset","and","then","use","the","end","nodes","of","the","edges",".","-","The",":","attr",":","`","'walk","'","`","sampler","uses","the","nodes","visited","by","random","walks",".","It","uniformly","selects","a","number","of","root","nodes","and","then","performs","a","fixed-length","random","walk","from","each","root","node",".","Parameters","--","--","--","--","--","mode",":","str","The","sampler","to","use",",","which","can","be",":","attr",":","`","'node","'","`",",",":","attr",":","`","'edge","'","`",",","or",":","attr",":","`","'walk","'","`",".","budget",":","int","or","tuple","[","int","]","Sampler","configuration",".","-","For",":","attr",":","`","'node","'","`","sampler",",","budget","specifies","the","number","of","nodes","in","each","sampled","subgraph",".","-","For",":","attr",":","`","'edge","'","`","sampler",",","budget","specifies","the","number","of","edges","to","sample","for","inducing","a","subgraph",".","-","For",":","attr",":","`","'walk","'","`","sampler",",","budget","is","a","tuple",".","budget","[","0","]","specifies","the","number","of","root","nodes","to","generate","random","walks",".","budget","[","1","]","specifies","the","length","of","a","random","walk",".","cache",":","bool",",","optional","If","False",",","it","will","not","cache","the","probability","arrays","for","sampling",".","Setting","it","to","False","is","required","if","you","want","to","use","the","sampler","across","different","graphs",".","prefetch_ndata",":","list","[","str","]",",","optional","The","node","data","to","prefetch","for","the","subgraph",".","See",":","ref",":","`","guide-minibatch-prefetching","`","for","a","detailed","explanation","of","prefetching",".","prefetch_edata",":","list","[","str","]",",","optional","The","edge","data","to","prefetch","for","the","subgraph",".","See",":","ref",":","`","guide-minibatch-prefetching","`","for","a","detailed","explanation","of","prefetching",".","output_device",":","device",",","optional","The","device","of","the","output","subgraphs",".","Examples","--","--","--","--",">",">",">","import","torch",">",">",">","from","dgl.dataloading","import","SAINTSampler",",","DataLoader",">",">",">","num_iters","=","1000",">",">",">","sampler","=","SAINTSampler","(","mode='node","'",",","budget=6000",")",">",">",">","#","Assume","g.ndata","[","'feat","'","]","and","g.ndata","[","'label","'","]","hold","node","features","and","labels",">",">",">","dataloader","=","DataLoader","(","g",",","torch.arange","(","num_iters",")",",","sampler",",","num_workers=4",")",">",">",">","for","subg","in","dataloader",":","...","train_on","(","subg",")"]
docstr: Node ID sampler for random edge sampler
docstr_tok: ["Node","ID","sampler","for","random","edge","sampler"]
code: def edge_sampler(self, g):
      """Node ID sampler for random edge sampler"""
      src, dst = g.edges()
      if self.cache and self.prob is not None:
          prob = self.prob
      else:
          in_deg = g.in_degrees().float().clamp(min=1)
          out_deg = g.out_degrees().float().clamp(min=1)
          # We can reduce the sample space by half if graphs are always symmetric.
          prob = 1.0 / in_deg[dst.long()] + 1.0 / out_deg[src.long()]
          prob /= prob.sum()
          if self.cache:
              self.prob = prob
      sampled_edges = torch.unique(
          choice(len(prob), size=self.budget, prob=prob)
      )
      sampled_nodes = torch.cat(
          [src[sampled_edges], dst[sampled_edges]]
      )
      return sampled_nodes.unique().type(g.idtype)
  
file_path: dgl/python/dgl/dataloading/graphsaint.py
imports: from ..base import DGLError
  from ..random import choice
  from ..sampling import pack_traces, random_walk
  from .base import Sampler, set_edge_lazy_features, set_node_lazy_features
label_desc: Use image node_id 3 for calling the SAINTSampler obj's underlying member method code with example usage: obj.edge_sampler(g) and returns: sampled_nodes