Repository: Lightning-AI/torchmetrics

Issue:
MetricTracker of a single metric should not accept a list of `maximize`
## 🐛 Bug

It can be confusing that MetricTracker can be instantiated with a single metric and still accept a list of booleans as `maximize`. Further, when calling `tracker.best_metric`, the metric will always be maximized when `maximize` is a list and `metric` is a single Metric (even if `maximize` is `[False]`), which is clearly not an expected behavior (the reason for this comes from those two lines in `MetricTracker`'s `best_metric` method:
```py
if isinstance(self._base_metric, Metric):
    fn = torch.max if self.maximize else torch.min
```
Here, if `self.maximize` is any list, the condition will be True.
Raising an error at initialization in such a scenario would be safer.

### To Reproduce

Initialize a `MetricTracker` with a single metric as `metric` and a list of booleans as `maximize`.

#### Code sample

```py
>>> import torch
>>> from torchmetrics import MetricTracker, MeanSquaredError
>>> _ = torch.manual_seed(42)
>>> tracker = MetricTracker(MeanSquaredError(), maximize=[False])
>>> for epoch in range(5):
...     tracker.increment()
...     for batch_idx in range(5):
...         preds, target = torch.randn(100), torch.randn(100)
...         tracker.update(preds, target)
... 
>>> best_acc, which_epoch = tracker.best_metric(return_step=True)
>>> print(best_acc)
2.2481114864349365
>>> print(which_epoch)
4
>>> print(tracker.compute_all())
tensor([1.8218, 2.0268, 1.9491, 1.9800, 2.2481])
```
=> The metric has been maximized despite `maximize` being `[False]`

### Expected behavior

Raising a `ValueError` at the initialization of `MetricTracker`, indicating that `maximize` should be a single `bool` when the `metric` is a single `Metric`.

### Environment

- TorchMetrics version: 0.12.0dev
- Python & PyTorch Version: Python 3.10.6, torch 1.13.1+cu117
- Any other relevant information such as OS (e.g., Linux): Ubuntu 20.04

### Additional context

With the additional support of `MultioutputWrapper` that I am working on (#1409) this becomes even more confusing, because a `MultioutputWrapper` is a single `Metric` and a user could be tempted to give a list of booleans as `maximize`.


Discussion:
good catch, would you be interested in sending a fix? :rabbit: 
Yes, I coded a fix already, just need to make a proper pull request!
I'm also curious about why we use a `maximize` value to begin with. 
Couldn't we simply use the `metric.higher_is_better` instead (and `[m.higher_is_better for m in metric.values()]` when metric is a `MetricCollection`)?
It seems that `maximize` is redundant with `higher_is_better`.

Resolving patch:
diff --git a/src/torchmetrics/wrappers/tracker.py b/src/torchmetrics/wrappers/tracker.py
--- a/src/torchmetrics/wrappers/tracker.py
+++ b/src/torchmetrics/wrappers/tracker.py
@@ -103,6 +103,8 @@ def __init__(self, metric: Union[Metric, MetricCollection], maximize: Union[bool
             raise ValueError("Argument `maximize` should either be a single bool or list of bool")
         if isinstance(maximize, list) and isinstance(metric, MetricCollection) and len(maximize) != len(metric):
             raise ValueError("The len of argument `maximize` should match the length of the metric collection")
+        if isinstance(metric, Metric) and not isinstance(maximize, bool):
+            raise ValueError("Argument `maximize` should be a single bool when `metric` is a single Metric")
         self.maximize = maximize
 
         self._increment_called = False


Test patch:
diff --git a/tests/unittests/wrappers/test_tracker.py b/tests/unittests/wrappers/test_tracker.py
--- a/tests/unittests/wrappers/test_tracker.py
+++ b/tests/unittests/wrappers/test_tracker.py
@@ -41,6 +41,11 @@ def test_raises_error_on_wrong_input():
     ):
         MetricTracker(MetricCollection([MeanAbsoluteError(), MeanSquaredError()]), maximize=[False, False, False])
 
+    with pytest.raises(
+        ValueError, match="Argument `maximize` should be a single bool when `metric` is a single Metric"
+    ):
+        MetricTracker(MeanAbsoluteError(), maximize=[False])
+
 
 @pytest.mark.parametrize(
     "method, method_input",