Как я могу получить градиент определенного количества изображений из нескольких изображений с помощью Pytorch? Вместо грPython

Программы на Python
Anonymous
Как я могу получить градиент определенного количества изображений из нескольких изображений с помощью Pytorch? Вместо гр

Сообщение Anonymous »

После того, как я обучил глубокую нейронную сеть (DNN), которая принимает 6 изображений в качестве входных данных, Я хочу оценить производительность модели, добавив возмущения к входным изображениям. В данном случае, используя градиент Функция потерь по отношению к входным изображениям является эффективным методом создания возмущений.
Но беда грядет.
Проще говоря, графическому процессору NVIDIA не хватит памяти, если я установлю input_images.requires_grad=True. Форма input_images — torch.Size([1, 6, 3, 928, 1600]), где 1 обозначает размер пакета, 6 — количество камер, 3 — каналы изображения и (928 , 1600) для ширины и высоты изображения соответственно. Кстати, входные изображения взяты из набора данных nuScenes.
Я использую приведенную ниже спецификацию удаленного сервера.

Код: Выделить всё

OS: Ubuntu 22.04.4 LTS
GPU: NVIDIA GeForce RTX 4090 / 24GB Memory
Totally 4 GPU
Сначала я бы вставил выходную информацию из терминала.

Код: Выделить всё

  File "/home/server/my_space/src/attack_eval.py", line 184, in main
predict_labels_vox, predict_labels_pts = my_model(img=imgs,

...

File "/home/server/my_space/modules/image_cross_attention.py", line 389, in forward
sampling_offsets, attention_weights = self.get_sampling_offsets_and_attention(query)
File "/home/server/my_space/modules/image_cross_attention.py", line 309, in get_sampling_offsets_and_attention
attns = torch.cat(attns, dim=1)
torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 72.00 MiB (GPU 0; 23.65 GiB total capacity; 22.53 GiB already allocated; 13.00 MiB free; 22.71 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF
Из выходных данных терминала мы видим, что во время процесса пересылки у cuda не хватило памяти. Ниже я также вставлю соответствующие коды:

Код: Выделить всё

my_model.eval()

for param in my_model.parameters():
param.requires_grad = False

torch.cuda.empty_cache()

for i_iter_val, (imgs, img_metas, val_vox_label, val_grid, val_pt_labs) in enumerate(val_dataset_loader):
imgs = imgs.cuda()
imgs.requires_grad = True

### This line caue the error above ###
predict_labels_vox, predict_labels_pts = my_model(img=imgs,
...

loss = ...
my_model.zero_grad()
loss.backward()
...

data_grad = input_images.grad.data

# Add the grad to the images
...
В приведенных выше кодах я закрываю флаг градиента my_model.parameters(), чтобы уменьшить использование памяти CUDA. Общее количество параметров my_model составляет около 67 000 000. Кстати, на этапе обучения код может успешно выполняться и получать градиент параметров. А общее количество пикселей входных изображений составляет около 26 700 000.
Вот вопрос: может ли память графического процессора поддерживать обучение всех параметров (около 0,067B), почему нельзя поддерживать расчет градиента всех входных изображений, то есть всех пикселей (около 0,026B)? Примечание. На этапе обучения я использую несколько графических процессоров, как и на этапе оценки.
Я пробовал несколько решений.
Решение 1. Уменьшите разрешение входных изображений. (Успешный запуск, но не рекомендуется)
Давайте углубимся в код.

Код: Выделить всё

def downsample_images(images, scale_factor=0.5):
# images: [1, 6, 3, 928, 1600]
batch_size, time_steps, channels, height, width = images.shape
new_height = int(height * scale_factor)
new_width = int(width * scale_factor)
images = images.view(batch_size * time_steps, channels, height, width)
downsampled_images = F.interpolate(images, size=(new_height, new_width), mode='bilinear', align_corners=False)
downsampled_images = downsampled_images.view(batch_size, time_steps, channels, new_height, new_width)
return downsampled_images

imgs = downsample_images(imgs, scale_factor=0.5)

... = my_model(output)
Таким образом, код может успешно выполнить пересылку модели, но это также повлияет на исходную производительность нейронной сети. Поэтому я пытаюсь придумать другие мысли.
Решение 2. Разделение входных изображений. (Не удалось. Попытка неглубокая, но правильность необходимо проверить.)

Код: Выделить всё

attack_image = imgs[:, 5:, :, :, :]
attack_image.requires_grad = True

imgs = imgs[:, :5, :, :, :]
imgs.requires_grad = False

class my_model(nn.Module):
...

def forward(imgs, attack_imgs):
img = torch.cat((img, attack_images), dim=1)
...

... = my_model(imgs, attack_imgs)
Решение 3. Для частичных элементов тензора установлено значение True. (Не удалось.)

Код: Выделить всё

imgs[:, 5:, :, :, :].requires_grad = True
... = my_model(imgs)
Исходя из вышеизложенных мыслей, я до сих пор не могу справиться с этой проблемой. Поэтому я ищу помощи в сообществе. Если вам нужна дополнительная информация, чтобы предложить решение, пожалуйста, дайте мне знать. Заранее спасибо.

Подробнее здесь: https://stackoverflow.com/questions/787 ... e-images-w

Вернуться в «Python»