class_docstr: A factor graph object.
  
  A factor graph represents a probability distribution as a bipartite graph
  where marginal distributions of each dimension in the distribution are on
  one side of the graph and factors are on the other side. The distributions
  on the factor side encode probability estimates from the model, whereas the
  distributions on the marginal side encode probability estimates from the
  data. 
  
  Inference is done on the factor graph using the loopy belief propogation
  algorithm. This is an iterative algorithm where "messages" are passed
  along each edge between the marginals and the factors until the estimates
  for the marginals converges. In brief: each message represents what the
  generating node thinks its marginal distribution is with respect to the
  child node. Calculating each message involves marginalizing the parent
  node with respect to *every other* node. When the parent node is already
  a univariate distribution -- either because it is a marginal node or
  a univariate factor node -- no marginalization is needed and it sends
  itself as the message. Basically, a joint probability table will receive
  messages from all the marginal nodes that comprise its dimensions and,
  to each of those marginal nodes, it will send a message back saying what
  it (the joint probability table) thinks its marginal distribution is with
  respect to the messages from the OTHER marginals. More concretely, if a
  joint probability table has two dimensions with marginal node parents
  A and B, it will send a message to A that is itself after marginalizing out
  B, and will send a message to B that is itself after marginalizing out A. 
  
  ..note:: It is worth noting that this algorithm is exact when the structure
  is a tree. If there exist any loops in the factors, i.e., you can draw a
  circle beginning with a factor and then hopping between marginals and
  factors and make it back to the factor without crossing any edges twice,
  the probabilities returned are approximate.
  
  
  Parameters
  ----------
  factors: tuple or list or None
          A set of distribution objects. These do not need to be initialized,
          i.e. can be "Categorical()". Currently, they must be either Categorical
          or JointCategorical distributions. Default is None.
  
  marginals: tuple or list or None
          A set of distribution objects. These must be initialized and be
          Categorical distributions.
  
  edges: list or tuple or None
          A set of edges. Critically, the items in this list must be the
          distribution objects themselves, and the order that edges must match
          the order distributions in a multivariate distribution. Specifically,
          if you have a multivariate distribution, the first edge that includes
          it must correspond to the first dimension, the second edge must
          correspond to the second dimension, etc, and the total number of
          edges cannot exceed the number of dimensions. Default is None.
  
  max_iter: int, optional
          The number of iterations to do in the inference step as distributions
          are converging. Default is 10.
  
  tol: float, optional
          The threshold at which to stop during fitting when the improvement
          goes under. Default is 1e-6.
  
  inertia: float, [0, 1], optional
          Indicates the proportion of the update to apply to the parameters
          during training. When the inertia is 0.0, the update is applied in
          its entirety and the previous parameters are ignored. When the
          inertia is 1.0, the update is entirely ignored and the previous
          parameters are kept, equivalently to if the parameters were frozen.
  
  frozen: bool, optional
          Whether all the parameters associated with this distribution are frozen.
          If you want to freeze individual pameters, or individual values in those
          parameters, you must modify the `frozen` attribute of the tensor or
          parameter directly. Default is False.
  
  check_data: bool, optional
          Whether to check properties of the data and potentially recast it to
          torch.tensors. This does not prevent checking of parameters but can
          slightly speed up computation when you know that your inputs are valid.
          Setting this to False is also necessary for compiling.
  
  verbose: bool, optional
          Whether to print the improvement and timings during training.
