Python Pickle 文件大小异常大

3

我制作了一个pickle文件,存储了100,000张大小为80x80的图像中每个像素的灰度值。

(另外还有一个包含100,000个整数的数组,其值为一位数字。)

我对pickle文件的总大小进行了估计,大约是:

4 byte x 80 x 80 x 100000 = 2.88 GB 

再加上整数数组,这个数组不应该很大。

生成的pickle文件大小超过16GB,因此解压和加载它需要几个小时,最终会在占用全部内存资源后冻结。

我的计算有问题还是我打包的方式有问题?

我是按照以下方式打包的文件。

from PIL import Image
import pickle
import os
import numpy
import time

trainpixels = numpy.empty([80000,6400])
trainlabels = numpy.empty(80000)
validpixels = numpy.empty([10000,6400])
validlabels = numpy.empty(10000)
testpixels = numpy.empty([10408,6400])
testlabels = numpy.empty(10408)

i=0
tr=0
va=0
te=0
for (root, dirs, filenames) in os.walk(indir1):
    print 'hello'
    for f in filenames:
        try:
                im = Image.open(os.path.join(root,f))
                Imv=im.load()
                x,y=im.size
                pixelv = numpy.empty(6400)
                ind=0
                for ii in range(x):
                        for j in range(y):
                                temp=float(Imv[j,ii])
                                temp=float(temp/255.0)
                                pixelv[ind]=temp
                                ind+=1
                if i<40000:
                        trainpixels[tr]=pixelv
                        tr+=1
                elif i<45000:
                        validpixels[va]=pixelv
                        va+=1
                else:
                        testpixels[te]=pixelv
                        te+=1
                print str(i)+'\t'+str(f)
                i+=1
        except IOError:
                continue
trainimage=(trainpixels,trainlabels)
validimage=(validpixels,validlabels)
testimage=(testpixels,testlabels)

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

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

如果您发现我的计算或代码有任何错误,请告诉我!


你的近似公式中的初始“8字节”是从哪里得来的?对于灰度像素来说,这似乎有点多。 - Kevin
@Kevin 哎呀,我想说的是4个字节!这会让我的 pickle 大小变得更奇怪! - ytrewq
@tristan 我需要坚持使用pickle。 - ytrewq
@CosmicRabbitMediaInc 为什么呢?对于数值/整型数据,将数据存储为对象会增加近乎滑稽的开销。 - user559633
@Kevin 像素值0-255已经调整为0-1的比例尺,使其成为浮点数。 - ytrewq
显示剩余3条评论
1个回答

2

Python Pickles不是一种节约的存储数据的机制,因为你存储的是对象而不是“只有数据”。

以下测试用例在我的系统上占用了24kb,而这只是一个稀疏小型numpy数组存储在pickle中:

import os
import sys
import numpy
import pickle

testlabels = numpy.empty(1000)
testlabels[0] = 1
testlabels[99] = 0

test_labels_size = sys.getsizeof(testlabels) #80

output = open('/tmp/pickle', 'wb')
test_labels_pickle = pickle.dump(testlabels, output)

print os.path.getsize('/tmp/pickle')

此外,我不确定您为什么认为Python中的数字大小为4kb - 非numpy整数为24字节(sys.getsizeof(1)),而numpy数组至少为80字节(sys.getsizeof(numpy.array([0], float)))。
正如您在对我的评论做出回应时所述,您有保留Pickle的理由,因此我不会再试图说服您不要存储对象,但请注意存储对象的开销。
作为一种选择:减少训练数据的大小/减少Pickle对象的数量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接