keras由于其易于上手的特性,广受研究人员的好评。
但是Keras本身没有C++接口,而一般的生产环境都需要C++环境支持。所以能够在C++上部属深度学习模型至关重要。
所以我们需要将hdf5模型转化成tensorflow的 pb模型才可以运用到visual studio 2015中。
本文主要分三个步骤,采用环境为jupter notebook:
1,保存训练好的keras的hdf5模型
2,用keras进行hdf5模型的读取,并输入一个样本进行测试
3,hdf5模型 转成 tensorflow pb模型
4,输入一个样本 测试pb模型,和hdf5模型的输出进行比较
步骤1:保存训练好的keras的hdf5模型
主要参考
Keras框架下的保存模型和加载模型_人工智能_tszupup的博客-CSDN博客
https://blog.csdn.net/tszupup/article/details/85198949
我采用的代码是:
# 保存最好的模型
filepath="weights.best.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True,
mode='max')
callbacks_list = [checkpoint]
history = DD_Net.fit([X_0,X_1],Y,
batch_size=len(Y),
epochs=500,
verbose=True,
shuffle=True,
callbacks=callbacks_list,
validation_data=([X_test_0,X_test_1],Y_test)
)
步骤2:用keras进行hdf5模型的读取,并输入一个样本进行测试
#加载整个模型
DD_Net = load_model('weights.best.hdf5')
我这里直接读取HDF5文件会报错,NameError: name 'poses_diff' is not defined,原因是没有将函数poses_diff()输入给模型,模型在数据处理上有些步骤缺失了,正确代码应该是
# 加载整个模型
DD_Net = load_model('weights.best.hdf5',custom_objects={'poses_diff': poses_diff})
输入一个样本进行测试
#输入一个样本的数据,我这里处理过后的一个样本数据格式是([X_0,X_1],大家要根据自己的实际修改
print(DD_Net.predict([X_0,X_1]))
print(np.argmax(DD_Net.predict([X_0,X_1])))
结果:
大家要记住这个输出,方便和后面pb模型的输出结果进行比较,如果一致的话就证明成功。
步骤3:hdf5模型 转成 tensorflow pb模型
from keras.models import load_model
import tensorflow as tf
from keras import backend as K
from tensorflow.python.framework import graph_io
#from keras.models import TripletModel
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
"""----------------------------------配置路径-----------------------------------"""
h5_model_path='.\\JHMDB\\weights.best.hdf5'#Keras训练模型
output_path='.\\JHMDB/'#转换后pb模型的地址
pb_model_name='pb_model.pb'#转换后pb模型的文件名
"""----------------------------------导入keras模型------------------------------"""
K.set_learning_phase(0)
net_model = load_model(h5_model_path,custom_objects={'poses_diff': poses_diff})
#print('input is :', net_model.input.name)
#print ('output is:', net_model.output.name)
"""----------------------------------保存为.pb格式------------------------------"""
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,输入一个样本 测试pb模型,和hdf5模型的输出进行比较
这里我也是搞了很久,主要原因是因为没接触过tensorflow ,搞不懂tensorflow的输入输出。简单来说,直接套用下面的这个识别函数,我是根据几个博主的代码改过来的,原出处忘记了,在此对他们表示感谢。
只需要修改sess.run(outputVec,feed_dict)。
我的理解是feed_dict作为输入数据,outputVec作为输出数据
"""-----------------------------------------------定义识别函数-----------------------------------------"""
def recognize( pb_file_path):
with tf.Graph().as_default():
output_graph_def = tf.GraphDef()
# 打开.pb模型
with open(pb_file_path, "rb") as f:
output_graph_def.ParseFromString(f.read())
tensors = tf.import_graph_def(output_graph_def, name="")
print("tensors:",tensors)
# 在一个session中去run一个前向
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
op = sess.graph.get_operations()
'''
# 打印图中有的操作
for i,m in enumerate(op):
print('op{}:'.format(i),m.values())
'''
outputVec = sess.graph.get_tensor_by_name('dense_1_1/Softmax:0')#名称要和模型里名称一致
X0 = sess.graph.get_tensor_by_name('M_1:0')
X1 = sess.graph.get_tensor_by_name('P_1:0')
feed_dict = {X0:X_0 , X1:X_1}
img_out_softmax = sess.run(outputVec,feed_dict)
print("img_out_softmax:", img_out_softmax)
print(np.argmax(img_out_softmax))
pb_path = 'C:\\Users\\Administrator\\DD-Net-master\\JHMDB\\pb_model.pb'
recognize(pb_path)
但是tensorflow里面,还要你知道这些输入数据是在模型的哪个地方输入的,要把这个地方的“名字”写上去,他才明白。(感觉好麻烦)
あの人は谁?忘れたくない人、忘れたくなかた人、忘れちゃダメな人、君の名前…
那我们怎么获得模型的名字呢
#获取节点名称
import tensorflow as tf
import os
model_name = 'C:\\Users\\Administrator\\DD-Net-master\\JHMDB\\pb_model.pb'
def create_graph():
with tf.gfile.FastGFile(model_name, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
create_graph()
tensor_name_list = [tensor.name for tensor in tf.get_default_graph().as_graph_def().node]
for tensor_name in tensor_name_list:
print(tensor_name,'\n')
我这里的输入节点名字是M_1,P_1,至此我们就获得了输入节点的名字,输出节点同理找一下可得名字:dense_1_1/Softmax,注意名字后面要加 “ :0 ”,要求你要对你的模型比较熟悉。
名字写好后进行测试。
获得结果:和HDF5模型输出一致,成功!
最后,我永远喜欢宫水三叶.jpg