class_docstr_tok: ["A","factor","graph","object",".","A","factor","graph","represents","a","probability","distribution","as","a","bipartite","graph","where","marginal","distributions","of","each","dimension","in","the","distribution","are","on","one","side","of","the","graph","and","factors","are","on","the","other","side",".","The","distributions","on","the","factor","side","encode","probability","estimates","from","the","model",",","whereas","the","distributions","on","the","marginal","side","encode","probability","estimates","from","the","data",".","Inference","is","done","on","the","factor","graph","using","the","loopy","belief","propogation","algorithm",".","This","is","an","iterative","algorithm","where","``","messages","''","are","passed","along","each","edge","between","the","marginals","and","the","factors","until","the","estimates","for","the","marginals","converges",".","In","brief",":","each","message","represents","what","the","generating","node","thinks","its","marginal","distribution","is","with","respect","to","the","child","node",".","Calculating","each","message","involves","marginalizing","the","parent","node","with","respect","to","*","every","other","*","node",".","When","the","parent","node","is","already","a","univariate","distribution","--","either","because","it","is","a","marginal","node","or","a","univariate","factor","node","--","no","marginalization","is","needed","and","it","sends","itself","as","the","message",".","Basically",",","a","joint","probability","table","will","receive","messages","from","all","the","marginal","nodes","that","comprise","its","dimensions","and",",","to","each","of","those","marginal","nodes",",","it","will","send","a","message","back","saying","what","it","(","the","joint","probability","table",")","thinks","its","marginal","distribution","is","with","respect","to","the","messages","from","the","OTHER","marginals",".","More","concretely",",","if","a","joint","probability","table","has","two","dimensions","with","marginal","node","parents","A","and","B",",","it","will","send","a","message","to","A","that","is","itself","after","marginalizing","out","B",",","and","will","send","a","message","to","B","that","is","itself","after","marginalizing","out","A",".","..","note",":",":","It","is","worth","noting","that","this","algorithm","is","exact","when","the","structure","is","a","tree",".","If","there","exist","any","loops","in","the","factors",",","i.e.",",","you","can","draw","a","circle","beginning","with","a","factor","and","then","hopping","between","marginals","and","factors","and","make","it","back","to","the","factor","without","crossing","any","edges","twice",",","the","probabilities","returned","are","approximate",".","Parameters","--","--","--","--","--","factors",":","tuple","or","list","or","None","A","set","of","distribution","objects",".","These","do","not","need","to","be","initialized",",","i.e",".","can","be","``","Categorical","(",")","''",".","Currently",",","they","must","be","either","Categorical","or","JointCategorical","distributions",".","Default","is","None",".","marginals",":","tuple","or","list","or","None","A","set","of","distribution","objects",".","These","must","be","initialized","and","be","Categorical","distributions",".","edges",":","list","or","tuple","or","None","A","set","of","edges",".","Critically",",","the","items","in","this","list","must","be","the","distribution","objects","themselves",",","and","the","order","that","edges","must","match","the","order","distributions","in","a","multivariate","distribution",".","Specifically",",","if","you","have","a","multivariate","distribution",",","the","first","edge","that","includes","it","must","correspond","to","the","first","dimension",",","the","second","edge","must","correspond","to","the","second","dimension",",","etc",",","and","the","total","number","of","edges","can","not","exceed","the","number","of","dimensions",".","Default","is","None",".","max_iter",":","int",",","optional","The","number","of","iterations","to","do","in","the","inference","step","as","distributions","are","converging",".","Default","is","10.","tol",":","float",",","optional","The","threshold","at","which","to","stop","during","fitting","when","the","improvement","goes","under",".","Default","is","1e-6",".","inertia",":","float",",","[","0",",","1","]",",","optional","Indicates","the","proportion","of","the","update","to","apply","to","the","parameters","during","training",".","When","the","inertia","is","0.0",",","the","update","is","applied","in","its","entirety","and","the","previous","parameters","are","ignored",".","When","the","inertia","is","1.0",",","the","update","is","entirely","ignored","and","the","previous","parameters","are","kept",",","equivalently","to","if","the","parameters","were","frozen",".","frozen",":","bool",",","optional","Whether","all","the","parameters","associated","with","this","distribution","are","frozen",".","If","you","want","to","freeze","individual","pameters",",","or","individual","values","in","those","parameters",",","you","must","modify","the","`","frozen","`","attribute","of","the","tensor","or","parameter","directly",".","Default","is","False",".","check_data",":","bool",",","optional","Whether","to","check","properties","of","the","data","and","potentially","recast","it","to","torch.tensors",".","This","does","not","prevent","checking","of","parameters","but","can","slightly","speed","up","computation","when","you","know","that","your","inputs","are","valid",".","Setting","this","to","False","is","also","necessary","for","compiling",".","verbose",":","bool",",","optional","Whether","to","print","the","improvement","and","timings","during","training","."]
docstr: Extract the sufficient statistics from a batch of data.
  
  This method calculates the sufficient statistics from optionally
  weighted data and adds them to the stored cache for each distribution
  in the network. Sample weights can either be provided as one
  value per example or as a 2D matrix of weights for each feature in
  each example.
  
  
  Parameters
  ----------
  X: list, tuple, numpy.ndarray, torch.Tensor, shape=(-1, len, self.d)
          A set of examples to summarize.
  
  sample_weight: list, tuple, numpy.ndarray, torch.Tensor, optional
          A set of weights for the examples. This can be either of shape
          (-1, self.d) or a vector of shape (-1,). Default is ones.
  
  
  Returns
  -------
  logp: torch.Tensor, shape=(-1,)
          The log probability of each example.
