当我在完成第一个epoch的训练转入第一个epoch的验证的时候,跑了没多久pytorch就报错内存不足。
然后上网查了一些解决方案,其中有使用pytorch的多GPU并行的方案来解决:
if t.cuda.device_count() > 1:
model = nn.DataParallel(model)
if opt.use_gpu: model.cuda()
然而其带来的结果也就是多跑了几组batchsize的验证。就继续报错。接着又尝试了pytorch forum上给出的一个方案:
for ii, data in enumerate(dataloader):
input, label = data
val_input1 = Variable(input, volatile=True)
val_input = val_input1.float()
val_label = Variable(label.type(t.LongTensor), volatile=True)
if opt.use_gpu:
val_input = val_input.cuda()
val_label = val_label.cuda()
score = model(val_input)
loss = criterion(score,val_label)
if ii == 0:
loss_mean = loss.item() # 通过.item()返回python number
loss_mean = 0.1 * loss.item() + 0.9 * loss_mean
'''
使用torch.cuda.empty_cache()解决显存爆炸问题
'''
t.cuda.empty_cache() # 显存释放防止显存爆炸
然而发现还是不行,该爆炸继续爆炸。但是我使用的可是P100的显卡啊,两张并行就是32个G的显存。居然两张都炸了。等到了最后终于找到了解决方案:
'''
加 with torch.no_grad,来表明此处不需要进行梯度计算。因为我在验证集加了model.eval所以好像pytorch并不会自动进行val的梯度的清理。
'''
with t.no_grad():
for ii, data in enumerate(dataloader):
input, label = data
val_input1 = Variable(input, volatile=True)
val_input = val_input1.float()
val_label = Variable(label.type(t.LongTensor), volatile=True)
if opt.use_gpu:
val_input = val_input.cuda()
val_label = val_label.cuda()
score = model(val_input)
loss = criterion(score,val_label)
if ii == 0:
loss_mean = loss.item() # 通过.item()返回python number
loss_mean = 0.1 * loss.item() + 0.9 * loss_mean
t.cuda.empty_cache() # 显存释放防止显存爆炸
进行torch.no_grad 后终于能成功跑完一整个的epoch了。不过在程序中我输出的loss高达100000.后来经过询问得知,当你的target不为label的时候。需要对loss除以你的H*W。其具体实现为:
loss = criterion(score,target) / (128 * 128)
具体原因暂未在数学上理解透彻。在理解透彻后再进行补充