代码之家  ›  专栏  ›  技术社区  ›  ytrewq

python pickle-抛出一个非常庞大的列表

  •  2
  • ytrewq  · 技术社区  · 11 年前

    我有两个目录,每个目录包含大约50000个图像,这些图像的大小大多为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 回复  |  直到 11 年前
        1
  •  3
  •   Greg Hewgill    11 年前

    pickle文件格式不是特别有效,尤其是对于图像。即使像素存储为每像素1字节

    50000×240×180&等于;2,160,000,000

    因此为2GB。毫无疑问,你的像素占用的空间比这更多,我不确定PIL是什么 tostring() 方法实际上在图像上执行。你得到的文件可能有几十千兆字节,这是完全合理的。

    您可能需要考虑泡菜以外的存储方法。例如,简单地将文件以其原始图像格式存储在磁盘上,并提取文件名列表会有什么问题?

        2
  •  1
  •   Mike McKerns    11 年前

    我同意,除非你绝对必须(出于任何原因),否则你可能不应该将成吨的腌制图像存储到磁盘上。你可能会得到一个非常大的磁盘,有一些非常好的内存和大量的处理能力。

    无论如何,如果您将图像数据传输到numpy.array scipy.ndimage.imread ,然后可以使用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内部表示压缩的腌制图像文件的字典接口,每个文件一个图像位于名为 demo (也许你需要添加 fast=True 旗帜,我不记得了)。所有的字典方法都非常可用,因此您可以根据分析需要访问图像,然后使用 del demo['image1'] 或者类似的东西。

    您也可以使用 盗窃犯 以方便地提供自定义编码,因此您可以对数据进行相当加密的存储。您甚至可以选择不加密/保存数据,而只是在磁盘上有一个指向文件的字典接口——这本身就很方便。

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

    收到 盗窃犯 在这里: https://github.com/uqfoundation