keras模型保存為tensorflow的二進制模型方式
最近需要將使用keras訓練的模型移植到手機上使用, 因此需要轉(zhuǎn)換到tensorflow的二進制模型。
折騰一下午,終于找到一個合適的方法,廢話不多說,直接上代碼:
# coding=utf-8
import sys
from keras.models import load_model
import tensorflow as tf
import os
import os.path as osp
from keras import backend as K
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a prunned computation graph.
Creates a new computation graph where variable nodes are replaced by
constants taking their current value in the session. The new graph will be
prunned so subgraphs that are not neccesary to compute the requested
outputs are removed.
@param session The TensorFlow session to be frozen.
@param keep_var_names A list of variable names that should not be frozen,
or None to freeze all the variables in the graph.
@param output_names Names of the relevant graph outputs.
@param clear_devices Remove the device directives from the graph for better portability.
@return The frozen graph definition.
"""
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
input_fld = sys.path[0]
weight_file = 'your_model.h5'
output_graph_name = 'tensor_model.pb'
output_fld = input_fld + '/tensorflow_model/'
if not os.path.isdir(output_fld):
os.mkdir(output_fld)
weight_file_path = osp.join(input_fld, weight_file)
K.set_learning_phase(0)
net_model = load_model(weight_file_path)
print('input is :', net_model.input.name)
print ('output is:', net_model.output.name)
sess = K.get_session()
frozen_graph = freeze_session(K.get_session(), output_names=[net_model.output.op.name])
from tensorflow.python.framework import graph_io
graph_io.write_graph(frozen_graph, output_fld, output_graph_name, as_text=False)
print('saved the constant graph (ready for inference) at: ', osp.join(output_fld, output_graph_name))
上面代碼實現(xiàn)保存到當前目錄的tensor_model目錄下。
驗證:
import tensorflow as tf
import numpy as np
import PIL.Image as Image
import cv2
def recognize(jpg_path, pb_file_path):
with tf.Graph().as_default():
output_graph_def = tf.GraphDef()
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
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
op = sess.graph.get_operations()
for m in op:
print(m.values())
input_x = sess.graph.get_tensor_by_name("convolution2d_1_input:0") #具體名稱看上一段代碼的input.name
print input_x
out_softmax = sess.graph.get_tensor_by_name("activation_4/Softmax:0") #具體名稱看上一段代碼的output.name
print out_softmax
img = cv2.imread(jpg_path, 0)
img_out_softmax = sess.run(out_softmax,
feed_dict={input_x: 1.0 - np.array(img).reshape((-1,28, 28, 1)) / 255.0})
print "img_out_softmax:", img_out_softmax
prediction_labels = np.argmax(img_out_softmax, axis=1)
print "label:", prediction_labels
pb_path = 'tensorflow_model/constant_graph_weights.pb'
img = 'test/6/8_48.jpg'
recognize(img, pb_path)
補充知識:如何將keras訓練好的模型轉(zhuǎn)換成tensorflow的.pb的文件并在TensorFlow serving環(huán)境調(diào)用
首先keras訓練好的模型通過自帶的model.save()保存下來是 .model (.h5) 格式的文件
模型載入是通過 my_model = keras . models . load_model( filepath )
要將該模型轉(zhuǎn)換為.pb 格式的TensorFlow 模型,代碼如下:
# -*- coding: utf-8 -*-
from keras.layers.core import Activation, Dense, Flatten
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers import Dropout
from keras.layers.wrappers import Bidirectional
from keras.models import Sequential,load_model
from keras.preprocessing import sequence
from sklearn.model_selection import train_test_split
import collections
from collections import defaultdict
import jieba
import numpy as np
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import tensorflow as tf
import os
import os.path as osp
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
input_fld = '/data/codebase/Keyword-fenci/brand_recogniton_biLSTM/'
weight_file = 'biLSTM_brand_recognize.model'
output_graph_name = 'tensor_model_v3.pb'
output_fld = input_fld + '/tensorflow_model/'
if not os.path.isdir(output_fld):
os.mkdir(output_fld)
weight_file_path = osp.join(input_fld, weight_file)
K.set_learning_phase(0)
net_model = load_model(weight_file_path)
print('input is :', net_model.input.name)
print ('output is:', net_model.output.name)
sess = K.get_session()
frozen_graph = freeze_session(K.get_session(), output_names=[net_model.output.op.name])
from tensorflow.python.framework import graph_io
graph_io.write_graph(frozen_graph, output_fld, output_graph_name, as_text=True)
print('saved the constant graph (ready for inference) at: ', osp.join(output_fld, output_graph_name))
然后模型就存成了.pb格式的文件
問題就來了,這樣存下來的.pb格式的文件是frozen model
如果通過TensorFlow serving 啟用模型的話,會報錯:
E tensorflow_serving/core/aspired_versions_manager.cc:358] Servable {name: mnist version: 1} cannot be loaded: Not found: Could not find meta graph def matching supplied tags: { serve }. To inspect available tag-sets in the SavedModel, please use the SavedModel CLI: `saved_model_cli`
因為TensorFlow serving 希望讀取的是saved model
于是需要將frozen model 轉(zhuǎn)化為 saved model 格式,解決方案如下:
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
export_dir = '/data/codebase/Keyword-fenci/brand_recogniton_biLSTM/saved_model'
graph_pb = '/data/codebase/Keyword-fenci/brand_recogniton_biLSTM/tensorflow_model/tensor_model.pb'
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
with tf.gfile.GFile(graph_pb, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sigs = {}
with tf.Session(graph=tf.Graph()) as sess:
# name="" is important to ensure we don't get spurious prefixing
tf.import_graph_def(graph_def, name="")
g = tf.get_default_graph()
inp = g.get_tensor_by_name(net_model.input.name)
out = g.get_tensor_by_name(net_model.output.name)
sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
tf.saved_model.signature_def_utils.predict_signature_def(
{"in": inp}, {"out": out})
builder.add_meta_graph_and_variables(sess,
[tag_constants.SERVING],
signature_def_map=sigs)
builder.save()
于是保存下來的saved model 文件夾下就有兩個文件:
saved_model.pb variables
其中variables 可以為空
于是將.pb 模型導入serving再讀取,成功!
以上這篇keras模型保存為tensorflow的二進制模型方式就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
python3.6、opencv安裝環(huán)境搭建過程(圖文教程)
這篇文章主要介紹了python3.6、opencv安裝環(huán)境搭建,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11
Pytorch使用VGG16模型進行預(yù)測貓狗二分類實戰(zhàn)
VGG16是Visual Geometry Group的縮寫,它的名字來源于提出該網(wǎng)絡(luò)的實驗室,本文我們將使用PyTorch來實現(xiàn)VGG16網(wǎng)絡(luò),用于貓狗預(yù)測的二分類任務(wù),我們將對VGG16的網(wǎng)絡(luò)結(jié)構(gòu)進行適當?shù)男薷?以適應(yīng)我們的任務(wù),需要的朋友可以參考下2023-08-08
使用Python中的greenlet包實現(xiàn)并發(fā)編程的入門教程
這篇文章主要介紹了使用Python中的greenlet包實現(xiàn)并發(fā)編程的入門教程,Python由于GIL的存在并不能實現(xiàn)真正的多線程并發(fā),greenlet可以做到一個相對的替換方案,需要的朋友可以參考下2015-04-04
解決pycharm運行出錯,代碼正確結(jié)果不顯示的問題
今天小編就為大家分享一篇解決pycharm運行出錯,代碼正確結(jié)果不顯示的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11

