Ошибка при создании преобразования поезда с помощью torch vision

#python #pytorch #torchvision

Вопрос:

Я использую torch vision для создания следующей трансформации поезда. Я не понимаю, в чем дело и как я могу это исправить?

 train_transform = torch.nn.Sequential(
    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)
)
 

В этом и заключается ошибка:

Трассировка ошибок типа (последний последний вызов) в () 5 преобразованиях.RandomApply([преобразования.Рандомаффин(0, сдвиг=0,2)], 0,3), 6 преобразований.RandomApply([преобразования.Случайная обрезка(размер = 224, масштаб=(0.8, 1.4))], 0.7) —-> 7 ], р= 0,5) 8 )

1 кадры /usr/локальные/библиотеки/python3.7/dist-пакеты/факел/nn/модули/модуль.py в add_module(self, имя, модуль) 371, если не isinstance(модуль, модуль), а модуль не является None: 372 вызовите ошибку типа(«{} не является подклассом модуля».формат( —> 373 torch.typename(модуль))) 374 выясните, не является ли установка(имя, факел._six.string_classes): 375 вызовите ошибку типа(«имя модуля должно быть строкой. Есть {}».формат(

Ошибка типа: torchvision.преобразования.преобразования.ToTensor не является подклассом модуля

Комментарии:

1. Вы хотите использовать transforms.Compose вместо torch.nn.Sequential этого ? torch.nn.Sequential обычно используется для построения вашей модели, а не для создания преобразований ваших данных

2. @юки Да, но я хочу, чтобы эти преобразования происходили по порядку. видишь pytorch.org/vision/stable/transforms.html#scriptable-transforms

3. Я обновил свой ответ, чтобы вы могли написать сценарий своих преобразований, что является основной целью torch.nn.Sequential функции. Как я понимаю из документации, это, однако, не должно иметь значения, пишете ли вы преобразования или используете transforms.Compose , поскольку ваши преобразования в обоих случаях будут выполняться в порядке, указанном вами в функции.

Ответ №1:

torch.nn.Sequential сценарии ваших преобразований. Вы можете использовать только преобразования по сценарию torch.nn.Sequential и transforms.ToTensor() не являетесь преобразованием по сценарию. Преобразование, выполняемое по сценарию, принимает в качестве входных данных только тензор. Вот почему вы не можете использовать transforms.ToTensor() в torch.nn.Sequential функции, так как вы берете некоторые данные в качестве входных данных и преобразуете их в тензор.

Вы можете найти эту информацию в документации PyTorch здесь в разделе Преобразования по сценарию. transforms.RandomApply Преобразование также не поддается сценарию, но здесь, в документе transforms.visions, говорится, как его использовать в любом случае по сценарию (см. Определение класса RandomApply ). В исходном коде написано: «Для того, чтобы написать сценарий преобразования, пожалуйста, используйте torch.nn.ModuleList в качестве входных данных вместо списка/кортежа преобразований».

Вы должны обернуть все свои случайные преобразования 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)
 

Если вы хотите, вы также можете обернуть эти преобразования, torch.nn.Sequential но в этом нет необходимости. Тогда код должен быть таким:

 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)
 

Как уже упоминалось, тензорное преобразование не может быть добавлено к этому, так как оно не поддается сценарию.

Другое решение состоит в том, чтобы использовать transforms.Compose вместо torch.nn.Sequential этого:

 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)
])
 

В обоих случаях полный список преобразований будет случайным образом применен к вашим данным точно в том порядке, в котором вы указали преобразования в списке. Вы можете увидеть это из исходного кода Random.Применитесь, если прямой проход выглядит следующим образом

 def forward(self, img):
        if self.p < torch.rand(1):
            return img
        for t in self.transforms:
            img = t(img)
        return img
 

Функция выполняет циклы всех преобразований t self.transforms точно в том порядке, который вы указали в списке. Поэтому технически нет необходимости, чтобы вы использовали torch.nn.Sequential .