How to save dictionaries and arrays in the same archive (with numpy.savez)
第一个问题。我尽量简明扼要。
我正在为机器学习应用程序生成包含功能信息的多个数组。由于数组的维数不相等,所以我将它们存储在字典中而不是数组中。有两种不同的功能,所以我使用两种不同的字典。
我还生成了与特性匹配的标签。这些标签存储在数组中。此外,还有包含用于运行脚本和时间戳的确切参数的字符串。
总之,它看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import numpy as np feature1 = {} feature2 = {} label1 = np.array([]) label2 = np.array([]) docString = 'Commands passed to the script were...' # features look like this: feature1 = {'case 1': np.array([1, 2, 3, ...]), 'case 2': np.array([2, 1, 3, ...]), 'case 3': np.array([2, 3, 1, ...]), and so on... } |
现在我的目标是:
1 2 3 4 5 6 | np.savez(outputFile, saveFeature1 = feature1, saveFeature2 = feature2, saveLabel1 = label1, saveLabel2 = label2, saveString = docString) |
这看起来是可行的(即这样的文件保存时不会引发错误,可以再次加载)。但是,当我尝试再次从文件加载功能时,例如:
1 2 3 | loadedArchive = np.load(outFile) loadedFeature1 = loadedArchive['saveFeature1'] loadedString = loadedArchive['saveString'] |
然后,我得到了一个麻木的形状数组(0),而不是一个字典,我不知道如何访问内容:
1 2 3 4 5 | In []: loadedFeature1 Out[]: array({'case 1': array([1, 2, 3, ...]), 'case 2': array([2, 3, 1, ...]), ..., }, dtype=object) |
字符串也会成为数组并获得奇怪的数据类型:
1 2 | In []: loadedString.dtype Out[]: dtype('|S20') |
所以简而言之,我假设这不是正确的做法。但是,我不希望将所有变量都放在一个大字典中,因为我将在另一个进程中检索它们,并且希望在不担心字符串比较的情况下循环dictionary.keys()。
任何想法都非常感谢。谢谢
正如@fraxel已经建议的那样,在这种情况下使用pickle是更好的选择。把你的东西放在里面就行了。
但是,请确保将pickle与二进制协议一起使用。默认情况下,它的格式效率较低,如果数组很大,则会导致内存使用过度和文件过大。
1 2 3 4 5 6 7 8 9 | saved_data = dict(outputFile, saveFeature1 = feature1, saveFeature2 = feature2, saveLabel1 = label1, saveLabel2 = label2, saveString = docString) with open('test.dat', 'wb') as outfile: pickle.dump(saved_data, outfile, protocol=pickle.HIGHEST_PROTOCOL) |
已经说过了,为了便于说明,让我们更详细地看一下正在发生的事情。
如果将
1 2 3 4 | import numpy as np test = {'a':np.arange(10), 'b':np.arange(20)} testarr = np.asarray(test) |
同样,如果用字符串创建数组,则会得到一个字符串数组:
1 2 3 4 | In [1]: np.asarray('abc') Out[1]: array('abc', dtype='|S3') |
但是,由于处理对象数组的方式有点奇怪,如果传入一个不是元组、列表或数组的单个对象(在本例中是
这意味着您不能直接索引它。实际上,执行
如果这一切看起来都很笨拙,那是因为它是。对象数组本质上总是错误的答案。(虽然可以说,
不过,如果您确实想使用它,一个快速的解决方法是:
1 2 3 4 5 6 | np.savez(outputFile, saveFeature1 = [feature1], saveFeature2 = [feature2], saveLabel1 = [label1], saveLabel2 = [label2], saveString = docString) |
然后你就可以用
1 2 3 | loadedArchive = np.load(outFile) loadedFeature1 = loadedArchive['saveFeature1'][0] loadedString = str(loadedArchive['saveString']) |
然而,这显然比只用泡菜要笨重得多。在保存数组时使用
如果需要以结构化方式保存数据,则应考虑使用HDF5文件格式(http://www.hdfgroup.org/hdf5/)。它非常灵活、易于使用、高效,其他软件可能已经支持它(hdfview、mathematica、matlab、origin…)。有一个名为h5py的简单python绑定。
您可以将数据集存储在类似文件系统的结构中,并为每个数据集(如字典)定义属性。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import numpy as np import h5py # some data table1 = np.array([(1,1), (2,2), (3,3)], dtype=[('x', float), ('y', float)]) table2 = np.ones(shape=(3,3)) # save to data to file h5file = h5py.File("test.h5","w") h5file.create_dataset("Table1", data=table1) h5file.create_dataset("Table2", data=table2, compression=True) # add attributes h5file["Table2"].attrs["attribute1"] ="some info" h5file["Table2"].attrs["attribute2"] = 42 h5file.close() |
读取数据也很简单,如果需要,您甚至可以从大文件中加载几个元素:
1 2 3 4 5 6 7 | h5file = h5py.File("test.h5","r") # read from file (numpy-like behavior) print h5file["Table1"]["x"][:2] # read everything into memory (real numpy array) print np.array(h5file["Table2"]) # read attributes print h5file["Table2"].attrs["attribute1"] |
更多的功能和可能性可以在文档和网站上找到(快速入门指南可能会感兴趣)。
将所有变量放入一个对象中,然后使用pickle。这是存储状态信息的更好方法。