Keras“pickle_safe”:什么是“pickle safe”,或者在Python中是“不可picklable”的意思?

12
Keras的fit_generator()函数有一个参数pickle_safe,默认为False。若参数值设为True,可以提高训练速度。根据Keras文档,如果参数为非picklable类型,则无法轻松地传递给子进程,因此不能将它们传递给生成器。

问:如何确定我的参数是否pickle_safe

答:您需要确保传递给生成器的所有参数都是可pickle化的。对于您所描述的情况,您的参数(X_train、y_train、batch_size和p_keep)似乎都是可pickle化的(np.array、int 和 float)。请注意,这仅适用于使用Keras 2及以上版本。
1个回答

17

我对keras不熟悉,但从文档看来,pickle_safe只是意味着由生成器产生的元组必须是“可pickle化”的。

pickle是一个标准的Python模块,用于序列化和反序列化对象。标准的multiprocessing实现使用pickle机制在不同的进程之间共享对象——因为这两个进程不共享同一地址空间,所以它们不能直接查看相同的Python对象。因此,为了将对象从进程A发送到进程B,在A中将它们pickled(这样会产生特定格式的字节序列),然后通过进程间通信机制将pickled格式发送到B,最后在B中unpickled,从而在B的地址空间中产生A原始对象的副本。

因此,要发现您的对象是否是可picklable的,只需在它们上面调用pickle.dumps

>>> import pickle
>>> class MyObject:
...    def __init__(self, a, b, c):
...      self.a = a
...      self.b = b
...      self.c = c
...
>>> foo = MyObject(1, 2, 3)
>>> pickle.dumps(foo)
b'\x80\x03c__main__\nMyObject\nq\x00)\x81q\x01}q\x02(X\x01\x00\x00\x00cq\x03K\x03X\x01\x00\x00\x00aq\x04K\x01X\x01\x00\x00\x00bq\x05K\x02ub.'
>>>

dumps 方法会生成一个字节字符串。现在,我们可以使用 loads 方法从该字节字符串中重新构建对象 foo 作为 bar

>>> foo_pick = pickle.dumps(foo)
>>> bar = pickle.loads(foo_pick)
>>> bar
<__main__.MyObject object at 0x7f5e262ece48>
>>> bar.a, bar.b, bar.c
(1, 2, 3)

如果某个东西不可被"pickled",你会收到一个异常。例如,lambda函数是无法被pickled的:
>>> class MyOther:
...   def __init__(self, a, b, c):
...     self.a = a
...     self.b = b
...     self.c = c
...     self.printer = lambda: print(self.a, self.b, self.c)
...
>>> other = MyOther(1, 2, 3)
>>> other_pick = pickle.dumps(other)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Can't pickle local object 'MyOther.__init__.<locals>.<lambda>'

请参阅文档以获取更多信息: https://docs.python.org/3.5/library/pickle.html?highlight=pickle#what-can-be-pickled-and-unpickled

谢谢您提供了一种检查是否可序列化的方法。我已经阅读了文档,但是处理、流、线程等方面我还不太理解。您的建议是一个很好的测试方式! - SherylHohman
事实证明,仅仅设置 pickle_safe=True 也会抛出错误(至少在我的情况下),因为该对象实际上不是 pickle 安全的。我曾经认为会有某种静默失败的情况。 - SherylHohman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接