Deep learning Pytorch默认数据加载器无法用于大型图像分类训练集

Deep learning Pytorch默认数据加载器无法用于大型图像分类训练集,deep-learning,computer-vision,classification,pytorch,dataloader,Deep Learning,Computer Vision,Classification,Pytorch,Dataloader,我正在Pytorch中训练图像分类模型,并使用它们加载我的训练数据。我有一个非常大的训练数据集,所以通常每个类有几千张样本图像。在过去,我训练过的模型总共有大约200k张图像,没有任何问题。然而,我发现,当Pytorch数据加载程序总共有超过一百万张图像时,就会卡住 我相信当我调用dataset.ImageFolder(…)时,代码是挂起的。当I Ctrl-C时,这始终是输出: Traceback (most recent call last):

我正在Pytorch中训练图像分类模型,并使用它们加载我的训练数据。我有一个非常大的训练数据集,所以通常每个类有几千张样本图像。在过去,我训练过的模型总共有大约200k张图像,没有任何问题。然而,我发现,当Pytorch数据加载程序总共有超过一百万张图像时,就会卡住

我相信当我调用
dataset.ImageFolder(…)
时,代码是挂起的。当I Ctrl-C时,这始终是输出:

Traceback (most recent call last):                                                                                                 │
  File "main.py", line 412, in <module>                                                                                            │
    main()                                                                                                                         │
  File "main.py", line 122, in main                                                                                                │
    run_training(args.group, args.num_classes)                                                                                     │
  File "main.py", line 203, in run_training                                                                                        │
    train_loader = create_dataloader(traindir, tfm.train_trans, shuffle=True)                                                      │
  File "main.py", line 236, in create_dataloader                                                                                   │
    dataset = datasets.ImageFolder(directory, trans)                                                                               │
  File "/home/username/.local/lib/python3.5/site-packages/torchvision/datasets/folder.py", line 209, in __init__     │
    is_valid_file=is_valid_file)                                                                                                   │
  File "/home/username/.local/lib/python3.5/site-packages/torchvision/datasets/folder.py", line 94, in __init__      │
    samples = make_dataset(self.root, class_to_idx, extensions, is_valid_file)                                                     │
  File "/home/username/.local/lib/python3.5/site-packages/torchvision/datasets/folder.py", line 47, in make_dataset  │
    for root, _, fnames in sorted(os.walk(d)):                                                                                     │
  File "/usr/lib/python3.5/os.py", line 380, in walk                                                                               │
    is_dir = entry.is_dir()                                                                                                        │
Keyboard Interrupt                                                                                                                       
回溯(最近一次呼叫最后一次):│
文件“main.py”,第412行,在│
main()│
文件“main.py”,第122行,在main中│
运行\u培训(args.group、args.num\u类)│
run_training中的文件“main.py”,第203行│
列车加载器=创建数据加载器(列车目录,tfm.train\U trans,随机播放=真)│
文件“main.py”,第236行,在create_dataloader中│
dataset=datasets.ImageFolder(目录,trans)│
文件“/home/username/.local/lib/python3.5/site packages/torchvision/datasets/folder.py”,第209行,在│
是否有效\u文件=是否有效\u文件)│
文件“/home/username/.local/lib/python3.5/site packages/torchvision/datasets/folder.py”,第94行,在│
samples=make_数据集(self.root,class_to_idx,扩展名,是有效的文件)│
make_数据集中第47行的文件“/home/username/.local/lib/python3.5/site packages/torchvision/datasets/folder.py”│
对于根,在排序(os.walk(d)):│
文件“/usr/lib/python3.5/os.py”,第380行,在walk中│
is_dir=entry.is_dir()│
键盘中断
我认为某个地方可能会出现死锁,但是根据Ctrl-C的堆栈输出,它看起来不像是在等待锁。然后我认为数据加载程序很慢,因为我试图加载更多的数据。我让它运行了大约2天,但没有取得任何进展,在加载的最后2个小时里,我检查了RAM的使用量是否保持不变。在过去的不到几个小时内,我还能够加载超过200k图像的训练数据集。我还尝试升级我的GCP机器,使其具有32个内核、4个GPU和超过100GB的RAM,但似乎在加载了一定数量的内存后,数据加载程序就卡住了

我很困惑数据加载器在目录中循环时怎么会卡住,我仍然不确定它是卡住了还是速度太慢。有什么方法可以改变Pytortch数据加载器,使其能够处理超过100万张图像进行培训?任何调试建议也将不胜感激


谢谢大家!

这不是数据加载器的问题,而是torchvision.datasets.ImageFolder的问题,以及它是如何工作的(以及为什么数据越多,它工作得更糟)

如您的错误所示,它挂在这一行上:

for root, _, fnames in sorted(os.walk(d)): 
来源可以找到

根本问题是它将每个
路径
和相应的
标签
保存在巨人
列表
中,请参见下面的代码(为了简洁起见删除了一些内容):

显然,图像将包含100万个字符串(相当长)和相应的类
int
,这些类肯定非常多,并且依赖于RAM和CPU

不过,您可以创建自己的数据集(前提是您事先更改了图像的名称),这样数据集就不会占用
内存

设置数据结构 您的文件夹结构应如下所示:

root
    class1
    class2
    class3
    ...
使用您拥有/需要的课程数量

现在,每个
应具有以下数据:

class1
    0.png
    1.png
    2.png
    ...
鉴于此,您可以继续创建数据集

创建数据集 下面的
torch.utils.data.Dataset
使用
PIL
打开图像,您可以用另一种方式:

import os
import pathlib

import torch
from PIL import Image


class ImageDataset(torch.utils.data.Dataset):
    def __init__(self, root: str, folder: str, klass: int, extension: str = "png"):
        self._data = pathlib.Path(root) / folder
        self.klass = klass
        self.extension = extension
        # Only calculate once how many files are in this folder
        # Could be passed as argument if you precalculate it somehow
        # e.g. ls | wc -l on Linux
        self._length = sum(1 for entry in os.listdir(self._data))

    def __len__(self):
        # No need to recalculate this value every time
        return self._length

    def __getitem__(self, index):
        # images always follow [0, n-1], so you access them directly
        return Image.open(self._data / "{}.{}".format(str(index), self.extension))
现在,您可以轻松地创建数据集(假定文件夹结构与上述结构类似:

root = "/path/to/root/with/images"
dataset = (
    ImageDataset(root, "class0", 0)
    + ImageDataset(root, "class1", 1)
    + ImageDataset(root, "class2", 2)
)
您可以使用指定的类添加任意数量的
数据集
,可以在循环中执行,也可以执行任何操作

最后,按照常规使用
torch.utils.data.DataLoader
,例如:

dataloader = torch.utils.data.DataLoader(dataset, batch_size=64, shuffle=True)

这不是数据加载器的问题,而是torchvision.datasets.ImageFolder的问题,以及它是如何工作的(以及为什么它工作得越差,数据越多)

如您的错误所示,它挂在这一行上:

for root, _, fnames in sorted(os.walk(d)): 
来源可以找到

根本问题是它将每个
路径
和相应的
标签
保存在巨人
列表
中,请参见下面的代码(为了简洁起见删除了一些内容):

明显的图像