我正在研究一个以图像为输入的深度学习项目。由于其他一些要求,我不能从一个文件夹加载图像,需要事先做。
我很难将所有图像加载到numpy数组中,因为其中有相当多的图像。也就是说,由于列表的长度,我经常用完Google Colab的25 GB内存。我知道列表是非常昂贵的空间,而numpy数组不是。然而,将图像直接加载到numpy数组中是很痛苦的。所以,我找到了一种变通方法,我一次只加载1000张图片到一个列表中,把它变成一个numpy数组,然后追加它。这一切似乎都工作得非常好,直到第九次交互,当RAM使用从大约3GB跳到25GB时,它都崩溃了。
我使用以下代码:
# Get images
def get_images(folder):
imgsl = []
i = 0
for filename in os.listdir(folder):
imgsl.append(img_to_array(load_img(folder + filename)))
i += 1
if i == 19:
imgs = np.array(imgsl, dtype=float)
imgsl = []
if i%1000 == 0:
i = 20
imgst = np.array(imgsl, dtype=float)
imgsl = []
imgs = np.append(imgs, imgst, axis = 0)
print('Thousand images processed!')
print('len: imgls: ', len(imgsl))
print('imgs shape: ', imgs.shape)
#imgs = np.array(imgs, dtype=float)
imgst = np.array(imgsl, dtype=float)
imgsl = []
imgs = np.append(imgs, imgst, axis = 0)
return imgs
并得到预期的结果,直到崩溃:
Thousand images processed!
len: imgls: 0
imgs shape: (1000, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (1980, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (2960, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (3940, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (4920, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (5900, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (6880, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (7860, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (8840, 224, 224, 3)
Thousand images processed!
len: imgls: 0
imgs shape: (9820, 224, 224, 3)
知道是怎么回事吗?或者关于修复它的建议?谢谢!
我很难将所有图像加载到numpy数组中,因为其中有相当多的图像
这样做通常是不合理的,并且会导致像您看到的那样的高内存占用。
我知道列表是超级空间昂贵的,而numpy数组不是。
如果列表包含Numpy数组,则不成立。列表的开销是每个项目对内存中CPython对象的8字节引用,以及64位平台上每个列表的小头(<100字节)。假设您的图像很大,这个开销可以忽略不计。然而,使用列表的列表的列表来存储N个图像将是非常昂贵的(因为每个整数/浮点值将存储在一个单独的CPython对象中,除了引用之外,还需要占用数十个字节)。
直接将图像加载到numpy数组中是很痛苦的。
这取决于用来加载它们的库。像OpenCV这样的一些库直接给你Numpy数组(顺便说一下,这是非常方便的)。
我来了一种变通方法,我一次只加载1000张图片到一个列表中
很好的决定,尽管它仍然占用大量空间(小批量当然更合理)。
这一切似乎都工作得非常好,直到第九次交互时,RAM使用量从大约3GB跃升到25GB,它都崩溃了。
一个问题是,您使用np.append
,每次创建一个新的数组。每个数组都是在前一个数组的基础上构建的,所以你实际上至少需要其中的2个。这还可能导致内存碎片,从而导致更高的内存占用。你应该将项目附加到列表中,然后将数组连接起来(例如:np.concatenate
或np.vstack
/np.hstack
等替代功能
另一个问题是np.array(imgsl, dtype=float)
,这当然是最大的一个。实际上,图像通常使用每个组件1字节进行编码(例如:每像素3或4个)。这里的float
类型意味着数组项是64位浮点数。因此,生成的数组每个组件占用8字节,这是不合理的(在空间和时间效率方面)。一个小小的改进是使用32位浮点数(np.float32
)。您可以尝试np.float16
类型,以便进一步减少内存占用。尽管如此,它将比基于uint8
/int8
的数组占用2倍的空间,更不用说两个数组应该同时存储在内存中以进行转换。更好的方法是预先分配输出数组并在循环中动态填充它。.