跑完训练集以后显存不足,无法跑测试集

   如图,在跑完训练集以后,显存占用和训练时一样,一直保持七点多,然后去跑测试集,结果提示内存不足。

   测试集没有求导,而且在测试集运行释放内存的函数也没有用,显存占用还是那么多。

   需要把释放内存的函数放在运行训练集的cell跑吗?

img

你这个是普通家用卡,不推荐,建议用专业卡,专业卡通常有48GB或者96GB的内存,而你这种家庭游戏卡,只有几GB

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7561164
  • 这篇博客也不错, 你可以看下算法模型运行后显存不释放解决办法
  • 除此之外, 这篇博客: 人民币面值识别中的 根据已有的图片构造数据集, 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 图片的标签只能是[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
    
  • 您还可以看一下 孙玖祥老师的图解数据结构与算法课程中的 无处不在的链表小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    针对该问题,可以尝试以下优化模型训练过程以避免出现显存不足的情况:

    1. 减小batch_size
    2. 减小batch_size可以降低显存的使用,但同时也会导致训练时间的增加
    3. 可以通过调节batch_size寻找一个合适的值来在显存和时间之间做出权衡

    4. 使用torch.utils.data.DataLoader的num_workers参数

    5. num_workers参数可以指定数据加载器中的进程数,从而减轻主进程的压力,降低显存的使用
    6. 可以通过调节num_workers参数寻找一个合适的值

    7. 将模型转移到GPU上

    8. 如果没有将模型转移到GPU上,可以使用model.cuda()将模型转移到GPU上进行训练,从而减少CPU的显存占用

    9. 使用半精度训练

    10. 可以使用torch.backends.cudnn.benchmark = True开启半精度训练
    11. 半精度训练可以显著降低显存的使用,但同时也会影响模型的训练速度和精度

    另外,即使在显存不足的情况下,也可以尝试使用模型的量化版本进行测试集的推理预测,可以通过以下代码实现:

    • 加载int8模型
    • 使用torch.quantization.prepare()和torch.quantization.convert()将模型转换为量化模型
    • 使用model.load_state_dict()加载量化模型
    • 使用model.eval()将模型设置为评估模式
    • 使用model进行推理预测
    # 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))