python - 如何将 keras 模型转换为 Protocol Buffer (.pb) 文件?

标签 python tensorflow keras protocol-buffers

我有一个训练有素的 keras 模型,我想将其保存到 Protocol Buffer (.pb) 文件中。当我这样做并加载模型时,预测是错误的(并且与原始模型不同)并且权重是错误的。这是模型类型:

type(model)
> keras.engine.training.Model

这是我用来卡住并将其保存到 .pb 文件的代码。

from keras import backend as K
K.set_learning_phase(0)
import tensorflow as tf
from tensorflow.python.framework.graph_util import convert_variables_to_constants
keras_session = K.get_session()
graph = keras_session.graph
graph.as_default()
keep_var_names=None
output_names=[out.op.name for out in model.outputs]
clear_devices=True
with graph.as_default():
    freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
    output_names = output_names or []
    output_names += [v.op.name for v in tf.global_variables()]
    input_graph_def = graph.as_graph_def()
    if clear_devices:
        for node in input_graph_def.node:
            node.device = ""
    frozen_graph = convert_variables_to_constants(keras_session, input_graph_def,
                                                  output_names, freeze_var_names)
tf.train.write_graph(frozen_graph, "model", "my_model.pb", as_text=False)

然后我就这样读了:

pb_file = 'my_model.pb'
with tf.gfile.GFile(pb_file, "rb") as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
    tf.import_graph_def(graph_def)
ops = graph.get_operations()
def get_outputs(feed_dict, output_tensor):
    with tf.Session() as sess:

        sess.graph.as_default()
        tf.import_graph_def(graph_def, name='')

        output_tensor_loc = sess.graph.get_tensor_by_name(output_tensor)
        out = sess.run(output_tensor_loc, feed_dict=feed_dict)

        print("Shape is ", out.shape)

        return out

然后,当我比较第一个卷积层的权重时,它们具有相同的形状(并且形状看起来正确)但权重不同。所有权重约为0:3,而在同一层的原始模型中它们约为-256:256。

get_outputs(feed_dict, 'conv1_relu/Relu:0')

上面的代码有什么问题吗?或者整个方法是错误的?我在 blog post 中看到有人使用 tf.train.Saver,我没有这样做。我需要这样做吗?如果是这样,我该如何对我的 keras.engine.training.Model 执行此操作?

最佳答案

问:上面的代码有什么问题吗?或者整个方法是错误的?

答:主要问题是 tf.train.write_graph 保存了 TensorFlow 图,但没有保存模型的权重。


问:我需要使用 tf.train.Saver 吗?如果是这样,我该如何对我的模型执行此操作?

答:是的。除了保存图形(仅当您的后续脚本未明确重新创建图形时才需要),您还应该使用 tf.train.Saver保存模型的权重:

from keras import backend as K

# ... define your model in Keras and do some work

# Add ops to save and restore all the variables.
saver = tf.train.Saver()  # setting var_list=None saves all variables

# Get TensorFlow session
sess = K.get_session()

# save the model's variables
save_path = saver.save(sess, "/tmp/model.ckpt")

调用 saver.save 也会保存一个 MetaGraphDef ,然后可以用它来恢复图形,所以你没有必要使用 tf.train .write_graph。要恢复权重,只需使用 saver.restore:

with tf.Session() as sess:
  # restore variables from disk
  saver.restore(sess, "/tmp/model.ckpt")

只要您使用 TensorFlow 后端(您仍然有 TensorFlow 图和权重),您使用 Keras 模型的事实不会改变这种方法。有关在 TensorFlow 中保存和恢复模型的更多信息,请参阅 save and restore教程。


保存 Keras 模型的替代(简洁)方法

现在,由于您使用的是 Keras 模型,使用 model.save('model_path.h5') 保存模型并按如下方式恢复它可能更方便:

from keras.models import load_model

# restore previously saved model
model = load_model('model_path.h5')

更新:从 .ckpt 文件生成单个 .pb 文件

如果要生成单个.pb 文件,请使用以前的tf.train.Saver 方法。一旦生成了 .ckpt 文件(.meta 保存图表,.data 保存权重),您就可以获得 。 pb 文件通过调用 Morgan's function freeze_graph如下:

freeze_graph('/tmp', '<Comma separated output node names>') 

引用资料:

  1. Save and restore在 TensorFlow 中。
  2. StackOverflow 对 TensorFlow saving into/loading a graph from a file 的回答.
  3. Saving/loading whole models在 Keras 中。
  4. Morgan's function.ckpt 文件生成一个 .pb 文件。

关于python - 如何将 keras 模型转换为 Protocol Buffer (.pb) 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57444171/

相关文章:

Python pickle : ImportError: No module named __main__

time-series - 使用 LSTM 和 Keras 进行时间序列预测的不同大小的预测器

python - 我可以向 KerasClassifier 发送回调吗?

python - 为 Keras ANN 选择层/函数 - 线性回归

python - 使用 Qthread 时的信号槽问题

python - 为 python setup.py 安装指定头文件位置

python - 如何从分类变量创建交互设计矩阵?

tensorflow - 如何为您训练的模型选择半精度(BFLOAT16 与 FLOAT16)?

python - 将tensorflow中的词向量导入gensim

python - 从 CNN 层获取过滤器值