prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Improve `ignite.contirb.metrics` implementation 
  For these metrics in `ignite.contrib.metrics` :
  - [Average Precision](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/average_precision.py)
  - [Precision Recall Curve](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/precision_recall_curve.py)
  - [Roc Auc](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/roc_auc.py) 
  We need to make the implementation simpler. Similar to the one here #1690. New arg `device` will be added, and we need to add the necessary distributed tests as well. See here for the tests https://github.com/pytorch/ignite/blob/master/tests/ignite/contrib/metrics/regression/test_canberra_metric.py#L99
  
  
  --- 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/contrib/metrics/average_precision.py`
  Content:
  ```
  1 from typing import Callable
  2 
  3 import torch
  4 
  5 from ignite.metrics import EpochMetric
  6 
  7 
  8 def average_precision_compute_fn(y_preds: torch.Tensor, y_targets: torch.Tensor) -> float:
  9     try:
  10         from sklearn.metrics import average_precision_score
  11     except ImportError:
  12         raise RuntimeError("This contrib module requires sklearn to be installed.")
  13 
  14     y_true = y_targets.numpy()
  15     y_pred = y_preds.numpy()
  16     return average_precision_score(y_true, y_pred)
  17 
  18 
  19 class AveragePrecision(EpochMetric):
  20     """Computes Average Precision accumulating predictions and the ground-truth during an epoch
  21     and applying `sklearn.metrics.average_precision_score <https://scikit-learn.org/stable/modules/generated/
  22     sklearn.metrics.average_precision_score.html#sklearn.metrics.average_precision_score>`_ .
  23 
  24     Args:
  25         output_transform: a callable that is used to transform the
  26             :class:`~ignite.engine.engine.Engine`'s ``process_function``'s output into the
  27             form expected by the metric. This can be useful if, for example, you have a multi-output model and
  28             you want to compute the metric with respect to one of the outputs.
  29         check_compute_fn: Default False. If True, `average_precision_score
  30             <https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html
  31             #sklearn.metrics.average_precision_score>`_ is run on the first batch of data to ensure there are
  32             no issues. User will be warned in case there are any issues computing the function.
  33 
  34     AveragePrecision expects y to be comprised of 0's and 1's. y_pred must either be probability estimates or
  35     confidence values. To apply an activation to y_pred, use output_transform as shown below:
  36 
  37     .. code-block:: python
  38 
  39         def activated_output_transform(output):
  40             y_pred, y = output
  41             y_pred = torch.softmax(y_pred, dim=1)
  42             return y_pred, y
  43 
  44         avg_precision = AveragePrecision(activated_output_transform)
  45 
  46     """
  47 
  48     def __init__(self, output_transform: Callable = lambda x: x, check_compute_fn: bool = False) -> None:
  49         super(AveragePrecision, self).__init__(
  50             average_precision_compute_fn, output_transform=output_transform, check_compute_fn=check_compute_fn
  51         )
  52
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/ignite/contrib/metrics/average_precision.py b/ignite/contrib/metrics/average_precision.py
  --- a/ignite/contrib/metrics/average_precision.py
  +++ b/ignite/contrib/metrics/average_precision.py
  @@ -1,4 +1,4 @@
  -from typing import Callable
  +from typing import Callable, Optional, Union
   
   import torch
   
  @@ -6,13 +6,10 @@
   
   
   def average_precision_compute_fn(y_preds: torch.Tensor, y_targets: torch.Tensor) -> float:
  -    try:
  -        from sklearn.metrics import average_precision_score
  -    except ImportError:
  -        raise RuntimeError("This contrib module requires sklearn to be installed.")
  +    from sklearn.metrics import average_precision_score
   
  -    y_true = y_targets.numpy()
  -    y_pred = y_preds.numpy()
  +    y_true = y_targets.cpu().numpy()
  +    y_pred = y_preds.cpu().numpy()
       return average_precision_score(y_true, y_pred)
   
   
  @@ -30,6 +27,7 @@
               <https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html
               #sklearn.metrics.average_precision_score>`_ is run on the first batch of data to ensure there are
               no issues. User will be warned in case there are any issues computing the function.
  +        device: optional device specification for internal storage.
   
       AveragePrecision expects y to be comprised of 0's and 1's. y_pred must either be probability estimates or
       confidence values. To apply an activation to y_pred, use output_transform as shown below:
  @@ -45,7 +43,21 @@
   
       """
   
  -    def __init__(self, output_transform: Callable = lambda x: x, check_compute_fn: bool = False) -> None:
  +    def __init__(
  +        self,
  +        output_transform: Callable = lambda x: x,
  +        check_compute_fn: bool = False,
  +        device: Union[str, torch.device] = torch.device("cpu"),
  +    ):
  +
  +        try:
  +            from sklearn.metrics import average_precision_score
  +        except ImportError:
  +            raise RuntimeError("This contrib module requires sklearn to be installed.")
  +
           super(AveragePrecision, self).__init__(
  -            average_precision_compute_fn, output_transform=output_transform, check_compute_fn=check_compute_fn
  +            average_precision_compute_fn,
  +            output_transform=output_transform,
  +            check_compute_fn=check_compute_fn,
  +            device=device,
           )
  
verification_info: {"golden_diff": "diff --git a/ignite/contrib/metrics/average_precision.py b/ignite/contrib/metrics/average_precision.py\n--- a/ignite/contrib/metrics/average_precision.py\n+++ b/ignite/contrib/metrics/average_precision.py\n@@ -1,4 +1,4 @@\n-from typing import Callable\n+from typing import Callable, Optional, Union\n \n import torch\n \n@@ -6,13 +6,10 @@\n \n \n def average_precision_compute_fn(y_preds: torch.Tensor, y_targets: torch.Tensor) -> float:\n-    try:\n-        from sklearn.metrics import average_precision_score\n-    except ImportError:\n-        raise RuntimeError(\"This contrib module requires sklearn to be installed.\")\n+    from sklearn.metrics import average_precision_score\n \n-    y_true = y_targets.numpy()\n-    y_pred = y_preds.numpy()\n+    y_true = y_targets.cpu().numpy()\n+    y_pred = y_preds.cpu().numpy()\n     return average_precision_score(y_true, y_pred)\n \n \n@@ -30,6 +27,7 @@\n             <https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html\n             #sklearn.metrics.average_precision_score>`_ is run on the first batch of data to ensure there are\n             no issues. User will be warned in case there are any issues computing the function.\n+        device: optional device specification for internal storage.\n \n     AveragePrecision expects y to be comprised of 0's and 1's. y_pred must either be probability estimates or\n     confidence values. To apply an activation to y_pred, use output_transform as shown below:\n@@ -45,7 +43,21 @@\n \n     \"\"\"\n \n-    def __init__(self, output_transform: Callable = lambda x: x, check_compute_fn: bool = False) -> None:\n+    def __init__(\n+        self,\n+        output_transform: Callable = lambda x: x,\n+        check_compute_fn: bool = False,\n+        device: Union[str, torch.device] = torch.device(\"cpu\"),\n+    ):\n+\n+        try:\n+            from sklearn.metrics import average_precision_score\n+        except ImportError:\n+            raise RuntimeError(\"This contrib module requires sklearn to be installed.\")\n+\n         super(AveragePrecision, self).__init__(\n-            average_precision_compute_fn, output_transform=output_transform, check_compute_fn=check_compute_fn\n+            average_precision_compute_fn,\n+            output_transform=output_transform,\n+            check_compute_fn=check_compute_fn,\n+            device=device,\n         )\n", "issue": "Improve `ignite.contirb.metrics` implementation \nFor these metrics in `ignite.contrib.metrics` :\r\n- [Average Precision](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/average_precision.py)\r\n- [Precision Recall Curve](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/precision_recall_curve.py)\r\n- [Roc Auc](https://github.com/pytorch/ignite/blob/master/ignite/contrib/metrics/roc_auc.py) \r\nWe need to make the implementation simpler. Similar to the one here #1690. New arg `device` will be added, and we need to add the necessary distributed tests as well. See here for the tests https://github.com/pytorch/ignite/blob/master/tests/ignite/contrib/metrics/regression/test_canberra_metric.py#L99\r\n\n", "before_files": [{"content": "from typing import Callable\n\nimport torch\n\nfrom ignite.metrics import EpochMetric\n\n\ndef average_precision_compute_fn(y_preds: torch.Tensor, y_targets: torch.Tensor) -> float:\n    try:\n        from sklearn.metrics import average_precision_score\n    except ImportError:\n        raise RuntimeError(\"This contrib module requires sklearn to be installed.\")\n\n    y_true = y_targets.numpy()\n    y_pred = y_preds.numpy()\n    return average_precision_score(y_true, y_pred)\n\n\nclass AveragePrecision(EpochMetric):\n    \"\"\"Computes Average Precision accumulating predictions and the ground-truth during an epoch\n    and applying `sklearn.metrics.average_precision_score <https://scikit-learn.org/stable/modules/generated/\n    sklearn.metrics.average_precision_score.html#sklearn.metrics.average_precision_score>`_ .\n\n    Args:\n        output_transform: a callable that is used to transform the\n            :class:`~ignite.engine.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        check_compute_fn: Default False. If True, `average_precision_score\n            <https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html\n            #sklearn.metrics.average_precision_score>`_ is run on the first batch of data to ensure there are\n            no issues. User will be warned in case there are any issues computing the function.\n\n    AveragePrecision expects y to be comprised of 0's and 1's. y_pred must either be probability estimates or\n    confidence values. To apply an activation to y_pred, use output_transform as shown below:\n\n    .. code-block:: python\n\n        def activated_output_transform(output):\n            y_pred, y = output\n            y_pred = torch.softmax(y_pred, dim=1)\n            return y_pred, y\n\n        avg_precision = AveragePrecision(activated_output_transform)\n\n    \"\"\"\n\n    def __init__(self, output_transform: Callable = lambda x: x, check_compute_fn: bool = False) -> None:\n        super(AveragePrecision, self).__init__(\n            average_precision_compute_fn, output_transform=output_transform, check_compute_fn=check_compute_fn\n        )\n", "path": "ignite/contrib/metrics/average_precision.py"}], "after_files": [{"content": "from typing import Callable, Optional, Union\n\nimport torch\n\nfrom ignite.metrics import EpochMetric\n\n\ndef average_precision_compute_fn(y_preds: torch.Tensor, y_targets: torch.Tensor) -> float:\n    from sklearn.metrics import average_precision_score\n\n    y_true = y_targets.cpu().numpy()\n    y_pred = y_preds.cpu().numpy()\n    return average_precision_score(y_true, y_pred)\n\n\nclass AveragePrecision(EpochMetric):\n    \"\"\"Computes Average Precision accumulating predictions and the ground-truth during an epoch\n    and applying `sklearn.metrics.average_precision_score <https://scikit-learn.org/stable/modules/generated/\n    sklearn.metrics.average_precision_score.html#sklearn.metrics.average_precision_score>`_ .\n\n    Args:\n        output_transform: a callable that is used to transform the\n            :class:`~ignite.engine.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        check_compute_fn: Default False. If True, `average_precision_score\n            <https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html\n            #sklearn.metrics.average_precision_score>`_ is run on the first batch of data to ensure there are\n            no issues. User will be warned in case there are any issues computing the function.\n        device: optional device specification for internal storage.\n\n    AveragePrecision expects y to be comprised of 0's and 1's. y_pred must either be probability estimates or\n    confidence values. To apply an activation to y_pred, use output_transform as shown below:\n\n    .. code-block:: python\n\n        def activated_output_transform(output):\n            y_pred, y = output\n            y_pred = torch.softmax(y_pred, dim=1)\n            return y_pred, y\n\n        avg_precision = AveragePrecision(activated_output_transform)\n\n    \"\"\"\n\n    def __init__(\n        self,\n        output_transform: Callable = lambda x: x,\n        check_compute_fn: bool = False,\n        device: Union[str, torch.device] = torch.device(\"cpu\"),\n    ):\n\n        try:\n            from sklearn.metrics import average_precision_score\n        except ImportError:\n            raise RuntimeError(\"This contrib module requires sklearn to be installed.\")\n\n        super(AveragePrecision, self).__init__(\n            average_precision_compute_fn,\n            output_transform=output_transform,\n            check_compute_fn=check_compute_fn,\n            device=device,\n        )\n", "path": "ignite/contrib/metrics/average_precision.py"}]}