class_docstr: MetricCollection class can be used to chain metrics that have the same call pattern into one single class.
  
  Args:
      metrics: One of the following
  
          * list or tuple (sequence): if metrics are passed in as a list or tuple, will use the metrics class name
            as key for output dict. Therefore, two metrics of the same class cannot be chained this way.
  
          * arguments: similar to passing in as a list, metrics passed in as arguments will use their metric
            class name as key for the output dict.
  
          * dict: if metrics are passed in as a dict, will use each key in the dict as key for output dict.
            Use this format if you want to chain together multiple of the same metric with different parameters.
            Note that the keys in the output dict will be sorted alphabetically.
  
      prefix: a string to append in front of the keys of the output dict
  
      postfix: a string to append after the keys of the output dict
  
      compute_groups:
          By default the MetricCollection will try to reduce the computations needed for the metrics in the collection
          by checking if they belong to the same **compute group**. All metrics in a compute group share the same
          metric state and are therefore only different in their compute step e.g. accuracy, precision and recall
          can all be computed from the true positives/negatives and false positives/negatives. By default,
          this argument is ``True`` which enables this feature. Set this argument to `False` for disabling
          this behaviour. Can also be set to a list of lists of metrics for setting the compute groups yourself.
  
  .. note::
      The compute groups feature can significantly speedup the calculation of metrics under the right conditions.
      First, the feature is only available when calling the ``update`` method and not when calling ``forward`` method
      due to the internal logic of ``forward`` preventing this. Secondly, since we compute groups share metric
      states by reference, calling ``.items()``, ``.values()`` etc. on the metric collection will break this
      reference and a copy of states are instead returned in this case (reference will be reestablished on the next
      call to ``update``).
  
  .. note::
      Metric collections can be nested at initialization (see last example) but the output of the collection will
      still be a single flatten dictionary combining the prefix and postfix arguments from the nested collection.
  
  Raises:
      ValueError:
          If one of the elements of ``metrics`` is not an instance of ``pl.metrics.Metric``.
      ValueError:
          If two elements in ``metrics`` have the same ``name``.
      ValueError:
          If ``metrics`` is not a ``list``, ``tuple`` or a ``dict``.
      ValueError:
          If ``metrics`` is ``dict`` and additional_metrics are passed in.
      ValueError:
          If ``prefix`` is set and it is not a string.
      ValueError:
          If ``postfix`` is set and it is not a string.
  
  Example::
      In the most basic case, the metrics can be passed in as a list or tuple. The keys of the output dict will be
      the same as the class name of the metric:
  
      >>> from torch import tensor
      >>> from pprint import pprint
      >>> from torchmetrics import MetricCollection
      >>> from torchmetrics.regression import MeanSquaredError
      >>> from torchmetrics.classification import MulticlassAccuracy, MulticlassPrecision, MulticlassRecall
      >>> target = tensor([0, 2, 0, 2, 0, 1, 0, 2])
      >>> preds = tensor([2, 1, 2, 0, 1, 2, 2, 2])
      >>> metrics = MetricCollection([MulticlassAccuracy(num_classes=3, average='micro'),
      ...                             MulticlassPrecision(num_classes=3, average='macro'),
      ...                             MulticlassRecall(num_classes=3, average='macro')])
      >>> metrics(preds, target)  # doctest: +NORMALIZE_WHITESPACE
      {'MulticlassAccuracy': tensor(0.1250),
       'MulticlassPrecision': tensor(0.0667),
       'MulticlassRecall': tensor(0.1111)}
  
  Example::
      Alternatively, metrics can be passed in as arguments. The keys of the output dict will be the same as the
      class name of the metric:
  
      >>> metrics = MetricCollection(MulticlassAccuracy(num_classes=3, average='micro'),
      ...                            MulticlassPrecision(num_classes=3, average='macro'),
      ...                            MulticlassRecall(num_classes=3, average='macro'))
      >>> metrics(preds, target)  # doctest: +NORMALIZE_WHITESPACE
      {'MulticlassAccuracy': tensor(0.1250),
       'MulticlassPrecision': tensor(0.0667),
       'MulticlassRecall': tensor(0.1111)}
  
  Example::
      If multiple of the same metric class (with different parameters) should be chained together, metrics can be
      passed in as a dict and the output dict will have the same keys as the input dict:
  
      >>> metrics = MetricCollection({'micro_recall': MulticlassRecall(num_classes=3, average='micro'),
      ...                             'macro_recall': MulticlassRecall(num_classes=3, average='macro')})
      >>> same_metric = metrics.clone()
      >>> pprint(metrics(preds, target))
      {'macro_recall': tensor(0.1111), 'micro_recall': tensor(0.1250)}
      >>> pprint(same_metric(preds, target))
      {'macro_recall': tensor(0.1111), 'micro_recall': tensor(0.1250)}
  
  Example::
      Metric collections can also be nested up to a single time. The output of the collection will still be a single
      dict with the prefix and postfix arguments from the nested collection:
  
      >>> metrics = MetricCollection([
      ...     MetricCollection([
      ...         MulticlassAccuracy(num_classes=3, average='macro'),
      ...         MulticlassPrecision(num_classes=3, average='macro')
      ...     ], postfix='_macro'),
      ...     MetricCollection([
      ...         MulticlassAccuracy(num_classes=3, average='micro'),
      ...         MulticlassPrecision(num_classes=3, average='micro')
      ...     ], postfix='_micro'),
      ... ], prefix='valmetrics/')
      >>> pprint(metrics(preds, target))  # doctest: +NORMALIZE_WHITESPACE
      {'valmetrics/MulticlassAccuracy_macro': tensor(0.1111),
       'valmetrics/MulticlassAccuracy_micro': tensor(0.1250),
       'valmetrics/MulticlassPrecision_macro': tensor(0.0667),
       'valmetrics/MulticlassPrecision_micro': tensor(0.1250)}
  
  Example::
      The `compute_groups` argument allow you to specify which metrics should share metric state. By default, this
      will automatically be derived but can also be set manually.
  
      >>> metrics = MetricCollection(
      ...     MulticlassRecall(num_classes=3, average='macro'),
      ...     MulticlassPrecision(num_classes=3, average='macro'),
      ...     MeanSquaredError(),
      ...     compute_groups=[['MulticlassRecall', 'MulticlassPrecision'], ['MeanSquaredError']]
      ... )
      >>> metrics.update(preds, target)
      >>> pprint(metrics.compute())
      {'MeanSquaredError': tensor(2.3750), 'MulticlassPrecision': tensor(0.0667), 'MulticlassRecall': tensor(0.1111)}
      >>> pprint(metrics.compute_groups)
      {0: ['MulticlassRecall', 'MulticlassPrecision'], 1: ['MeanSquaredError']}
