快速将Keras模型转换成Tensorflow模型

由于工作需要,最近要将一个keras模型部署在c++环境下,然而keras只有python接口。如果要支持c++,需要将将Keras的.h5 模型先转换成Tensorflow的.pb模型,然后通过Tensorflow的C++接口来加载使用。

由于Keras底层本来就是调用的Tensorflow,所以整个转换过程也很简单快速。
概括起来就是冻结模型,保存参数

1.生成keras模型

可以是自己训练生成的,也可以是直接从网上下载的预训练模型。
比如VGG之类较常用模型,也可以通过keras接口直接加载预训练模型。

from keras.applications.vgg16 import VGG16
keras_model = VGG16(weights='imagenet',input_shape=(224, 224, 3),pooling='max',include_top=False)
keras_model .save('./vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')

2.冻结Keras模型

from keras.models import load_model
from keras import backend as K

def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
    from tensorflow.python.framework.graph_util import convert_variables_to_constants
    graph = session.graph
    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(session, input_graph_def,
                                                      output_names, freeze_var_names)
        return frozen_graph

3.保存Tensorflow模型

import tensorflow as tf
from tensorflow.python.framework import graph_io

#设置路径
h5_model_path='./vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
pb_model_name='vgg16_weights_tf_dim_ordering_tf_kernels_notop.pb'

#加载keras模型
K.set_learning_phase(0)
net_model = load_model(h5_model_path)
 
print('input is :', net_model.input.name)
print ('output is:', net_model.output.name)

#冻结并保存为Tensorflow模型
sess = K.get_session()
frozen_graph = freeze_session(K.get_session(), output_names=[net_model.output.op.name])
graph_io.write_graph(frozen_graph, output_path, pb_model_name, as_text=False)

4.模型验证

模型转换完成后,我们需要确认模型转换是否正确。
验证方案:读取一张图片,按输入尺寸缩放后,验证VGG模型提取的特征是否一致。

(1)用Keras模型预测

# 读取文件*
img = cv2.imread("11.jpg")
img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_NEAREST)
img = np.asarray(img, 'f')
img = np.expand_dims(img, axis=0)

*# 导入模型*,也可以loadmodel本地模型
keras_VGG = VGG16(weights='imagenet',input_shape=(224, 224, 3),pooling='max',include_top=False)

*# 预测向量*
feature = keras_VGG.predict(img)
print(feature)

(2)用Tensorflow模型预测

import numpy as np
from keras.applications.vgg16 import VGG16
import tensorflow as tf
import cv2

*# 读取文件*
img = cv2.imread("11.jpg")
img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_NEAREST)
img = np.asarray(img, 'f')
img = np.expand_dims(img, axis=0)

with tf.Graph().as_default():
    output_graph_def = tf.GraphDef()

*# 打开.pb模型*
with open("vgg16_weights_tf_dim_ordering_tf_kernels_notop.pb", "rb") as f:
    output_graph_def.ParseFromString(f.read())
    tensors = tf.import_graph_def(output_graph_def, name="")
    print("tensors:", tensors)

*#建立会话执行预测*
with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)

    op = sess.graph.get_operations()

    input_x = sess.graph.get_tensor_by_name("input_1:0")  # 具体名称看上一段代码的input.name
    print("input_X:", input_x)

    out_softmax = sess.graph.get_tensor_by_name("global_max_pooling2d_1/Max:0")  # 具体名称看上一段代码的output.name
    print("Output:", out_softmax)

    feature = sess.run(out_softmax, feed_dict={input_x: np.reshape(img, (1, 224, 224, 3))})
    print(feature)

执行后可以看到,输入相同的情况下,他们的输出结果都是一样的,从而可以证明,模型转换是正确的。具体数据我就不贴出来了,可自行测试。

你可能感兴趣的:(人工智能,tensorflow,python,keras,深度学习)