【问题标题】:Why does saving/loading data in python take a lot more space/time than matlab?为什么在 python 中保存/加载数据比 matlab 占用更多的空间/时间?
【发布时间】:2014-10-31 23:27:46
【问题描述】:

我有一些变量,包括字典、列表列表和 numpy 数组。我使用以下代码保存所有这些,其中 obj=[var1,var2,...,varn]。变量大小足够小,可以加载到内存中。

我的问题是当我在 matlab 中保存相应的变量时,输出文件在磁盘上占用的空间比在 python 中要少得多。同样,从磁盘加载变量在python中加载到内存中的时间要比matlab多得多。

with open(filename, 'wb') as output:
    pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)

谢谢

【问题讨论】:

  • pickle 不是优化的磁盘格式。它是一个完整的表示。如果空间是一个大问题,您可以压缩腌制结果或创建自己的文件格式。
  • 为了更快的酸洗,你可以给cPickle一个机会!
  • scipy.io.savemat 以 MATLAB 兼容格式(4 和 5 版本)保存数组(包括稀疏数组)。

标签: python matlab file-io numpy mat-file


【解决方案1】:

Matlab 使用 HDF5 和压缩来保存 mat-Files; HDF5 是一种可以非常快速地访问大量数据的格式。 Python-pickle 保护信息以重新创建对象,它没有针对速度和大小进行优化,而是针对灵活性进行了优化。 如果您愿意,请使用 HDF5 for python。

【讨论】:

  • 那么,使用 HDF5 保存/加载上述 obj 的最佳方法是什么? f = h5py.File(filename, "w",chunks=True) f['var1']=obj[0], ..., f.close()
【解决方案2】:

试试这个:

保存到磁盘

import gzip
gz = gzip.open(filename + '.gz', 'wb')
gz.write(pickle.dumps(obj, pickle.HIGHEST_PROTOCOL))
gz.close()

从磁盘加载

import gzip
gz = gzip.open(filename + '.gz', 'rb')
obj = pickle.loads(gz.read())
gz.close()

【讨论】:

  • 加载情况如何?应该像 lists=[] gz = gzip.open(filename + '.gz', 'rb') lists.append(gz.unzip(pickle.load(filename)))
【解决方案3】:

嗯,问题出在 pickle 而不是 Python 本身。正如其他人所提到的,以 7.3 或更高版本保存的 .mat 文件使用 HDF5 格式。 HDF5 已针对高效存储和检索大型数据集进行了优化; Pickle 以不同的方式处理数据。您可以使用 h5py 或 netcf4 Python 模块复制甚至超越 Matlab 的保存功能; NetCDF 是 HDF5 的子集。例如,使用 HDF5,您可以这样做:

import h5py
import numpy as np

f = h5py.File('test.hdf5','w')
a = np.arange(10)
dset = f.create_dataset("init", data=a)
f.close()

我不确定在 MATLAB 中执行等效操作是否会产生完全相同大小的文件,但应该是接近的。您可以尝试使用 HDF5 的压缩功能来获得您想要的结果。

编辑 1:

要加载 HDF5 文件,例如 .mat 文件,您可以执行 M2 = h5py.File('file.mat') 之类的操作。 M2 是一个 HDF5 组,有点像 python 字典。执行M2.keys() 会为您提供变量名称。如果其中一个变量是一个名为“data”的数组,您可以通过 data = M2["data"][:] 读取它。

编辑 2:

要保存多个变量,可以创建多个datasets。基本语法是f.create_dataset("variable_name", data=variable)。有关更多选项,请参见链接。例如

import h5py
import numpy as np

f = h5py.File('test.hdf5','w')

data1 = np.ones((4,4))
data2 = 2*data1
f.create_dataset("ones", data=data1)
f.create_dataset("twos", data=data2)

f 既是文件对象又是 HDF5 组。这样做f.keys() 给出:

[u'ones', u'twos']

要查看“ones”键下存储的内容,您可以:

f['ones'][:]

array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])

您可以根据需要创建任意数量的数据集。完成文件写入后,关闭文件对象:f.close()

我应该补充一点,我的方法只适用于类似数组的数据集。您可以保存其他 Python 对象,例如列表和字典,但这样做需要更多的工作。我只对大型 numpy 数组使用 HDF5。对于其他一切,泡菜对我来说都很好。

【讨论】:

  • 如何使用 HDF5 保存 data=[var1,var2,...,varn]?此外,我如何通过 HDF5 加载它们?
  • 使用 HDF5 保存数据的方法有多种。基本的方法是创建一个HDF5 dataset
  • 扩展我之前的评论.... 要加载 HDF5 文件,例如 .mat 文件,您可以执行 M2 = h5py.File('file.mat') 之类的操作。 M2 是一个 HDF5 组,有点像 python 字典。执行M2.keys() 会为您提供变量名称。如果其中一个变量是一个名为“data”的数组,您可以通过 data = M2["data][:]. 读取它
  • 谢谢!我觉得上面应该是 data = M2['data'][:]?
  • 那么,在这种情况下,我们如何保存多个变量,如 data1、data2、...?
猜你喜欢
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
  • 2016-11-13
相关资源
最近更新 更多