Repository: pytorch/ignite

Issue:
SSIM update does not work for the last batch (if batch size is different)
## 🐛 Bug description
![Screenshot 2022-03-28 at 4 27 36 PM](https://user-images.githubusercontent.com/13629918/160447093-d5c0980e-4951-4eaa-930b-6dd9ea7992a4.png)

<!-- A clear and concise description of what the bug is. -->
<!-- Please, add steps on how to reproduce it. -->
<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->
<!-- A clear and concise description of what you expected to happen. -->

## Environment

- PyTorch Version :1.10.1
- Ignite Version ():0.4.8
- OS : Ubuntu
- How you installed Ignite (`conda`, `pip`, source): 
- Python version: 3.9
- Any other relevant information:

If the previous batch and the current batch are different then it throws the error. Attaching the screen shot of error. 

Screenshot of the basic code is also attached.
![Screenshot 2022-03-28 at 7 04 08 PM](https://user-images.githubusercontent.com/13629918/160450347-141131ed-ef66-4532-a36a-a21c27028b0e.png)

Implementation of ReduceLROnPlateau scheduler 
## 🚀 Feature

While there might be some workarounds in using `ReduceLROnPlateau` with ignite's optimizer , it would be nicer to have a standalone feature like other schedulers in contrib.

[Relevant issue and code sample](https://github.com/pytorch/ignite/issues/462#issuecomment-771907302).


Discussion:

Resolving patch:
diff --git a/ignite/metrics/ssim.py b/ignite/metrics/ssim.py
--- a/ignite/metrics/ssim.py
+++ b/ignite/metrics/ssim.py
@@ -98,7 +98,7 @@ def __init__(
 
     @reinit__is_reduced
     def reset(self) -> None:
-        self._sum_of_ssim = torch.tensor(0.0, device=self._device)
+        self._sum_of_ssim = torch.tensor(0.0, dtype=torch.float64, device=self._device)
         self._num_examples = 0
         self._kernel = self._gaussian_or_uniform_kernel(kernel_size=self.kernel_size, sigma=self.sigma)
 
@@ -180,7 +180,7 @@ def update(self, output: Sequence[torch.Tensor]) -> None:
         self._num_examples += y.shape[0]
 
     @sync_all_reduce("_sum_of_ssim", "_num_examples")
-    def compute(self) -> torch.Tensor:
+    def compute(self) -> float:
         if self._num_examples == 0:
             raise NotComputableError("SSIM must have at least one example before it can be computed.")
-        return self._sum_of_ssim / self._num_examples
+        return (self._sum_of_ssim / self._num_examples).item()


Test patch:
diff --git a/tests/ignite/metrics/test_ssim.py b/tests/ignite/metrics/test_ssim.py
--- a/tests/ignite/metrics/test_ssim.py
+++ b/tests/ignite/metrics/test_ssim.py
@@ -96,10 +96,8 @@ def test_ssim(device, shape, kernel_size, gaussian, use_sample_covariance):
         use_sample_covariance=use_sample_covariance,
     )
 
-    assert isinstance(ignite_ssim, torch.Tensor)
-    assert ignite_ssim.dtype == torch.float64
-    assert ignite_ssim.device.type == torch.device(device).type
-    assert np.allclose(ignite_ssim.cpu().numpy(), skimg_ssim, atol=7e-5)
+    assert isinstance(ignite_ssim, float)
+    assert np.allclose(ignite_ssim, skimg_ssim, atol=7e-5)
 
 
 def test_ssim_variable_batchsize():
@@ -125,7 +123,7 @@ def test_ssim_variable_batchsize():
     ssim.reset()
     ssim.update((torch.cat(y_preds), torch.cat(y_true)))
     expected = ssim.compute()
-    assert torch.allclose(out, expected)
+    assert np.allclose(out, expected)
 
 
 def _test_distrib_integration(device, tol=1e-4):