torch.nn.Sequential scripts your transformations. You can only use scriptable transformations in torch.nn.Sequential and transforms.ToTensor() is not a scriptable transformation.
A scriptable transformation only takes a Tensor as an input. This is why you cannot use transforms.ToTensor() in the torch.nn.Sequential function, as you take an some data as input and transform it to a tensor.
You can find this information in the PyTorch documentation here under Scriptable Transformations. The transforms.RandomApply transformation is also not scriptable but it says here in the transforms.visions docu how to use it in a scriptable way anyway (see the definition of the class RandomApply). In the source code it says: " In order to script the transformation, please use torch.nn.ModuleList as input instead of list/tuple of transforms"
You have to wrap all your random transformations with torch.nn.ModuleList.
my_transforms = transforms.RandomApply(torch.nn.ModuleList([
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomRotation(15)]), p=0.6),
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomAffine(0, shear=0.2)]), p=0.3),
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomResizedCrop(size = 224, scale=(0.8, 1.4))]), p=0.7),
]), p=0.3)
scripted_transforms = torch.jit.script(my_transforms)
If you want to, you can also wrap these transformations with torch.nn.Sequential but it is not necessary. Then the code should be this:
my_transforms = torch.nn.Sequential(transforms.RandomApply(torch.nn.ModuleList([
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomRotation(15)]), p=0.6),
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomAffine(0, shear=0.2)]), p=0.3),
transforms.RandomApply( torch.nn.ModuleList([ transforms.RandomResizedCrop(size = 224, scale=(0.8, 1.4))]), p=0.7),
]), p=0.3))
scripted_transforms = torch.jit.script(my_transforms)
As mentioned, the tensor transformation cannot be added to this, since it is not scriptable.
Another solution is to use the transforms.Compose instead of torch.nn.Sequential like this:
from torchvision import transforms
train_transform = transforms.Compose([
transforms.ToTensor(),
transforms.RandomApply([
transforms.RandomApply([transforms.RandomRotation(15)], 0.6),
transforms.RandomApply([transforms.RandomAffine(0, shear=0.2)], 0.3),
transforms.RandomApply([transforms.RandomResizedCrop(size = 224, scale=(0.8, 1.4))], 0.7)
], p= 0.5)
])
In both cases the complete list of transformations will be randomly applied to your data, exactly in the order as you have specified the transformations in the list. You can see this from the source code of Random.Apply, where the forward pass looks like this
def forward(self, img):
if self.p < torch.rand(1):
return img
for t in self.transforms:
img = t(img)
return img
The function loops over all transformations t in self.transforms exactly in the order you have specified in the list. So technically it is not necessary that you use torch.nn.Sequential.