использование аргумента pytorch dataloader default_collate с to (устройством)

#pytorch #batch-processing #data-stream #dataloader

#pytorch #пакетная обработка #поток данных #загрузчик данных

Вопрос:

Я пытался интегрировать to (устройство) в мой загрузчик данных, используя to (устройство), как показано вhttps://github.com/pytorch/pytorch/issues/11372

Я определил это в FashionMNIST следующим образом:

 device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
batch_size = 32
trainset = datasets.FashionMNIST('~/.pytorch/F_MNIST_data/',
                                 download=True,
                                 train=True,
                                 transform=transforms.ToTensor())
rain_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=False, collate_fn=lambda x: default_collate(x).to(device))
  

Но я получаю следующую ошибку:
Ошибка атрибута: объект ‘list’ не имеет атрибута ‘to’
Кажется, что вывод по умолчанию collate представляет собой список длиной 2, где первый элемент является тензором изображения, а второй — тензором меток (поскольку это вывод next(iter(train_loader)) с collate_fn=None), поэтому я попробовал использовать следующую определенную функцию:

 def to_device_list(l, device):
    return [l[0].to(device), l[1].to(device)]
train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=False, collate_fn=lambda x: to_device_list(x, device))
  

И я получил следующую ошибку:
Ошибка атрибута: объект ‘tuple’ не имеет атрибута ‘to’

Любая помощь, пожалуйста, о том, как это сделать?

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

1. Я знаю, что слишком поздно, но добавил решение

Ответ №1:

Набор данных fashion mnist возвращает кортеж из img и target , где img является тензором, а target — int значением для класса.

Теперь вы dataloader берете образцы размера пакета из dataset класса, чтобы получить список образцов. Обратите внимание, что этот список примеров теперь, List[Tuple[Tensor, int]] (используя аннотацию ввода здесь). Затем он вызывает функцию collate для преобразования List[Tuple[Tensor, int]] в List[Tensor] , где этот список имеет 2 тензора. Первый тензор представляет собой сложенный массив изображений размером [32, 1, 28, 28], где 32 — размер пакета, а второй тензор — тензорный массив значений int (метки классов).

default_collate Функция просто преобразует массив структур в структуры массива.

Теперь, когда вы используете collate_fn=lambda x: default_collate(x).to(device) , обратите внимание, что default_collate возвращает вам список тензоров. Таким образом, вызов .to в списке не будет работать и должен вызываться для всех элементов списка.

Использование решения

 collate_fn=lambda x: list(map(lambda x: x.to(device), default_collate(x))))
  

Функция map передает каждый элемент списка (из default_collate ) в cuda и, наконец, вызывает список, поскольку map вычисляется лениво в python3.

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

1. Для тех, кто сталкивается с этой проблемой, я бы рекомендовал использовать инструмент отладки в pycharm или другой ide, или просто pudb. Таким образом очень легко определить проблему.