两天没有错误,所以我想它已经解决了。最后,我使用了一些不同的东西,因为我在保存时在32GB RAM上运行64位python版本时遇到了MemoryError
,其中一半以上可用。
我有字典列表,其中每个字典包含多个不同的项目。它用作强化学习训练过程中的记忆重播,我需要创建一个备份文件,以防过程中断。每个字典代表一个环境步骤,因此结构相同,只有值不同。
每个字典包含的数据类型是:numpy数组的numpy.array,int,bool,字符串,列表和float。 Np数组经过了预处理,因此它确实包含实际的浮点数-不含NaN或Inf。
我的问题是,我尝试了多种方式,如何存储和加载文件,并且它们的行为都相似-创建备份没有问题,但是有时(甚至根本没有-根本没有模式可以发现其他地方的错误)加载它时,它会引发EOFError。
列表中的最大数据量现在限制为100k,创建的文件通常约为128MB。
当前,我正在通过pickle.dumps进行尝试,但过去我曾尝试过普通的joblib dump / load和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评论:
from joblib import dump, load
import pickle
[想法是通过pickle.dumps将对象序列化为字符串,并且由于它仅创建字符串但不保存到文件中,因此我使用joblib.dump来创建此类文件。
serialized_mem = load(f)
中确实引发错误,>
保存期间无例外
在转储后,文件路径作为dict(保持基类的继承)传递给主类,并与备份文件的其他路径(如神经网络,优化器等)合并。]
错误文件的大小是不确定的-有时在列表达到最大容量(100k个样本)之前会失败,然后其大小会变小,例如在500k步之后会发生错误,因此大小是正常的。但是您使我记住了一个重要的细节... self._memory
实际上是deque
from collections import deque
)类型(它继承自父类,并允许像list一样使用它,这就是为什么我忘记了关于它)。并且作为双端队列,保存“未满”对象可能是一个问题,这将解释EOFError的含义。我将做一些测试并报告结果。我有字典列表,其中每个字典包含多个不同的项目。它在强化学习的训练过程中用作记忆重播,在某些情况下,我需要创建一个备份文件...
两天没有错误,所以我想它已经解决了。最后,我使用了一些不同的东西,因为我在保存时在32GB RAM上运行64位python版本时遇到了MemoryError
,其中一半以上可用。
此实现在加载时似乎可以同时解决MemoryError
和EOFError
def save_backup(self, path:str, name:str) -> dict:
# save memory
file_path = path+name+'_memory.joblib'
with open(file_path, "wb") as f:
for data in list(self._memory):
pickle.dump(data,f)
# save other files
d = self._save_backup(path,name) # child class method
# merge dicts
d.update({'memory':file_path})
return d
def load_backup(self, data:dict):
# load memory
if os.path.exists(data['memory']):
with open(data['memory'], "rb") as f:
self._memory.clear()
while True:
try:
self._memory.append(pickle.load(f))
except EOFError:
break
# load others
self._load_backup(data) # child class method
两天没有错误,所以我想它已经解决了。最后,我使用了一些不同的东西,因为我在保存时在32GB RAM上运行64位python版本时遇到了MemoryError
,其中一半以上可用。