为什么酸洗张量流张量会失败?
Why does pickling a tensorflow Tensor fail?
这是一个片段,它可以用 dill
成功序列化,但用 pickle
失败。令人惊讶的是 Tensor
对象不是原生可腌制的。这是线程感知张量的基本限制,还是只是没有实现?
import dill
import pickle
import tensorflow as tf
dill.dumps(tf.zeros((1,1)))
print("Dill succeeded")
pickle.dumps(tf.zeros((1,1)))
print("Pickle succeeded")
输出:
$ python foo.py
Dill succeeded
Traceback (most recent call last):
File "foo.py", line 7, in <module>
pickle.dumps(tf.zeros((1,1)))
TypeError: can't pickle _thread.lock objects
为什么dill可以序列化这些对象,而pickle却不能?简单的答案是 pickle
无法序列化 python 中的大多数对象,包括 thread.lock
对象。如果要序列化这些对象之一,请使用像 dill
这样的高级序列化库。至于为什么 pickle
不能,我认为它最初源于 GIL 的实现和 frame
对象渲染一些对象不可序列化,因此没有驱动来序列化语言中的所有内容。一直有关于所有 python 对象序列化引起的安全问题的讨论,但我认为这是转移注意力的问题。没有完整的语言序列化限制了在并行计算中运行的能力,因此希望 pickle
将学习 dill
如何序列化更多对象。
我发现我无法重现 eqzx's 脚本的输出并且 dill
和 pickle
的序列化都失败了。
虽然这个问题已经有好几年了,但我认为问题不在于 pickle,而在于 tensorflow 1.x 中的张量没有立即求值。当他们的图表被执行时,他们会被评估。 (在 tensorflow 2.0 中,eager execution 是默认启用的,所以你真的不必处理这个范例)。
使用 tf.enable_eager_execution()
或在 tf.Session()
上下文中评估张量
以下脚本在使用 Pickle 或 Dill 时不会抛出错误:
import tensorflow as tf
tf.enable_eager_execution()
import pickle
# import dill
n = tf.zeros((1,1))
pickle.dumps(n)
# dill.dumps(n)
print('Success')
使用 Session.run() 的相同脚本不会引发错误:
import tensorflow as tf
import pickle
# import dill
with tf.Session() as sess:
n = sess.run(tf.zeros((1,1)))
pickle.dumps(n)
# dill.dumps(n)
print('Success')
这是一个片段,它可以用 dill
成功序列化,但用 pickle
失败。令人惊讶的是 Tensor
对象不是原生可腌制的。这是线程感知张量的基本限制,还是只是没有实现?
import dill
import pickle
import tensorflow as tf
dill.dumps(tf.zeros((1,1)))
print("Dill succeeded")
pickle.dumps(tf.zeros((1,1)))
print("Pickle succeeded")
输出:
$ python foo.py
Dill succeeded
Traceback (most recent call last):
File "foo.py", line 7, in <module>
pickle.dumps(tf.zeros((1,1)))
TypeError: can't pickle _thread.lock objects
为什么dill可以序列化这些对象,而pickle却不能?简单的答案是 pickle
无法序列化 python 中的大多数对象,包括 thread.lock
对象。如果要序列化这些对象之一,请使用像 dill
这样的高级序列化库。至于为什么 pickle
不能,我认为它最初源于 GIL 的实现和 frame
对象渲染一些对象不可序列化,因此没有驱动来序列化语言中的所有内容。一直有关于所有 python 对象序列化引起的安全问题的讨论,但我认为这是转移注意力的问题。没有完整的语言序列化限制了在并行计算中运行的能力,因此希望 pickle
将学习 dill
如何序列化更多对象。
我发现我无法重现 eqzx's 脚本的输出并且 dill
和 pickle
的序列化都失败了。
虽然这个问题已经有好几年了,但我认为问题不在于 pickle,而在于 tensorflow 1.x 中的张量没有立即求值。当他们的图表被执行时,他们会被评估。 (在 tensorflow 2.0 中,eager execution 是默认启用的,所以你真的不必处理这个范例)。
使用 tf.enable_eager_execution()
或在 tf.Session()
上下文中评估张量
以下脚本在使用 Pickle 或 Dill 时不会抛出错误:
import tensorflow as tf
tf.enable_eager_execution()
import pickle
# import dill
n = tf.zeros((1,1))
pickle.dumps(n)
# dill.dumps(n)
print('Success')
使用 Session.run() 的相同脚本不会引发错误:
import tensorflow as tf
import pickle
# import dill
with tf.Session() as sess:
n = sess.run(tf.zeros((1,1)))
pickle.dumps(n)
# dill.dumps(n)
print('Success')