Увеличение данных PyTorch занимает слишком много времени - PullRequest
2 голосов
/ 01 ноября 2019

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

dataset_for_augmentation.listDataset(train_list,
                        shuffle=True,
                        transform=transforms.Compose([
                            transforms.RandomHorizontalFlip(p=1),
                            transforms.ToTensor(),
                            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
                        ]),
                        target_transform=transforms.Compose([
                            transforms.RandomHorizontalFlip(p=1),
                            transforms.ToTensor()
                        ]),
                        train=True,
                        resize=4,
                        batch_size=args.batch_size,
                        num_workers=args.workers),

Но вот проблема: по какой-то причине функция PyTorch transforms.RandomHorizontFlip принимает только изображения PIL (numpy неразрешено) в качестве ввода. Поэтому я решил преобразовать тип в PIL Image.

img_path = self.lines[index]

img, target = load_data(img_path, self.train, resize=self.resize)

if type(target[0][0]) is np.float64:
    target = np.float32(target)

img = Image.fromarray(img)
target = Image.fromarray(target)

if self.transform is not None:
    img = self.transform(img)
    target = self.target_transform(target)

return img, target

И да, эта операция требует огромного количества времени. Учитывая, что мне нужно, чтобы эта операция выполнялась для тысяч изображений, недопустимо использовать 23 секунды (не более полсекунды) для каждой партии.

2019-11-01 16:29:02,497 - INFO - Epoch: [0][0/152]  Time 27.095 (27.095)    Data 23.150 (23.150)    Loss 93.7401 (93.7401)

Буду признателен за любые предложения по ускорениюмой процесс увеличения

Ответы [ 2 ]

3 голосов
/ 01 ноября 2019

Вам не нужно менять DataLoader, чтобы сделать это. Вы можете использовать ToPILImage():

transform=transforms.Compose([
    transforms.ToPILImage(),  # check mode assumption in the documentation
    transforms.RandomHorizontalFlip(p=1),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

В любом случае, я бы не стал конвертировать в PIL. Это кажется совершенно ненужным. Если вы хотите перевернуть все изображений, то почему бы не сделать это, используя только NumPy?

img_path = self.lines[index]

img, target = load_data(img_path, self.train, resize=self.resize)

if type(target[0][0]) is np.float64:
    target = np.float32(target)

# assuming width axis=1 -- see my comment below
img = np.flip(img, axis=1)
target = np.flip(target, axis=1)

if self.transform is not None:
    img = self.transform(img)
    target = self.target_transform(target)

return img, target

И удалить transforms.RandomHorizontalFlip(p=1) из Compose. Поскольку ToTensor(...) также обрабатывает ndarray, вы можете идти.

Примечание : Я предполагаю, что ширина оси равна 1, поскольку ToTensor ожидает, что она там будет.

Из документов :

Преобразование изображения PIL или numpy.ndarray (В x Ш x В) ...

1 голос
/ 01 ноября 2019

Больше дополнений к @ Берриэль ответу.

Горизонтальное отражение

Вы используете transforms.RandomHorizontalFlip(p=1) для изображений X и y. В вашем случае с p=1 они будут преобразованы точно так же, но вам не хватает точки увеличения данных, поскольку сеть будет видеть только перевернутые изображения (а не только оригинальные изображения). Для получения высокой вариабельности версий изображения вам следует использовать вероятность меньше 1 и больше 0 (обычно 0.5).

Если это так (p=0.5), вы можете быть большеуверен, что возникнет ситуация, когда X переворачивается, а y - нет.

Я бы посоветовал использовать библиотеку albumentations, а для этого нужно albumentations.augmentations.transforms.HorizontalFlipпереворачивание на обоих изображениях одинаково.

Нормализация

Вы можете найти normalization с ImageNet средствами и стандартными настройками, уже настроенными там.

Кэширование

Кроме того, чтобы ускорить процесс, вы можете использовать torchdata стороннюю библиотеку (заявление об отказе от ответственности, я автор). В вашем случае вы можете преобразовать образ из PIL в Tensor, Normalize с albumentations, cache на диске или, что еще лучше, в образы RAM после этих преобразований с помощью torchdata и, наконец, применить ваши преобразования. Этот способ позволит вам применить HorizontalFlip s к вашему изображению и цели после начальной эпохи, предыдущие шаги будут предварительно рассчитаны.

...