gpt4 book ai didi

python - 如何将字典和数组保存在同一个存档中(使用 numpy.savez)

转载 作者:太空狗 更新时间:2023-10-29 17:25:18 25 4
gpt4 key购买 nike

这里是第一个问题。我会尽量简洁。

我正在为机器学习应用程序生成包含特征信息的多个数组。由于数组的维度不同,我将它们存储在字典中而不是数组中。有两种不同的功能,所以我使用了两种不同的词典。

我还生成标签以配合这些功能。这些标签存储在数组中。此外,还有一些字符串包含用于运行脚本的确切参数和时间戳。

总而言之,它看起来像这样:

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... }

现在我的目标是这样做:

np.savez(outputFile, 
saveFeature1 = feature1,
saveFeature2 = feature2,
saveLabel1 = label1,
saveLabel2 = label2,
saveString = docString)

这似乎有效(即这样的文件保存时没有抛出错误并且可以再次加载)。但是,当我尝试再次从文件加载功能时:

loadedArchive = np.load(outFile)
loadedFeature1 = loadedArchive['saveFeature1']
loadedString = loadedArchive['saveString']

然后我没有取回字典,而是得到一个形状为 (0) 的 numpy 数组,我不知道如何访问其中的内容:

In []: loadedFeature1
Out[]:
array({'case 1': array([1, 2, 3, ...]),
'case 2': array([2, 3, 1, ...]),
..., }, dtype=object)

字符串也变成数组并得到一个奇怪的数据类型:

In []: loadedString.dtype
Out[]: dtype('|S20')

简而言之,我假设这不是正确的做法。但是,我不希望将所有变量都放入一个大字典中,因为我将在另一个进程中检索它们,并且只想循环遍历 dictionary.keys() 而不必担心字符串比较。

非常感谢任何想法。谢谢

最佳答案

正如@fraxel 已经建议的那样,在这种情况下使用 pickle 是一个更好的选择。只需保存一个包含您的项目的 dict

但是,请务必将 pickle 与二进制协议(protocol)一起使用。默认情况下,它的格式化效率较低,如果您的数组很大,这将导致过多的内存使用和巨大的文件。

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)

话虽如此,为了便于说明,让我们更详细地看一下发生了什么。

numpy.savez 期望每个项目都是一个数组。事实上,它会在您传入的所有内容上调用 np.asarray

如果将 dict 转换为数组,您将得到一个对象数组。例如

import numpy as np

test = {'a':np.arange(10), 'b':np.arange(20)}
testarr = np.asarray(test)

类似地,如果你用字符串创建一个数组,你会得到一个字符串数组:

In [1]: np.asarray('abc')
Out[1]:
array('abc',
dtype='|S3')

但是,由于处理对象数组的方式有一个怪癖,如果您传入一个不是元组、列表或数组的对象(在您的情况下,您的 dict) ,你会得到一个 0 维对象数组。

这意味着你不能直接索引它。事实上,执行 testarr[0] 会引发 IndexError。数据还在,但你需要先添加一个维度,所以你必须做yourdictionary = testarr.reshape(-1)[0]

如果所有这些看起来都很笨拙,那是因为它确实很笨重。对象数组基本上总是错误的答案。 (虽然 asarray 应该将 ndmin=1 传递给 array,这可以解决这个特定问题,但可能会破坏其他东西。)

savez 旨在存储数组,而不是任意对象。由于它的工作方式,它可以完全存储任意对象,但不应该那样使用它。

不过,如果您确实想使用它,一个快速的解决方法是:

np.savez(outputFile, 
saveFeature1 = [feature1],
saveFeature2 = [feature2],
saveLabel1 = [label1],
saveLabel2 = [label2],
saveString = docString)

然后您可以使用

访问内容
loadedArchive = np.load(outFile)
loadedFeature1 = loadedArchive['saveFeature1'][0]
loadedString = str(loadedArchive['saveString'])

但是,这显然比只使用 pickle 笨拙得多。仅在保存数组时使用 numpy.savez。在这种情况下,您保存的是嵌套数据结构,而不是数组。

关于python - 如何将字典和数组保存在同一个存档中(使用 numpy.savez),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10075661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com