【发布时间】:2020-02-29 22:12:20
【问题描述】:
我有字典列表,其中每个字典包含多个不同的项目。它在强化学习的训练过程中用作记忆回放,我需要创建一个备份文件以防万一该过程中断。每个 dict 代表一个环境步骤,因此结构相同,只有值不同。
每个 dict 包含的数据类型有:numpy.array、int、bool、string、list 的 numpy 数组和 float。 Np 数组经过预处理,因此它包含实数浮点数 - 没有 NaN 或 Inf。
我的问题是,我尝试了多种方法,如何存储和加载文件,并且所有文件的行为都相似 - 创建备份没有问题,但有时(甚至根本没有 - 根本没有模式可以在其他地方发现错误) 加载它时,它会引发 EOFError。
列表中的最大数据量现在限制为 100k,创建的文件通常在 128MB 左右。
目前我正在通过 pickle.dumps 进行尝试,但过去我尝试过使用普通的 joblib 转储/加载和 copy.deepcopy 进行转储。
def _save_backup(self, path:str, name:str) -> dict:
file_path = path+name+'_memory.joblib'
with open(file_path, "wb") as f:
serialized_mem = pickle.dumps(self._memory,protocol=pickle.HIGHEST_PROTOCOL)
dump(serialized_mem,f)
return {'memory':file_path}
def _load_backup(self, data:dict):
if os.path.exists(data['memory']):
with open(data['memory'], "rb") as f:
serialized_mem = load(f)
self._memory = pickle.loads(serialized_mem)
编辑
回复tdelaney评论:
- 加载和转储来自joblib
from joblib import dump, load
import pickle
想法是通过pickle.dumps将对象序列化为字符串,因为它只创建字符串但不保存到文件中,然后我使用joblib.dump来创建这样的文件。
确实在
serialized_mem = load(f)中引发了错误保存过程中不会抑制任何异常
dump 后,文件路径作为 dict(以保持基类的继承)传递给主类,并与其他备份文件路径(如神经网络、优化器等)合并。
错误文件大小不是确定性的 - 有时它会在列表达到其全部容量(100k 个样本)之前失败,然后它的 ofc 更小,有时会在例如 500k 步之后发生错误,因此大小是正常的。但是你让我记住了一个非常重要的细节......
self._memory实际上是 deque 类型(from collections import deque)(它从父级继承并允许像使用列表一样使用它,就是这样为什么我忘了它)。作为双端队列,保存“未满”对象可能会出现问题,这可以解释 EOFError 的含义。我会做一些测试并报告结果。
【问题讨论】:
-
dump()和load()是什么?你是双重腌制吗?load(f)的错误在哪里?失败时文件的大小是否合理?您是否正在捕获和抑制可能在转储期间发生的异常,从而导致文件缩略? -
@tdelaney 我已经添加了您要求的详细信息。关于文件大小的问题给了我一个想法,我将对其进行测试。