python pickle - 倾销一个非常庞大的列表

时间:2014-08-04 22:27:53

标签: python pickle

我有两个目录,每个目录包含大约50,000张图像,大多数是240x180。

我想将他们的像素信息腌制为训练,验证和测试集,

但这显然非常非常大,最终导致计算机空闲或耗尽磁盘空间。

当计算机冻结时,生成中间的pkl文件为28GB。

我不确定这应该是这么大。

我做错了吗?或者有更有效的方法吗?

from PIL import Image
import pickle
import os

indir1 = 'Positive'
indir2 = 'Negative'

trainimage = []
trainpixels = []
trainlabels = []
validimage = []
validpixels = []
validlabels = []
testimage = []
testpixels = []
testlabels = []


i=0
for (root, dirs, filenames) in os.walk(indir1):
    print 'hello'
    for f in filenames:
        try:
            im = Image.open(os.path.join(root,f))
            if i<40000:
                trainpixels.append(im.tostring())
                trainlabels.append(0)
            elif i<45000:
                validpixels.append(im.tostring())
                validlabels.append(0)
            else:
                testpixels.append(im.tostring())
                testlabels.append(0)
            print str(i)+'\t'+str(f)
            i+=1
        except IOError:
            continue

i=0
for (root, dirs, filenames) in os.walk(indir2):
print 'hello'
    for f in filenames:
        try:
            im = Image.open(os.path.join(root,f))
            if i<40000:
                trainpixels.append(im.tostring())
                trainlabels.append(1)
            elif i<45000:
                validpixels.append(im.tostring())
                validlabels.append(1)
            else:
                testpixels.append(im.tostring())
                testlabels.append(1)
            print str(i)+'\t'+str(f)
            i+=1
        except IOError:
            continue

trainimage.append(trainpixels)
trainimage.append(trainlabels)
validimage.append(validpixels)
validimage.append(validlabels)
testimage.append(testpixels)
testimage.append(testlabels)

output=open('data.pkl','wb')

pickle.dump(trainimage,output)
pickle.dump(validimage,output)
pickle.dump(testimage,output)

2 个答案:

答案 0 :(得分:3)

pickle文件格式不是特别有效,尤其不适用于图像。即使您的像素存储为每像素1个字节,您也可以

  

50,000×240×180 = 2,160,000,000

所以2 GB。毫无疑问,你的像素占用了更多的空间,我不确定PIL tostring()方法对图像的实际作用。完全可信的是,您生成的文件可能只有几十GB。

您可能需要考虑除pickle之外的存储方法。例如,简单地将文件以原生图像格式存储在磁盘上并挑选文件名列表会出现什么问题?

答案 1 :(得分:1)

我同意你可能不应该将大量的腌制图像存储到磁盘上......除非你绝对必须(无论出于何种原因)。你应该得到一个非常大的磁盘,一些非常好的内存,以及大量的处理能力。

无论如何,如果您使用scipy.ndimage.imread将图像数据传输到numpy.array,那么您可以使用numpy内部格式加压缩将图像存储到磁盘。

klepto这样的软件包可以让您轻松上手。

>>> from klepto.archives import dir_archive
>>> from scipy import ndimage
>>> demo = dir_archive('demo', {}, serialized=True, compression=9, cached=False)
>>> demo['image1'] = ndimage.imread('image1')
>>> demo['image2'] = ndimage.imread('image2')

现在你有了一个字典界面来接近numpy内部表示压缩的pickle图像文件,在一个名为demo的目录中每个文件有一个图像(也许你需要添加fast=True标志,我不要&#39记得)。所有的字典方法都非常可用,因此您可以根据需要访问图像进行分析,然后使用del demo['image1']或类似的东西抛出腌制的图像。

您还可以使用klepto轻松提供自定义编码,因此您可以对数据进行相当加密的存储。你甚至可以选择不对你的数据进行加密/腌制,而只是为了在磁盘上设置一个字典界面 - 这本身通常很方便。

如果您没有关闭缓存,则可能会达到计算机内存或磁盘大小的限制,除非您注意转储的顺序并将映像加载到磁盘。在上面的例子中,我关闭了内存缓存,因此它直接写入磁盘。还有其他选项,例如使用内存映射模式和写入HDF文件。我通常使用如上所述的方案来处理大型阵列数据,并在一台机器上进行处理,并可能选择一个MySQL归档后端,以便更多小型数据可以被多台机器并行访问。

在此处获取kleptohttps://github.com/uqfoundation