Repository: pytorch/vision

Issue:
RandomErasing with default parameters is not scriptable
```py
import torch

from torchvision import transforms

transform = transforms.RandomErasing()

torch.jit.script(transform)
```

```
RuntimeError: 

get_params(Tensor img, (float, float) scale, (float, float) ratio, float[]? value=None) -> ((int, int, int, int, Tensor)):
Expected a value of type 'Optional[List[float]]' for argument 'value' but instead found type 'List[int]'.
:
  File "/home/user/vision/torchvision/transforms/transforms.py", line 1730
                )
    
            x, y, h, w, v = self.get_params(img, scale=self.scale, ratio=self.ratio, value=value)
                            ~~~~~~~~~~~~~~~ <--- HERE
            return F.erase(img, x, y, h, w, v, self.inplace)
        return img
```

The problem is the default of `value`

https://github.com/pytorch/vision/blob/5dd95944c609ac399743fa843ddb7b83780512b3/torchvision/transforms/transforms.py#L1638

It is an `int`, but `get_params` expect a `float`

https://github.com/pytorch/vision/blob/5dd95944c609ac399743fa843ddb7b83780512b3/torchvision/transforms/transforms.py#L1663-L1665

but we fail to convert it. Changing the default to `0.0` works, but since we support `int`'s in general

https://github.com/pytorch/vision/blob/5dd95944c609ac399743fa843ddb7b83780512b3/torchvision/transforms/transforms.py#L1619-L1620

we get the same error if we construct with `RandomErasing(value=1)` or the like.

This is not caught by our CI, because the JIT test checks all kind of inputs

https://github.com/pytorch/vision/blob/5dd95944c609ac399743fa843ddb7b83780512b3/test/test_transforms_tensor.py#L673-L676

but fails to include a single `int`.

cc @vfdev-5


Discussion:

Resolving patch:
diff --git a/torchvision/prototype/transforms/_augment.py b/torchvision/prototype/transforms/_augment.py
--- a/torchvision/prototype/transforms/_augment.py
+++ b/torchvision/prototype/transforms/_augment.py
@@ -23,7 +23,7 @@ def __init__(
         p: float = 0.5,
         scale: Tuple[float, float] = (0.02, 0.33),
         ratio: Tuple[float, float] = (0.3, 3.3),
-        value: float = 0,
+        value: float = 0.0,
         inplace: bool = False,
     ):
         super().__init__(p=p)
@@ -42,11 +42,11 @@ def __init__(
         self.scale = scale
         self.ratio = ratio
         if isinstance(value, (int, float)):
-            self.value = [value]
+            self.value = [float(value)]
         elif isinstance(value, str):
             self.value = None
-        elif isinstance(value, tuple):
-            self.value = list(value)
+        elif isinstance(value, (list, tuple)):
+            self.value = [float(v) for v in value]
         else:
             self.value = value
         self.inplace = inplace
diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py
--- a/torchvision/transforms/transforms.py
+++ b/torchvision/transforms/transforms.py
@@ -1713,11 +1713,11 @@ def forward(self, img):
 
             # cast self.value to script acceptable type
             if isinstance(self.value, (int, float)):
-                value = [self.value]
+                value = [float(self.value)]
             elif isinstance(self.value, str):
                 value = None
-            elif isinstance(self.value, tuple):
-                value = list(self.value)
+            elif isinstance(self.value, (list, tuple)):
+                value = [float(v) for v in self.value]
             else:
                 value = self.value
 


Test patch:
diff --git a/test/test_transforms_tensor.py b/test/test_transforms_tensor.py
--- a/test/test_transforms_tensor.py
+++ b/test/test_transforms_tensor.py
@@ -672,7 +672,17 @@ def shear(pil_img, level, mode, resample):
 @pytest.mark.parametrize("device", cpu_and_gpu())
 @pytest.mark.parametrize(
     "config",
-    [{"value": 0.2}, {"value": "random"}, {"value": (0.2, 0.2, 0.2)}, {"value": "random", "ratio": (0.1, 0.2)}],
+    [
+        {},
+        {"value": 1},
+        {"value": 0.2},
+        {"value": "random"},
+        {"value": (1, 1, 1)},
+        {"value": (0.2, 0.2, 0.2)},
+        {"value": [1, 1, 1]},
+        {"value": [0.2, 0.2, 0.2]},
+        {"value": "random", "ratio": (0.1, 0.2)},
+    ],
 )
 def test_random_erasing(device, config):
     tensor, _ = _create_data(24, 32, channels=3, device=device)