如图,在跑完训练集以后,显存占用和训练时一样,一直保持七点多,然后去跑测试集,结果提示内存不足。
测试集没有求导,而且在测试集运行释放内存的函数也没有用,显存占用还是那么多。
需要把释放内存的函数放在运行训练集的cell跑吗?
你这个是普通家用卡,不推荐,建议用专业卡,专业卡通常有48GB或者96GB的内存,而你这种家庭游戏卡,只有几GB
图片的标签只能是[0:c-1](此处代表前闭后闭的区间),其中c为图片的类别,否则可能会出现错误。
class RMBDataset(Dataset):
def __init__(self, root, resize, mode): # 根据输入mode的不同将数据集分为训练集,验证集和测试集
super(RMBDataset, self).__init__()
self.root = root
self.resize = resize
self.mode = mode
self.name2label = {} # "sq...": 0
for name in sorted(os.listdir(os.path.join(root))[:6], key=int):
if not os.path.isdir(os.path.join(root, name)):
continue
self.name2label[name] = len(self.name2label.keys())
# print(self.name2label[name])
self.images, self.labels = self.load_csv("images.csv")
if self.mode == 'train': # 60% mode=‘train’则生成训练集
self.images = self.images[: int(0.6 * len(self.images))]
self.labels = self.labels[: int(0.6 * len(self.labels))]
elif self.mode == 'val': # 20% = 60% -> 80% mode=‘val’则生成训练集
self.images = self.images[int(0.6 * len(self.images)): int(0.8 * len(self.images))]
self.labels = self.labels[int(0.6 * len(self.labels)): int(0.8 * len(self.labels))]
else: # mode=‘test’则生成训练集
self.images = self.images[int(0.8 * len(self.images)):]
self.labels = self.labels[int(0.8 * len(self.labels)):]
def load_csv(self, filename):# 加载文件
if not os.path.exists(os.path.join(filename)):
images = []
for name in self.name2label.keys():
images += glob.glob(os.path.join(self.root, name, '*.jpg'))
random.shuffle(images)
with open(os.path.join(filename), mode='w', newline='') as f:
writer = csv.writer(f)
for img in images:
name = img.split(os.sep)[-2]
label = self.name2label[name]
writer.writerow([img, label]) # 将图片路径和标签写入csv文件
images, labels = [], []
with open(os.path.join(filename)) as f:
reader = csv.reader(f)
for row in reader:
img, label = row
label = int(label)
images.append(img)
labels.append(label)
assert len(images) == len(labels)
# print(type(images), type(labels[0]))
return images, labels
def denormalize(self, x_hat): # 反归一化
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
mean = torch.tensor(mean).unsqueeze(1).unsqueeze(1)
std = torch.tensor(std).unsqueeze(1).unsqueeze(1)
x = x_hat * std + mean
return x
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
img, label = self.images[idx], self.labels[idx]
# 数据增强
tf1 = transforms.Compose([
lambda x : Image.open(x).convert('RGB'),
transforms.Resize((int(self.resize * 1.25), int(self.resize * 2))),
transforms.RandomRotation(15),
transforms.CenterCrop(self.resize),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
tf2 = transforms.Compose([
lambda x : Image.open(x).convert('RGB'),
transforms.Resize((int(self.resize * 1), int(self.resize * 1.5))),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
if self.mode == 'test': # 对于测试集数据使用tf2的方式对图片进行数据增强,该方式主要是为了方便可视化查看。
img = tf2(img)
else:
img = tf1(img)
label = torch.tensor(label)
return img, label
针对该问题,可以尝试以下优化模型训练过程以避免出现显存不足的情况:
可以通过调节batch_size寻找一个合适的值来在显存和时间之间做出权衡
使用torch.utils.data.DataLoader的num_workers参数
可以通过调节num_workers参数寻找一个合适的值
将模型转移到GPU上
如果没有将模型转移到GPU上,可以使用model.cuda()将模型转移到GPU上进行训练,从而减少CPU的显存占用
使用半精度训练
另外,即使在显存不足的情况下,也可以尝试使用模型的量化版本进行测试集的推理预测,可以通过以下代码实现:
# Load int8 model
state_dict = torch.load('./model.pth')
model_fp32 = CNN()
model_fp32.qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_fp32_prepared = torch.quantization.prepare(model_fp32)
model_int8 = torch.quantization.convert(model_fp32_prepared)
model_int8.load_state_dict(state_dict)
model = model_int8
model.eval()
# 使用model进行推理预测
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images = get_variable(images)
labels = get_variable(labels).squeeze()
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))