class_docstr_tok: ["MetricCollection","class","can","be","used","to","chain","metrics","that","have","the","same","call","pattern","into","one","single","class",".","Args",":","metrics",":","One","of","the","following","*","list","or","tuple","(","sequence",")",":","if","metrics","are","passed","in","as","a","list","or","tuple",",","will","use","the","metrics","class","name","as","key","for","output","dict",".","Therefore",",","two","metrics","of","the","same","class","can","not","be","chained","this","way",".","*","arguments",":","similar","to","passing","in","as","a","list",",","metrics","passed","in","as","arguments","will","use","their","metric","class","name","as","key","for","the","output","dict",".","*","dict",":","if","metrics","are","passed","in","as","a","dict",",","will","use","each","key","in","the","dict","as","key","for","output","dict",".","Use","this","format","if","you","want","to","chain","together","multiple","of","the","same","metric","with","different","parameters",".","Note","that","the","keys","in","the","output","dict","will","be","sorted","alphabetically",".","prefix",":","a","string","to","append","in","front","of","the","keys","of","the","output","dict","postfix",":","a","string","to","append","after","the","keys","of","the","output","dict","compute_groups",":","By","default","the","MetricCollection","will","try","to","reduce","the","computations","needed","for","the","metrics","in","the","collection","by","checking","if","they","belong","to","the","same","*","*","compute","group","*","*",".","All","metrics","in","a","compute","group","share","the","same","metric","state","and","are","therefore","only","different","in","their","compute","step","e.g",".","accuracy",",","precision","and","recall","can","all","be","computed","from","the","true","positives\/negatives","and","false","positives\/negatives",".","By","default",",","this","argument","is","``","True","``","which","enables","this","feature",".","Set","this","argument","to","`","False","`","for","disabling","this","behaviour",".","Can","also","be","set","to","a","list","of","lists","of","metrics","for","setting","the","compute","groups","yourself",".","..","note",":",":","The","compute","groups","feature","can","significantly","speedup","the","calculation","of","metrics","under","the","right","conditions",".","First",",","the","feature","is","only","available","when","calling","the","``","update","``","method","and","not","when","calling","``","forward","``","method","due","to","the","internal","logic","of","``","forward","``","preventing","this",".","Secondly",",","since","we","compute","groups","share","metric","states","by","reference",",","calling","``",".items","(",")","``",",","``",".values","(",")","``","etc",".","on","the","metric","collection","will","break","this","reference","and","a","copy","of","states","are","instead","returned","in","this","case","(","reference","will","be","reestablished","on","the","next","call","to","``","update","``",")",".","..","note",":",":","Metric","collections","can","be","nested","at","initialization","(","see","last","example",")","but","the","output","of","the","collection","will","still","be","a","single","flatten","dictionary","combining","the","prefix","and","postfix","arguments","from","the","nested","collection",".","Raises",":","ValueError",":","If","one","of","the","elements","of","``","metrics","``","is","not","an","instance","of","``","pl.metrics.Metric","``",".","ValueError",":","If","two","elements","in","``","metrics","``","have","the","same","``","name","``",".","ValueError",":","If","``","metrics","``","is","not","a","``","list","``",",","``","tuple","``","or","a","``","dict","``",".","ValueError",":","If","``","metrics","``","is","``","dict","``","and","additional_metrics","are","passed","in",".","ValueError",":","If","``","prefix","``","is","set","and","it","is","not","a","string",".","ValueError",":","If","``","postfix","``","is","set","and","it","is","not","a","string",".","Example",":",":","In","the","most","basic","case",",","the","metrics","can","be","passed","in","as","a","list","or","tuple",".","The","keys","of","the","output","dict","will","be","the","same","as","the","class","name","of","the","metric",":",">",">",">","from","torch","import","tensor",">",">",">","from","pprint","import","pprint",">",">",">","from","torchmetrics","import","MetricCollection",">",">",">","from","torchmetrics.regression","import","MeanSquaredError",">",">",">","from","torchmetrics.classification","import","MulticlassAccuracy",",","MulticlassPrecision",",","MulticlassRecall",">",">",">","target","=","tensor","(","[","0",",","2",",","0",",","2",",","0",",","1",",","0",",","2","]",")",">",">",">","preds","=","tensor","(","[","2",",","1",",","2",",","0",",","1",",","2",",","2",",","2","]",")",">",">",">","metrics","=","MetricCollection","(","[","MulticlassAccuracy","(","num_classes=3",",","average='micro","'",")",",","...","MulticlassPrecision","(","num_classes=3",",","average='macro","'",")",",","...","MulticlassRecall","(","num_classes=3",",","average='macro","'",")","]",")",">",">",">","metrics","(","preds",",","target",")","#","doctest",":","+NORMALIZE_WHITESPACE","{","'MulticlassAccuracy","'",":","tensor","(","0.1250",")",",","'MulticlassPrecision","'",":","tensor","(","0.0667",")",",","'MulticlassRecall","'",":","tensor","(","0.1111",")","}","Example",":",":","Alternatively",",","metrics","can","be","passed","in","as","arguments",".","The","keys","of","the","output","dict","will","be","the","same","as","the","class","name","of","the","metric",":",">",">",">","metrics","=","MetricCollection","(","MulticlassAccuracy","(","num_classes=3",",","average='micro","'",")",",","...","MulticlassPrecision","(","num_classes=3",",","average='macro","'",")",",","...","MulticlassRecall","(","num_classes=3",",","average='macro","'",")",")",">",">",">","metrics","(","preds",",","target",")","#","doctest",":","+NORMALIZE_WHITESPACE","{","'MulticlassAccuracy","'",":","tensor","(","0.1250",")",",","'MulticlassPrecision","'",":","tensor","(","0.0667",")",",","'MulticlassRecall","'",":","tensor","(","0.1111",")","}","Example",":",":","If","multiple","of","the","same","metric","class","(","with","different","parameters",")","should","be","chained","together",",","metrics","can","be","passed","in","as","a","dict","and","the","output","dict","will","have","the","same","keys","as","the","input","dict",":",">",">",">","metrics","=","MetricCollection","(","{","'micro_recall","'",":","MulticlassRecall","(","num_classes=3",",","average='micro","'",")",",","...","'macro_recall","'",":","MulticlassRecall","(","num_classes=3",",","average='macro","'",")","}",")",">",">",">","same_metric","=","metrics.clone","(",")",">",">",">","pprint","(","metrics","(","preds",",","target",")",")","{","'macro_recall","'",":","tensor","(","0.1111",")",",","'micro_recall","'",":","tensor","(","0.1250",")","}",">",">",">","pprint","(","same_metric","(","preds",",","target",")",")","{","'macro_recall","'",":","tensor","(","0.1111",")",",","'micro_recall","'",":","tensor","(","0.1250",")","}","Example",":",":","Metric","collections","can","also","be","nested","up","to","a","single","time",".","The","output","of","the","collection","will","still","be","a","single","dict","with","the","prefix","and","postfix","arguments","from","the","nested","collection",":",">",">",">","metrics","=","MetricCollection","(","[","...","MetricCollection","(","[","...","MulticlassAccuracy","(","num_classes=3",",","average='macro","'",")",",","...","MulticlassPrecision","(","num_classes=3",",","average='macro","'",")","...","]",",","postfix='_macro","'",")",",","...","MetricCollection","(","[","...","MulticlassAccuracy","(","num_classes=3",",","average='micro","'",")",",","...","MulticlassPrecision","(","num_classes=3",",","average='micro","'",")","...","]",",","postfix='_micro","'",")",",","...","]",",","prefix='valmetrics\/","'",")",">",">",">","pprint","(","metrics","(","preds",",","target",")",")","#","doctest",":","+NORMALIZE_WHITESPACE","{","'valmetrics\/MulticlassAccuracy_macro","'",":","tensor","(","0.1111",")",",","'valmetrics\/MulticlassAccuracy_micro","'",":","tensor","(","0.1250",")",",","'valmetrics\/MulticlassPrecision_macro","'",":","tensor","(","0.0667",")",",","'valmetrics\/MulticlassPrecision_micro","'",":","tensor","(","0.1250",")","}","Example",":",":","The","`","compute_groups","`","argument","allow","you","to","specify","which","metrics","should","share","metric","state",".","By","default",",","this","will","automatically","be","derived","but","can","also","be","set","manually",".",">",">",">","metrics","=","MetricCollection","(","...","MulticlassRecall","(","num_classes=3",",","average='macro","'",")",",","...","MulticlassPrecision","(","num_classes=3",",","average='macro","'",")",",","...","MeanSquaredError","(",")",",","...","compute_groups=","[","[","'MulticlassRecall","'",",","'MulticlassPrecision","'","]",",","[","'MeanSquaredError","'","]","]","...",")",">",">",">","metrics.update","(","preds",",","target",")",">",">",">","pprint","(","metrics.compute","(",")",")","{","'MeanSquaredError","'",":","tensor","(","2.3750",")",",","'MulticlassPrecision","'",":","tensor","(","0.0667",")",",","'MulticlassRecall","'",":","tensor","(","0.1111",")","}",">",">",">","pprint","(","metrics.compute_groups",")","{","0",":","[","'MulticlassRecall","'",",","'MulticlassPrecision","'","]",",","1",":","[","'MeanSquaredError","'","]","}"]
docstr: Iterate over the collection of metrics, checking if the state of each metric matches another.
  
  If so, their compute groups will be merged into one. The complexity of the method is approximately
  ``O(number_of_metrics_in_collection ** 2)``, as all metrics need to be compared to all other metrics.
