We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug in ConfusionMatrix
When passing in the groundtruth `y` with the format of `shape (batch_size, num_categories, ...) and contains ground-truth class indices`, flattened one-hot encoding tensor `y_ohe_t` will result in wrong order with respect to that of prediction. https://github.com/pytorch/ignite/blob/fc85e25dc4f938d780b4c425acb2d40f6cac6f24/ignite/metrics/confusion_matrix.py#L79-L80

https://github.com/pytorch/ignite/blob/fc85e25dc4f938d780b4c425acb2d40f6cac6f24/ignite/metrics/confusion_matrix.py#L82-L83
For example:
```python
y_pred                                       # shape (B, C, H, W)
indices = torch.argmax(y_pred, dim=1)        # shape (B, H, W)
y_pred_ohe = to_onehot(indices.reshape(-1),  # shape (B*H*W)
                       self.num_classes)     # shape (B*H*W, C)

y                                      # shape (B, C, H, W), C: num of classes
y_ohe_t = (y.transpose(1, -1)          # shape (B, W, H, C)
            .reshape(y.shape[1], -1))  # reshape (B, W, H, C) into (C, B*W*H) and the value order is totally wrong
```
Expected behavior:
```python
y_ohe_t = y.transpose(0, 1).reshape(y.shape[1], -1)
# (B, C, H, W) --> (C, B, H, W) --> (C, B*H*W)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/metrics/confusion_matrix.py`
Content:
```
1 import numbers
2 
3 import torch
4 
5 from ignite.metrics import Metric, MetricsLambda
6 from ignite.exceptions import NotComputableError
7 from ignite.utils import to_onehot
8 
9 
10 class ConfusionMatrix(Metric):
11     """Calculates confusion matrix for multi-class data.
12 
13     - `update` must receive output of the form `(y_pred, y)`.
14     - `y_pred` must contain logits and has the following shape (batch_size, num_categories, ...)
15     - `y` can be of two types:
16         - shape (batch_size, num_categories, ...)
17         - shape (batch_size, ...) and contains ground-truth class indices
18 
19     Args:
20         num_classes (int): number of classes. In case of images, num_classes should also count the background index 0.
21         average (str, optional): confusion matrix values averaging schema: None, "samples", "recall", "precision".
22             Default is None. If `average="samples"` then confusion matrix values are normalized by the number of seen
23             samples. If `average="recall"` then confusion matrix values are normalized such that diagonal values
24             represent class recalls. If `average="precision"` then confusion matrix values are normalized such that
25             diagonal values represent class precisions.
26         output_transform (callable, optional): a callable that is used to transform the
27             :class:`~ignite.engine.Engine`'s `process_function`'s output into the
28             form expected by the metric. This can be useful if, for example, you have a multi-output model and
29             you want to compute the metric with respect to one of the outputs.
30     """
31 
32     def __init__(self, num_classes, average=None, output_transform=lambda x: x):
33         if average is not None and average not in ("samples", "recall", "precision"):
34             raise ValueError("Argument average can None or one of ['samples', 'recall', 'precision']")
35 
36         self.num_classes = num_classes
37         self._num_examples = 0
38         self.average = average
39         self.confusion_matrix = None
40         super(ConfusionMatrix, self).__init__(output_transform=output_transform)
41 
42     def reset(self):
43         self.confusion_matrix = torch.zeros(self.num_classes, self.num_classes, dtype=torch.float)
44         self._num_examples = 0
45 
46     def _check_shape(self, output):
47         y_pred, y = output
48 
49         if y_pred.ndimension() < 2:
50             raise ValueError("y_pred must have shape (batch_size, num_categories, ...), "
51                              "but given {}".format(y_pred.shape))
52 
53         if y_pred.shape[1] != self.num_classes:
54             raise ValueError("y_pred does not have correct number of categories: {} vs {}"
55                              .format(y_pred.shape[1], self.num_classes))
56 
57         if not (y.ndimension() == y_pred.ndimension() or y.ndimension() + 1 == y_pred.ndimension()):
58             raise ValueError("y_pred must have shape (batch_size, num_categories, ...) and y must have "
59                              "shape of (batch_size, num_categories, ...) or (batch_size, ...), "
60                              "but given {} vs {}.".format(y.shape, y_pred.shape))
61 
62         y_shape = y.shape
63         y_pred_shape = y_pred.shape
64 
65         if y.ndimension() + 1 == y_pred.ndimension():
66             y_pred_shape = (y_pred_shape[0],) + y_pred_shape[2:]
67 
68         if y_shape != y_pred_shape:
69             raise ValueError("y and y_pred must have compatible shapes.")
70 
71         return y_pred, y
72 
73     def update(self, output):
74         y_pred, y = self._check_shape(output)
75 
76         if y_pred.shape != y.shape:
77             y_ohe = to_onehot(y.reshape(-1), self.num_classes)
78             y_ohe_t = y_ohe.transpose(0, 1).float()
79         else:
80             y_ohe_t = y.transpose(1, -1).reshape(y.shape[1], -1).float()
81 
82         indices = torch.argmax(y_pred, dim=1)
83         y_pred_ohe = to_onehot(indices.reshape(-1), self.num_classes)
84         y_pred_ohe = y_pred_ohe.float()
85 
86         if self.confusion_matrix.type() != y_ohe_t.type():
87             self.confusion_matrix = self.confusion_matrix.type_as(y_ohe_t)
88 
89         self.confusion_matrix += torch.matmul(y_ohe_t, y_pred_ohe).float()
90         self._num_examples += y_pred.shape[0]
91 
92     def compute(self):
93         if self._num_examples == 0:
94             raise NotComputableError('Confusion matrix must have at least one example before it can be computed.')
95         if self.average:
96             if self.average == "samples":
97                 return self.confusion_matrix / self._num_examples
98             elif self.average == "recall":
99                 return self.confusion_matrix / (self.confusion_matrix.sum(dim=1) + 1e-15)
100             elif self.average == "precision":
101                 return self.confusion_matrix / (self.confusion_matrix.sum(dim=0) + 1e-15)
102         return self.confusion_matrix.cpu()
103 
104 
105 def IoU(cm, ignore_index=None):
106     """Calculates Intersection over Union
107 
108     Args:
109         cm (ConfusionMatrix): instance of confusion matrix metric
110         ignore_index (int, optional): index to ignore, e.g. background index
111 
112     Returns:
113         MetricsLambda
114 
115     Examples:
116 
117     .. code-block:: python
118 
119         train_evaluator = ...
120 
121         cm = ConfusionMatrix(num_classes=num_classes)
122         IoU(cm, ignore_index=0).attach(train_evaluator, 'IoU')
123 
124         state = train_evaluator.run(train_dataset)
125         # state.metrics['IoU'] -> tensor of shape (num_classes - 1, )
126 
127     """
128     if not isinstance(cm, ConfusionMatrix):
129         raise TypeError("Argument cm should be instance of ConfusionMatrix, but given {}".format(type(cm)))
130 
131     if ignore_index is not None:
132         if not (isinstance(ignore_index, numbers.Integral) and 0 <= ignore_index < cm.num_classes):
133             raise ValueError("ignore_index should be non-negative integer, but given {}".format(ignore_index))
134 
135     # Increase floating point precision
136     cm = cm.type(torch.float64)
137     iou = cm.diag() / (cm.sum(dim=1) + cm.sum(dim=0) - cm.diag() + 1e-15)
138     if ignore_index is not None:
139 
140         def ignore_index_fn(iou_vector):
141             if ignore_index >= len(iou_vector):
142                 raise ValueError("ignore_index {} is larger than the length of IoU vector {}"
143                                  .format(ignore_index, len(iou_vector)))
144             indices = list(range(len(iou_vector)))
145             indices.remove(ignore_index)
146             return iou_vector[indices]
147 
148         return MetricsLambda(ignore_index_fn, iou)
149     else:
150         return iou
151 
152 
153 def mIoU(cm, ignore_index=None):
154     """Calculates mean Intersection over Union
155 
156     Args:
157         cm (ConfusionMatrix): instance of confusion matrix metric
158         ignore_index (int, optional): index to ignore, e.g. background index
159 
160     Returns:
161         MetricsLambda
162 
163     Examples:
164 
165     .. code-block:: python
166 
167         train_evaluator = ...
168 
169         cm = ConfusionMatrix(num_classes=num_classes)
170         mIoU(cm, ignore_index=0).attach(train_evaluator, 'mean IoU')
171 
172         state = train_evaluator.run(train_dataset)
173         # state.metrics['mean IoU'] -> scalar
174 
175 
176     """
177     return IoU(cm=cm, ignore_index=ignore_index).mean()
178 
179 
180 def cmAccuracy(cm):
181     """
182     Calculates accuracy using :class:`~ignite.metrics.ConfusionMatrix` metric.
183     Args:
184         cm (ConfusionMatrix): instance of confusion matrix metric
185 
186     Returns:
187         MetricsLambda
188     """
189     # Increase floating point precision
190     cm = cm.type(torch.float64)
191     return cm.diag().sum() / (cm.sum() + 1e-15)
192 
193 
194 def cmPrecision(cm, average=True):
195     """
196     Calculates precision using :class:`~ignite.metrics.ConfusionMatrix` metric.
197     Args:
198         cm (ConfusionMatrix): instance of confusion matrix metric
199         average (bool, optional): if True metric value is averaged over all classes
200     Returns:
201         MetricsLambda
202     """
203 
204     # Increase floating point precision
205     cm = cm.type(torch.float64)
206     precision = cm.diag() / (cm.sum(dim=0) + 1e-15)
207     if average:
208         return precision.mean()
209     return precision
210 
211 
212 def cmRecall(cm, average=True):
213     """
214     Calculates recall using :class:`~ignite.metrics.ConfusionMatrix` metric.
215     Args:
216         cm (ConfusionMatrix): instance of confusion matrix metric
217         average (bool, optional): if True metric value is averaged over all classes
218     Returns:
219         MetricsLambda
220     """
221 
222     # Increase floating point precision
223     cm = cm.type(torch.float64)
224     recall = cm.diag() / (cm.sum(dim=1) + 1e-15)
225     if average:
226         return recall.mean()
227     return recall
228
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ignite/metrics/confusion_matrix.py b/ignite/metrics/confusion_matrix.py
--- a/ignite/metrics/confusion_matrix.py
+++ b/ignite/metrics/confusion_matrix.py
@@ -77,7 +77,7 @@
             y_ohe = to_onehot(y.reshape(-1), self.num_classes)
             y_ohe_t = y_ohe.transpose(0, 1).float()
         else:
-            y_ohe_t = y.transpose(1, -1).reshape(y.shape[1], -1).float()
+            y_ohe_t = y.transpose(0, 1).reshape(y.shape[1], -1).float()
 
         indices = torch.argmax(y_pred, dim=1)
         y_pred_ohe = to_onehot(indices.reshape(-1), self.num_classes)

{"golden_diff": "diff --git a/ignite/metrics/confusion_matrix.py b/ignite/metrics/confusion_matrix.py\n--- a/ignite/metrics/confusion_matrix.py\n+++ b/ignite/metrics/confusion_matrix.py\n@@ -77,7 +77,7 @@\n             y_ohe = to_onehot(y.reshape(-1), self.num_classes)\n             y_ohe_t = y_ohe.transpose(0, 1).float()\n         else:\n-            y_ohe_t = y.transpose(1, -1).reshape(y.shape[1], -1).float()\n+            y_ohe_t = y.transpose(0, 1).reshape(y.shape[1], -1).float()\n \n         indices = torch.argmax(y_pred, dim=1)\n         y_pred_ohe = to_onehot(indices.reshape(-1), self.num_classes)\n", "issue": "Bug in ConfusionMatrix\nWhen passing in the groundtruth `y` with the format of `shape (batch_size, num_categories, ...) and contains ground-truth class indices`, flattened one-hot encoding tensor `y_ohe_t` will result in wrong order with respect to that of prediction. https://github.com/pytorch/ignite/blob/fc85e25dc4f938d780b4c425acb2d40f6cac6f24/ignite/metrics/confusion_matrix.py#L79-L80\r\n\r\nhttps://github.com/pytorch/ignite/blob/fc85e25dc4f938d780b4c425acb2d40f6cac6f24/ignite/metrics/confusion_matrix.py#L82-L83\r\nFor example:\r\n```python\r\ny_pred                                       # shape (B, C, H, W)\r\nindices = torch.argmax(y_pred, dim=1)        # shape (B, H, W)\r\ny_pred_ohe = to_onehot(indices.reshape(-1),  # shape (B*H*W)\r\n                       self.num_classes)     # shape (B*H*W, C)\r\n\r\ny                                      # shape (B, C, H, W), C: num of classes\r\ny_ohe_t = (y.transpose(1, -1)          # shape (B, W, H, C)\r\n            .reshape(y.shape[1], -1))  # reshape (B, W, H, C) into (C, B*W*H) and the value order is totally wrong\r\n```\r\nExpected behavior:\r\n```python\r\ny_ohe_t = y.transpose(0, 1).reshape(y.shape[1], -1)\r\n# (B, C, H, W) --> (C, B, H, W) --> (C, B*H*W)\r\n```\n", "before_files": [{"content": "import numbers\n\nimport torch\n\nfrom ignite.metrics import Metric, MetricsLambda\nfrom ignite.exceptions import NotComputableError\nfrom ignite.utils import to_onehot\n\n\nclass ConfusionMatrix(Metric):\n    \"\"\"Calculates confusion matrix for multi-class data.\n\n    - `update` must receive output of the form `(y_pred, y)`.\n    - `y_pred` must contain logits and has the following shape (batch_size, num_categories, ...)\n    - `y` can be of two types:\n        - shape (batch_size, num_categories, ...)\n        - shape (batch_size, ...) and contains ground-truth class indices\n\n    Args:\n        num_classes (int): number of classes. In case of images, num_classes should also count the background index 0.\n        average (str, optional): confusion matrix values averaging schema: None, \"samples\", \"recall\", \"precision\".\n            Default is None. If `average=\"samples\"` then confusion matrix values are normalized by the number of seen\n            samples. If `average=\"recall\"` then confusion matrix values are normalized such that diagonal values\n            represent class recalls. If `average=\"precision\"` then confusion matrix values are normalized such that\n            diagonal values represent class precisions.\n        output_transform (callable, optional): a callable that is used to transform the\n            :class:`~ignite.engine.Engine`'s `process_function`'s output into the\n            form expected by the metric. This can be useful if, for example, you have a multi-output model and\n            you want to compute the metric with respect to one of the outputs.\n    \"\"\"\n\n    def __init__(self, num_classes, average=None, output_transform=lambda x: x):\n        if average is not None and average not in (\"samples\", \"recall\", \"precision\"):\n            raise ValueError(\"Argument average can None or one of ['samples', 'recall', 'precision']\")\n\n        self.num_classes = num_classes\n        self._num_examples = 0\n        self.average = average\n        self.confusion_matrix = None\n        super(ConfusionMatrix, self).__init__(output_transform=output_transform)\n\n    def reset(self):\n        self.confusion_matrix = torch.zeros(self.num_classes, self.num_classes, dtype=torch.float)\n        self._num_examples = 0\n\n    def _check_shape(self, output):\n        y_pred, y = output\n\n        if y_pred.ndimension() < 2:\n            raise ValueError(\"y_pred must have shape (batch_size, num_categories, ...), \"\n                             \"but given {}\".format(y_pred.shape))\n\n        if y_pred.shape[1] != self.num_classes:\n            raise ValueError(\"y_pred does not have correct number of categories: {} vs {}\"\n                             .format(y_pred.shape[1], self.num_classes))\n\n        if not (y.ndimension() == y_pred.ndimension() or y.ndimension() + 1 == y_pred.ndimension()):\n            raise ValueError(\"y_pred must have shape (batch_size, num_categories, ...) and y must have \"\n                             \"shape of (batch_size, num_categories, ...) or (batch_size, ...), \"\n                             \"but given {} vs {}.\".format(y.shape, y_pred.shape))\n\n        y_shape = y.shape\n        y_pred_shape = y_pred.shape\n\n        if y.ndimension() + 1 == y_pred.ndimension():\n            y_pred_shape = (y_pred_shape[0],) + y_pred_shape[2:]\n\n        if y_shape != y_pred_shape:\n            raise ValueError(\"y and y_pred must have compatible shapes.\")\n\n        return y_pred, y\n\n    def update(self, output):\n        y_pred, y = self._check_shape(output)\n\n        if y_pred.shape != y.shape:\n            y_ohe = to_onehot(y.reshape(-1), self.num_classes)\n            y_ohe_t = y_ohe.transpose(0, 1).float()\n        else:\n            y_ohe_t = y.transpose(1, -1).reshape(y.shape[1], -1).float()\n\n        indices = torch.argmax(y_pred, dim=1)\n        y_pred_ohe = to_onehot(indices.reshape(-1), self.num_classes)\n        y_pred_ohe = y_pred_ohe.float()\n\n        if self.confusion_matrix.type() != y_ohe_t.type():\n            self.confusion_matrix = self.confusion_matrix.type_as(y_ohe_t)\n\n        self.confusion_matrix += torch.matmul(y_ohe_t, y_pred_ohe).float()\n        self._num_examples += y_pred.shape[0]\n\n    def compute(self):\n        if self._num_examples == 0:\n            raise NotComputableError('Confusion matrix must have at least one example before it can be computed.')\n        if self.average:\n            if self.average == \"samples\":\n                return self.confusion_matrix / self._num_examples\n            elif self.average == \"recall\":\n                return self.confusion_matrix / (self.confusion_matrix.sum(dim=1) + 1e-15)\n            elif self.average == \"precision\":\n                return self.confusion_matrix / (self.confusion_matrix.sum(dim=0) + 1e-15)\n        return self.confusion_matrix.cpu()\n\n\ndef IoU(cm, ignore_index=None):\n    \"\"\"Calculates Intersection over Union\n\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        ignore_index (int, optional): index to ignore, e.g. background index\n\n    Returns:\n        MetricsLambda\n\n    Examples:\n\n    .. code-block:: python\n\n        train_evaluator = ...\n\n        cm = ConfusionMatrix(num_classes=num_classes)\n        IoU(cm, ignore_index=0).attach(train_evaluator, 'IoU')\n\n        state = train_evaluator.run(train_dataset)\n        # state.metrics['IoU'] -> tensor of shape (num_classes - 1, )\n\n    \"\"\"\n    if not isinstance(cm, ConfusionMatrix):\n        raise TypeError(\"Argument cm should be instance of ConfusionMatrix, but given {}\".format(type(cm)))\n\n    if ignore_index is not None:\n        if not (isinstance(ignore_index, numbers.Integral) and 0 <= ignore_index < cm.num_classes):\n            raise ValueError(\"ignore_index should be non-negative integer, but given {}\".format(ignore_index))\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    iou = cm.diag() / (cm.sum(dim=1) + cm.sum(dim=0) - cm.diag() + 1e-15)\n    if ignore_index is not None:\n\n        def ignore_index_fn(iou_vector):\n            if ignore_index >= len(iou_vector):\n                raise ValueError(\"ignore_index {} is larger than the length of IoU vector {}\"\n                                 .format(ignore_index, len(iou_vector)))\n            indices = list(range(len(iou_vector)))\n            indices.remove(ignore_index)\n            return iou_vector[indices]\n\n        return MetricsLambda(ignore_index_fn, iou)\n    else:\n        return iou\n\n\ndef mIoU(cm, ignore_index=None):\n    \"\"\"Calculates mean Intersection over Union\n\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        ignore_index (int, optional): index to ignore, e.g. background index\n\n    Returns:\n        MetricsLambda\n\n    Examples:\n\n    .. code-block:: python\n\n        train_evaluator = ...\n\n        cm = ConfusionMatrix(num_classes=num_classes)\n        mIoU(cm, ignore_index=0).attach(train_evaluator, 'mean IoU')\n\n        state = train_evaluator.run(train_dataset)\n        # state.metrics['mean IoU'] -> scalar\n\n\n    \"\"\"\n    return IoU(cm=cm, ignore_index=ignore_index).mean()\n\n\ndef cmAccuracy(cm):\n    \"\"\"\n    Calculates accuracy using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n\n    Returns:\n        MetricsLambda\n    \"\"\"\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    return cm.diag().sum() / (cm.sum() + 1e-15)\n\n\ndef cmPrecision(cm, average=True):\n    \"\"\"\n    Calculates precision using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        average (bool, optional): if True metric value is averaged over all classes\n    Returns:\n        MetricsLambda\n    \"\"\"\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    precision = cm.diag() / (cm.sum(dim=0) + 1e-15)\n    if average:\n        return precision.mean()\n    return precision\n\n\ndef cmRecall(cm, average=True):\n    \"\"\"\n    Calculates recall using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        average (bool, optional): if True metric value is averaged over all classes\n    Returns:\n        MetricsLambda\n    \"\"\"\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    recall = cm.diag() / (cm.sum(dim=1) + 1e-15)\n    if average:\n        return recall.mean()\n    return recall\n", "path": "ignite/metrics/confusion_matrix.py"}], "after_files": [{"content": "import numbers\n\nimport torch\n\nfrom ignite.metrics import Metric, MetricsLambda\nfrom ignite.exceptions import NotComputableError\nfrom ignite.utils import to_onehot\n\n\nclass ConfusionMatrix(Metric):\n    \"\"\"Calculates confusion matrix for multi-class data.\n\n    - `update` must receive output of the form `(y_pred, y)`.\n    - `y_pred` must contain logits and has the following shape (batch_size, num_categories, ...)\n    - `y` can be of two types:\n        - shape (batch_size, num_categories, ...)\n        - shape (batch_size, ...) and contains ground-truth class indices\n\n    Args:\n        num_classes (int): number of classes. In case of images, num_classes should also count the background index 0.\n        average (str, optional): confusion matrix values averaging schema: None, \"samples\", \"recall\", \"precision\".\n            Default is None. If `average=\"samples\"` then confusion matrix values are normalized by the number of seen\n            samples. If `average=\"recall\"` then confusion matrix values are normalized such that diagonal values\n            represent class recalls. If `average=\"precision\"` then confusion matrix values are normalized such that\n            diagonal values represent class precisions.\n        output_transform (callable, optional): a callable that is used to transform the\n            :class:`~ignite.engine.Engine`'s `process_function`'s output into the\n            form expected by the metric. This can be useful if, for example, you have a multi-output model and\n            you want to compute the metric with respect to one of the outputs.\n    \"\"\"\n\n    def __init__(self, num_classes, average=None, output_transform=lambda x: x):\n        if average is not None and average not in (\"samples\", \"recall\", \"precision\"):\n            raise ValueError(\"Argument average can None or one of ['samples', 'recall', 'precision']\")\n\n        self.num_classes = num_classes\n        self._num_examples = 0\n        self.average = average\n        self.confusion_matrix = None\n        super(ConfusionMatrix, self).__init__(output_transform=output_transform)\n\n    def reset(self):\n        self.confusion_matrix = torch.zeros(self.num_classes, self.num_classes, dtype=torch.float)\n        self._num_examples = 0\n\n    def _check_shape(self, output):\n        y_pred, y = output\n\n        if y_pred.ndimension() < 2:\n            raise ValueError(\"y_pred must have shape (batch_size, num_categories, ...), \"\n                             \"but given {}\".format(y_pred.shape))\n\n        if y_pred.shape[1] != self.num_classes:\n            raise ValueError(\"y_pred does not have correct number of categories: {} vs {}\"\n                             .format(y_pred.shape[1], self.num_classes))\n\n        if not (y.ndimension() == y_pred.ndimension() or y.ndimension() + 1 == y_pred.ndimension()):\n            raise ValueError(\"y_pred must have shape (batch_size, num_categories, ...) and y must have \"\n                             \"shape of (batch_size, num_categories, ...) or (batch_size, ...), \"\n                             \"but given {} vs {}.\".format(y.shape, y_pred.shape))\n\n        y_shape = y.shape\n        y_pred_shape = y_pred.shape\n\n        if y.ndimension() + 1 == y_pred.ndimension():\n            y_pred_shape = (y_pred_shape[0],) + y_pred_shape[2:]\n\n        if y_shape != y_pred_shape:\n            raise ValueError(\"y and y_pred must have compatible shapes.\")\n\n        return y_pred, y\n\n    def update(self, output):\n        y_pred, y = self._check_shape(output)\n\n        if y_pred.shape != y.shape:\n            y_ohe = to_onehot(y.reshape(-1), self.num_classes)\n            y_ohe_t = y_ohe.transpose(0, 1).float()\n        else:\n            y_ohe_t = y.transpose(0, 1).reshape(y.shape[1], -1).float()\n\n        indices = torch.argmax(y_pred, dim=1)\n        y_pred_ohe = to_onehot(indices.reshape(-1), self.num_classes)\n        y_pred_ohe = y_pred_ohe.float()\n\n        if self.confusion_matrix.type() != y_ohe_t.type():\n            self.confusion_matrix = self.confusion_matrix.type_as(y_ohe_t)\n\n        self.confusion_matrix += torch.matmul(y_ohe_t, y_pred_ohe).float()\n        self._num_examples += y_pred.shape[0]\n\n    def compute(self):\n        if self._num_examples == 0:\n            raise NotComputableError('Confusion matrix must have at least one example before it can be computed.')\n        if self.average:\n            if self.average == \"samples\":\n                return self.confusion_matrix / self._num_examples\n            elif self.average == \"recall\":\n                return self.confusion_matrix / (self.confusion_matrix.sum(dim=1) + 1e-15)\n            elif self.average == \"precision\":\n                return self.confusion_matrix / (self.confusion_matrix.sum(dim=0) + 1e-15)\n        return self.confusion_matrix.cpu()\n\n\ndef IoU(cm, ignore_index=None):\n    \"\"\"Calculates Intersection over Union\n\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        ignore_index (int, optional): index to ignore, e.g. background index\n\n    Returns:\n        MetricsLambda\n\n    Examples:\n\n    .. code-block:: python\n\n        train_evaluator = ...\n\n        cm = ConfusionMatrix(num_classes=num_classes)\n        IoU(cm, ignore_index=0).attach(train_evaluator, 'IoU')\n\n        state = train_evaluator.run(train_dataset)\n        # state.metrics['IoU'] -> tensor of shape (num_classes - 1, )\n\n    \"\"\"\n    if not isinstance(cm, ConfusionMatrix):\n        raise TypeError(\"Argument cm should be instance of ConfusionMatrix, but given {}\".format(type(cm)))\n\n    if ignore_index is not None:\n        if not (isinstance(ignore_index, numbers.Integral) and 0 <= ignore_index < cm.num_classes):\n            raise ValueError(\"ignore_index should be non-negative integer, but given {}\".format(ignore_index))\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    iou = cm.diag() / (cm.sum(dim=1) + cm.sum(dim=0) - cm.diag() + 1e-15)\n    if ignore_index is not None:\n\n        def ignore_index_fn(iou_vector):\n            if ignore_index >= len(iou_vector):\n                raise ValueError(\"ignore_index {} is larger than the length of IoU vector {}\"\n                                 .format(ignore_index, len(iou_vector)))\n            indices = list(range(len(iou_vector)))\n            indices.remove(ignore_index)\n            return iou_vector[indices]\n\n        return MetricsLambda(ignore_index_fn, iou)\n    else:\n        return iou\n\n\ndef mIoU(cm, ignore_index=None):\n    \"\"\"Calculates mean Intersection over Union\n\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        ignore_index (int, optional): index to ignore, e.g. background index\n\n    Returns:\n        MetricsLambda\n\n    Examples:\n\n    .. code-block:: python\n\n        train_evaluator = ...\n\n        cm = ConfusionMatrix(num_classes=num_classes)\n        mIoU(cm, ignore_index=0).attach(train_evaluator, 'mean IoU')\n\n        state = train_evaluator.run(train_dataset)\n        # state.metrics['mean IoU'] -> scalar\n\n\n    \"\"\"\n    return IoU(cm=cm, ignore_index=ignore_index).mean()\n\n\ndef cmAccuracy(cm):\n    \"\"\"\n    Calculates accuracy using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n\n    Returns:\n        MetricsLambda\n    \"\"\"\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    return cm.diag().sum() / (cm.sum() + 1e-15)\n\n\ndef cmPrecision(cm, average=True):\n    \"\"\"\n    Calculates precision using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        average (bool, optional): if True metric value is averaged over all classes\n    Returns:\n        MetricsLambda\n    \"\"\"\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    precision = cm.diag() / (cm.sum(dim=0) + 1e-15)\n    if average:\n        return precision.mean()\n    return precision\n\n\ndef cmRecall(cm, average=True):\n    \"\"\"\n    Calculates recall using :class:`~ignite.metrics.ConfusionMatrix` metric.\n    Args:\n        cm (ConfusionMatrix): instance of confusion matrix metric\n        average (bool, optional): if True metric value is averaged over all classes\n    Returns:\n        MetricsLambda\n    \"\"\"\n\n    # Increase floating point precision\n    cm = cm.type(torch.float64)\n    recall = cm.diag() / (cm.sum(dim=1) + 1e-15)\n    if average:\n        return recall.mean()\n    return recall\n", "path": "ignite/metrics/confusion_matrix.py"}]}