#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
.