docstr_tok: ["Iterate","over","the","collection","of","metrics",",","checking","if","the","state","of","each","metric","matches","another",".","If","so",",","their","compute","groups","will","be","merged","into","one",".","The","complexity","of","the","method","is","approximately","``","O","(","number_of_metrics_in_collection","*","*","2",")","``",",","as","all","metrics","need","to","be","compared","to","all","other","metrics","."]
code: def _merge_compute_groups(self) -> None:
      """Iterate over the collection of metrics, checking if the state of each metric matches another.
  
      If so, their compute groups will be merged into one. The complexity of the method is approximately
      ``O(number_of_metrics_in_collection ** 2)``, as all metrics need to be compared to all other metrics.
  
      """
      num_groups = len(self._groups)
      while True:
          for cg_idx1, cg_members1 in deepcopy(self._groups).items():
              for cg_idx2, cg_members2 in deepcopy(
                  self._groups
              ).items():
                  if cg_idx1 == cg_idx2:
                      continue
  
                  metric1 = getattr(self, cg_members1[0])
                  metric2 = getattr(self, cg_members2[0])
  
                  if self._equal_metric_states(metric1, metric2):
                      self._groups[cg_idx1].extend(
                          self._groups.pop(cg_idx2)
                      )
                      break
  
              # Start over if we merged groups
              if len(self._groups) != num_groups:
                  break
  
          # Stop when we iterate over everything and do not merge any groups
          if len(self._groups) == num_groups:
              break
          num_groups = len(self._groups)
  
      # Re-index groups
      temp = deepcopy(self._groups)
      self._groups = {}
      for idx, values in enumerate(temp.values()):
          self._groups[idx] = values
  
imports: from collections import OrderedDict
  from copy import deepcopy
  from typing import Any, Dict, Hashable, Iterable, Iterator, List, Optional, Sequence, Tuple, Union
  import torch
  from torch import Tensor
  from torch.nn import ModuleDict
  from typing_extensions import Literal
  from torchmetrics.metric import Metric
  from torchmetrics.utilities import rank_zero_warn
  from torchmetrics.utilities.data import _flatten_dict, allclose
  from torchmetrics.utilities.imports import _MATPLOTLIB_AVAILABLE
  from torchmetrics.utilities.plot import _AX_TYPE, _PLOT_OUT_TYPE, plot_single_or_multi_val
label_desc: Use image node_id 4 for calling the MetricCollection obj's underlying member method code with example usage: obj._merge_compute_groups() without return types