使用 Pytorch 进行训练:由于 CUDA 内存问题导致错误
Training with Pytorch: error due to CUDA memory issue
我正在尝试在 Cityscapes 数据集上训练模型以进行分割。我使用 torchvision deeplabv3_resnet50 模型及其 Cityscapes 数据集 class 和转换。万一重要,我是 运行 Jupyter notebook 中的代码。
数据集和数据加载器都在工作。当我尝试训练时,我总是在第一批试图通过网络(one_epoch 函数中的 y_ = net(xb))时出现此错误。
运行时错误:CUDA 内存不足。尝试分配 128.00 MiB(GPU 0;6.00 GiB 总容量;4.20 GiB 已分配;6.87 MiB 空闲;PyTorch 总共保留 4.20 GiB)
奇怪的是,无论批量大小(bs)是多少,根据错误的空闲内存量都是一个比尝试分配的内存量少一点的值,例如对于 bs=16 我得到:
运行时错误:CUDA 内存不足。尝试分配 2.00 GiB(GPU 0;6.00 GiB 总容量;2.90 GiB 已分配;1.70 GiB 可用;PyTorch 总共保留 2.92 GiB)
我有一个更复杂的模型 运行,它适用于 bs=16。该模型从头开始构建所有内容。但我真的希望能够使用 torchvision 的模型动物园和数据集似乎具有的简单性。
我的代码在下面,仅是最基本的代码,足以显示它是否 运行 在 GPU 上正常。
def one_epoch(net, loss, dl, opt=None, metric=None):
if opt:
net.train() # only affects some layers
else:
net.eval()
rq_stored = []
for p in net.parameters():
rq_stored.append(p.requires_grad)
p.requires_grad = False
L, M = [], []
dl_it = iter(dl)
for xb, yb in tqdm(dl_it, leave=False):
xb, yb = xb.cuda(), yb.cuda()
y_ = net(xb)
l = loss(y_, yb)
if opt:
opt.zero_grad()
l.backward()
opt.step()
L.append(l.detach().cpu().numpy())
if metric: M.append(metric(y_, yb).cpu().numpy())
if not opt:
for p,rq in zip(net.parameters(), rq_stored): p.requires_grad = rq
return L, M
accuracy = lambda y_,yb: (y_.max(dim=1)[1] == yb).float().mean()
def fit(net, tr_dl, val_dl, loss=nn.CrossEntropyLoss(), epochs=3, lr=3e-3, wd=1e-3):
opt = optim.Adam(net.parameters(), lr=lr, weight_decay=wd)
Ltr_hist, Lval_hist = [], []
for epoch in trange(epochs):
Ltr, _ = one_epoch(net, loss, tr_dl, opt)
Lval, Aval = one_epoch(net, loss, val_dl, None, accuracy)
Ltr_hist.append(np.mean(Ltr))
Lval_hist.append(np.mean(Lval))
print(f'epoch: {epoch+1}\ttraining loss: {np.mean(Ltr):0.4f}\tvalidation loss: {np.mean(Lval):0.4f}\tvalidation accuracy: {np.mean(Aval):0.2f}')
return Ltr_hist, Lval_hist
class To3ch(object):
def __call__(self, pic):
if pic.shape[0]==1: pic = pic.repeat(3,1,1)
return pic
bs = 1
imagenet_stats = ([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
transf = transforms.Compose([
transforms.ToTensor(),
To3ch(),
transforms.Normalize(*imagenet_stats)
])
train_ds = datasets.Cityscapes('C:/cityscapes_ds', split='train', target_type='semantic', transform=transf, target_transform=transf)
val_ds = datasets.Cityscapes('C:/cityscapes_ds', split='val', target_type='semantic', transform=transf, target_transform=transf)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True, num_workers=0)
val_dl = DataLoader(val_ds, batch_size=2*bs, shuffle=False, num_workers=0)
net = models.segmentation.deeplabv3_resnet50(num_classes=20)
fit(net.cuda(), train_dl, val_dl, loss=nn.CrossEntropyLoss(), epochs=1, lr=1e-4, wd=1e-4, plot=True)
您没有指定,但如果您使用的是原始 Cityscapes,则完全可以预料到此 OOM。
原始的 Cityscapes 数据集包含大图像(类似于 1024x2048,IIRC),看起来您有 6GB GPU。仅供参考,我无法将 batch_size=2
放入具有这种大小输入的 12GB GPU 中。
训练 DeepLab 模型时,对输入应用变换(例如,随机裁剪、调整大小、缩放等)很常见,但您似乎没有应用任何变换。
当你说:
I have a much more complicated model running, that will work with bs=16.
也许您正在研究另一种复杂性,它对内存需求的影响没有您想象的那么大。
我正在尝试在 Cityscapes 数据集上训练模型以进行分割。我使用 torchvision deeplabv3_resnet50 模型及其 Cityscapes 数据集 class 和转换。万一重要,我是 运行 Jupyter notebook 中的代码。
数据集和数据加载器都在工作。当我尝试训练时,我总是在第一批试图通过网络(one_epoch 函数中的 y_ = net(xb))时出现此错误。
运行时错误:CUDA 内存不足。尝试分配 128.00 MiB(GPU 0;6.00 GiB 总容量;4.20 GiB 已分配;6.87 MiB 空闲;PyTorch 总共保留 4.20 GiB)
奇怪的是,无论批量大小(bs)是多少,根据错误的空闲内存量都是一个比尝试分配的内存量少一点的值,例如对于 bs=16 我得到:
运行时错误:CUDA 内存不足。尝试分配 2.00 GiB(GPU 0;6.00 GiB 总容量;2.90 GiB 已分配;1.70 GiB 可用;PyTorch 总共保留 2.92 GiB)
我有一个更复杂的模型 运行,它适用于 bs=16。该模型从头开始构建所有内容。但我真的希望能够使用 torchvision 的模型动物园和数据集似乎具有的简单性。
我的代码在下面,仅是最基本的代码,足以显示它是否 运行 在 GPU 上正常。
def one_epoch(net, loss, dl, opt=None, metric=None):
if opt:
net.train() # only affects some layers
else:
net.eval()
rq_stored = []
for p in net.parameters():
rq_stored.append(p.requires_grad)
p.requires_grad = False
L, M = [], []
dl_it = iter(dl)
for xb, yb in tqdm(dl_it, leave=False):
xb, yb = xb.cuda(), yb.cuda()
y_ = net(xb)
l = loss(y_, yb)
if opt:
opt.zero_grad()
l.backward()
opt.step()
L.append(l.detach().cpu().numpy())
if metric: M.append(metric(y_, yb).cpu().numpy())
if not opt:
for p,rq in zip(net.parameters(), rq_stored): p.requires_grad = rq
return L, M
accuracy = lambda y_,yb: (y_.max(dim=1)[1] == yb).float().mean()
def fit(net, tr_dl, val_dl, loss=nn.CrossEntropyLoss(), epochs=3, lr=3e-3, wd=1e-3):
opt = optim.Adam(net.parameters(), lr=lr, weight_decay=wd)
Ltr_hist, Lval_hist = [], []
for epoch in trange(epochs):
Ltr, _ = one_epoch(net, loss, tr_dl, opt)
Lval, Aval = one_epoch(net, loss, val_dl, None, accuracy)
Ltr_hist.append(np.mean(Ltr))
Lval_hist.append(np.mean(Lval))
print(f'epoch: {epoch+1}\ttraining loss: {np.mean(Ltr):0.4f}\tvalidation loss: {np.mean(Lval):0.4f}\tvalidation accuracy: {np.mean(Aval):0.2f}')
return Ltr_hist, Lval_hist
class To3ch(object):
def __call__(self, pic):
if pic.shape[0]==1: pic = pic.repeat(3,1,1)
return pic
bs = 1
imagenet_stats = ([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
transf = transforms.Compose([
transforms.ToTensor(),
To3ch(),
transforms.Normalize(*imagenet_stats)
])
train_ds = datasets.Cityscapes('C:/cityscapes_ds', split='train', target_type='semantic', transform=transf, target_transform=transf)
val_ds = datasets.Cityscapes('C:/cityscapes_ds', split='val', target_type='semantic', transform=transf, target_transform=transf)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True, num_workers=0)
val_dl = DataLoader(val_ds, batch_size=2*bs, shuffle=False, num_workers=0)
net = models.segmentation.deeplabv3_resnet50(num_classes=20)
fit(net.cuda(), train_dl, val_dl, loss=nn.CrossEntropyLoss(), epochs=1, lr=1e-4, wd=1e-4, plot=True)
您没有指定,但如果您使用的是原始 Cityscapes,则完全可以预料到此 OOM。
原始的 Cityscapes 数据集包含大图像(类似于 1024x2048,IIRC),看起来您有 6GB GPU。仅供参考,我无法将 batch_size=2
放入具有这种大小输入的 12GB GPU 中。
训练 DeepLab 模型时,对输入应用变换(例如,随机裁剪、调整大小、缩放等)很常见,但您似乎没有应用任何变换。
当你说:
I have a much more complicated model running, that will work with bs=16.
也许您正在研究另一种复杂性,它对内存需求的影响没有您想象的那么大。