【发布时间】:2020-04-17 15:10:15
【问题描述】:
我有一个旧的训练过的 tf1.x 模型(让它成为 Model1),由占位符、tf.contrib 等构建。我可以通过从 tf.Session(在 tf1.x 中)中的 .ckpt 检查点恢复图形来使用此模型。 我解决了使用 Model1 的最简单方法是导出它:
# tf1.x code
tf.saved_model.simple_save(sess, saved_Model1_path,
inputs={'input':'Placeholder:0'}, outputs={'output':'.../Sigmoid:0'})
即使在tf2.0中我也可以使用获得的saved_model.pb:
# tf2.0 code
Model1 = tf.saved_model.load(saved_Model1_path)
out = Model1.signatures['serving_default'](tf.convert_to_tensor(data))['output'].numpy()
out = Model1.signatures['serving_default'].prune('Placeholder:0', '.../Sigmoid:0')(data)
out = Model1.prune('Placeholder:0', '.../Sigmoid:0')(data)
现在想象一下,我有一个用 tf2.0 tf.function 编写的前/后处理。
我希望 preprocessing -> Model1-> postprocessing 的构造能够导出到 tf2.0 中的单个 saved_model.pb 中。 由于 Model1 的 saved_model.pb 使用了 tf.Placeholders,问题就来了(像这样,我不是这里的专家)。
同时,我可以轻松地从其他 tf2.0 导出的模型构建 saved_model.pb:
import os
import tensorflow as tf
assert tf.__version__[0] == '2'
class M1(tf.Module):
def __init__(self):
super(M1, self).__init__()
self.v = tf.Variable(2.)
@tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
def M1_func(self, x):
return x * self.v
# build some saved_model.pb
m1 = M1()
path_1 = './save1'
path_to_save = os.path.realpath(path_1)
tf.saved_model.save(m1, path_to_save)
# load built saved_model.pb and check it works
m1 = tf.saved_model.load(path_1)
assert 6 == m1.M1_func(3.).numpy()
# build other saved_model.pb using first saved_model.pb as a part of computing graph
class M2(tf.Module):
def __init__(self):
super(M2, self).__init__()
self.run = m1
self.v = tf.Variable(3.)
@tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
def M2_func(self, x):
return self.run.M1_func(x) * self.v
m2 = M2()
path_2 = './save2'
path_to_save = os.path.realpath(path_2)
tf.saved_model.save(m2, path_to_save)
m2 = tf.saved_model.load(path_2)
assert 18 == m2.M2_func(3.).numpy()
但是当我尝试做同样的事情时,除了将第一个 saved_model.pb 从 tf2.0 保存到 tf1.x 保存替换之外,它不起作用:
# save first saved_model.pb with tf1.x
import tensorflow as tf
assert tf.__version__[0] == '1'
inp = tf.placeholder(shape=[],dtype=tf.float32)
a = tf.Variable(1.5)
out = a*inp
sess = tf.Session()
sess.run(tf.global_variables_initializer())
assert 7.5 == out.eval({inp:5.}, sess)
path_3 = './save3'
path_to_save = os.path.realpath(path_3)
tf.saved_model.simple_save(sess, path_to_save, inputs={'input': inp}, outputs={'output': out})
现在切换到 tf2.0 并尝试使用第一个作为计算图的一部分构建新的 saved_model.pb:
import os
import tensorflow as tf
assert tf.__version__[0] == '2'
path_3 = './save3'
path_to_save = os.path.realpath(path_3)
m1 = tf.saved_model.load(path_to_save)
class M2(tf.Module):
def __init__(self):
super(M2, self).__init__()
self.run = m1.signatures['serving_default'].prune('Placeholder:0', 'mul:0')
self.v = tf.Variable(3.)
@tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
def M2_func(self, x):
return self.run(x) * self.v
m2 = M2()
assert 22.5 == m2.M2_func(5.) # ofc eager execution works
# now save M2 to saved_model.pb and check it works (it does not)
path_4 = './save4'
path_to_save = os.path.realpath(path_4)
tf.saved_model.save(m2, path_to_save)
m2 = tf.saved_model.load(path_4)
m2.M2_func(5.) # error:
tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value StatefulPartitionedCall/StatefulPartitionedCall/Variable
[[{{node StatefulPartitionedCall/StatefulPartitionedCall/Variable/read}}]] [Op:__inference_restored_function_body_207]
Function call stack:
restored_function_body
所以问题是:如何将这个架构保存在 tf2.0 中的单个 saved_model.pb 中
预处理(tf2.0 @tf.function)->Model1(在tf1.x中创建的saved_model.pb)->后处理 (tf2.0 @tf.function)
【问题讨论】:
标签: python tensorflow deep-learning protocol-buffers tensorflow2.0