CUDA не хватает памяти при настройке большой модели
Ранее я обучал режиму VGG (скажем, модель1) и двухслойной модели (скажем, модель2) отдельно, теперь мне нужно обучить новую модель, которая объединяет эти две модели вместе, и каждая часть новой модели инициализируется с помощью изученного Веса model1 и model2, которые я реализовал следующим образом:
class TransferModel(nn.Module):
def __init__(self, VGG, TwoLayer):
super(TransferModel, self).__init__()
self.vgg_layer=VGG
self.linear = TwoLayer
for param in self.vgg_layer.parameters():
param.requires_grad = True
def forward(self, x):
h1_vgg = self.vgg_layer(x)
y_pred = self.linear(h1_vgg)
return y_pred
# for image_id in train_ids[0:1]:
# img = load_image(train_id_to_file[image_id])
new_model=TransferModel(trained_vgg_instance, trained_twolayer_instance)
new_model.linear.load_state_dict(trained_twolayer_instance.state_dict())
new_model.vgg_layer.load_state_dict(trained_vgg_instance.state_dict())
new_model.cuda()
А когда тренируюсь, я стараюсь:
def train(model, learning_rate=0.001, batch_size=50, epochs=2):
optimizer=optim.Adam(model.parameters(), lr=learning_rate)
criterion = torch.nn.MultiLabelSoftMarginLoss()
x = torch.zeros([batch_size, 3, img_size, img_size])
y_true = torch.zeros([batch_size, 4096])
for epoch in range(epochs): # loop over the dataset multiple times
running_loss = 0.0
shuffled_indcs=torch.randperm(20000)
for i in range(20000):
for batch_num in range(int(20000/batch_size)):
optimizer.zero_grad()
for j in range(batch_size):
# ... some code to load batches of images into x....
x_batch=Variable(x).cuda()
print(batch_num)
y_true_batch=Variable(train_labels[batch_num*batch_size:(batch_num+1)*batch_size, :]).cuda()
y_pred =model(x_batch)
loss = criterion(y_pred, y_true_batch)
loss.backward()
optimizer.step()
running_loss += loss
del x_batch, y_true_batch, y_pred
torch.cuda.empty_cache()
print("in epoch[%d] = %.8f " % (epoch, running_loss /(batch_num+1)))
running_loss = 0.0
print('Finished Training')
train(new_model)
Во второй итерации (batch_num=1) первой эпохи я получаю эту ошибку:
CUDA из памяти. Попытка выделить 153,12 МБ (ГП 0; 5,93 ГБ общей емкости; 4,83 ГБ уже выделено; 66,94 МБ свободной; 374,12 МБ кэшировано)
Хотя я явно использовал "del" в своих тренировках, при запуске nvidia-smi похоже, что он ничего не делает и память не освобождается.
Что я должен делать?
1 ответ
Измените эту строку:
running_loss += loss
к этому:
running_loss += loss.item()
Добавляя loss
в running_loss
, вы говорите Pytorch, чтобы сохранить все градиенты по отношению к loss
для этой партии в памяти, даже когда вы начинаете обучение на следующей партии. Pytorch думает, что, возможно, вы захотите использовать running_loss
в некоторых больших функциях потерь в течение нескольких партий позже, и поэтому сохраняет все градиенты (и, следовательно, активации) для всех партий в памяти.
Добавляя .item()
вы просто получаете потерю как питон float
, а не torch.FloatTensor
, Этот float отделен от графа pytorch и, таким образом, pytorch знает, что вам не нужны градиенты по отношению к нему.
Если вы используете старую версию Pytorch без .item()
, ты можешь попробовать:
running_loss += float(loss).cpu().detach
Это также может быть вызвано аналогичной ошибкой в test()
цикл, если у вас есть.