docstr_tok: ["Extract","the","sufficient","statistics","from","a","batch","of","data",".","This","method","calculates","the","sufficient","statistics","from","optionally","weighted","data","and","adds","them","to","the","stored","cache","for","each","distribution","in","the","network",".","Sample","weights","can","either","be","provided","as","one","value","per","example","or","as","a","2D","matrix","of","weights","for","each","feature","in","each","example",".","Parameters","--","--","--","--","--","X",":","list",",","tuple",",","numpy.ndarray",",","torch.Tensor",",","shape=","(","-1",",","len",",","self.d",")","A","set","of","examples","to","summarize",".","sample_weight",":","list",",","tuple",",","numpy.ndarray",",","torch.Tensor",",","optional","A","set","of","weights","for","the","examples",".","This","can","be","either","of","shape","(","-1",",","self.d",")","or","a","vector","of","shape","(","-1",",",")",".","Default","is","ones",".","Returns","--","--","--","-","logp",":","torch.Tensor",",","shape=","(","-1",",",")","The","log","probability","of","each","example","."]
code: def summarize(self, X, sample_weight=None):
      """Extract the sufficient statistics from a batch of data.
  
      This method calculates the sufficient statistics from optionally
      weighted data and adds them to the stored cache for each distribution
      in the network. Sample weights can either be provided as one
      value per example or as a 2D matrix of weights for each feature in
      each example.
  
  
      Parameters
      ----------
      X: list, tuple, numpy.ndarray, torch.Tensor, shape=(-1, len, self.d)
              A set of examples to summarize.
  
      sample_weight: list, tuple, numpy.ndarray, torch.Tensor, optional
              A set of weights for the examples. This can be either of shape
              (-1, self.d) or a vector of shape (-1,). Default is ones.
  
  
      Returns
      -------
      logp: torch.Tensor, shape=(-1,)
              The log probability of each example.
      """
  
      if self.frozen:
          return
  
      X, sample_weight = super().summarize(
          X, sample_weight=sample_weight
      )
      X = _check_parameter(
          X, "X", ndim=2, check_parameter=self.check_data
      )
  
      for i, factor in enumerate(self.factors):
          factor.summarize(
              X[:, self._factor_edges[i]],
              sample_weight=sample_weight[:, i],
          )
  
imports: import time
  import torch
  import itertools
  from ._utils import _cast_as_tensor
  from ._utils import _update_parameter
  from ._utils import _check_parameter
  from ._utils import _reshape_weights
  from .distributions._distribution import Distribution
  from .distributions._distribution import ConditionalDistribution
  from .distributions import Categorical
  from .distributions import JointCategorical
label_desc: Use image node_id 12 for calling the FactorGraph obj's underlying member method code with example usage: obj.summarize(X, sample_weight) without return types