Repository: Lightning-AI/torchmetrics

Issue:
`clone()` throwing exception on single `Metric` or `MetricCollection`
## 🐛 Bug

`clone()` functionality not working and raising argument error.

### To Reproduce

```python
>>> import torchmetrics as tm
>>> iou_train = tm.JaccardIndex(num_classes=3, average="none", mdmc_average="samplewise")
>>> iou_val = iou_train.clone()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/.../.venv/lib/python3.8/site-packages/torchmetrics/metric.py", line 569, in clone
    return deepcopy(self)
  File "/usr/lib/python3.8/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/usr/lib/python3.8/copy.py", line 264, in _reconstruct
    y = func(*args)
  File "/usr/lib/python3.8/copyreg.py", line 91, in __newobj__
    return cls.__new__(cls, *args)
TypeError: __new__() missing 1 required positional argument: 'num_classes
```

### Expected behavior

It should create a new object with given template

### Environment

- TorchMetrics version (and how you installed TM, e.g. `conda`, `pip`, build from source):
  - `torchmetrics==0.10.0 (pip)`
- Python & PyTorch Version (e.g., 1.0):
  - `python==3.8.10`
  - `torch==1.12.1+cu116`
- Any other relevant information such as OS (e.g., Linux):
  - `uname`
```
Linux hostname 5.15.0-1018-gcp #24~20.04.1-Ubuntu SMP Mon Sep 12 06:14:01 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
```
  - `nvcc --version`
```
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Tue_Mar__8_18:18:20_PST_2022
Cuda compilation tools, release 11.6, V11.6.124
Build cuda_11.6.r11.6/compiler.31057947_0
```

### Additional context

> P.S. When I downgrade to version ~0.9 , errors not occur anymore and works expected.


Discussion:

Resolving patch:
diff --git a/src/torchmetrics/metric.py b/src/torchmetrics/metric.py
--- a/src/torchmetrics/metric.py
+++ b/src/torchmetrics/metric.py
@@ -16,7 +16,7 @@
 from abc import ABC, abstractmethod
 from contextlib import contextmanager
 from copy import deepcopy
-from typing import Any, Callable, Dict, Generator, List, Optional, Sequence, Union
+from typing import Any, Callable, Dict, Generator, List, Optional, Sequence, Tuple, Union
 
 import torch
 from torch import Tensor
@@ -848,6 +848,9 @@ def __pos__(self) -> "Metric":
     def __getitem__(self, idx: int) -> "Metric":
         return CompositionalMetric(lambda x: x[idx], self, None)
 
+    def __getnewargs__(self) -> Tuple:
+        return (Metric.__str__(self),)
+
 
 def _neg(x: Tensor) -> Tensor:
     return -torch.abs(x)


Test patch:
diff --git a/tests/unittests/helpers/testers.py b/tests/unittests/helpers/testers.py
--- a/tests/unittests/helpers/testers.py
+++ b/tests/unittests/helpers/testers.py
@@ -165,6 +165,11 @@ def _class_test(
     if check_scriptable:
         torch.jit.script(metric)
 
+    # check that metric can be cloned
+    clone = metric.clone()
+    assert clone is not metric, "Clone is not a different object than the metric"
+    assert type(clone) == type(metric), "Type of clone did not match metric type"
+
     # move to device
     metric = metric.to(device)
     preds = apply_to_collection(preds, Tensor, lambda x: x.to(device))