How to export Keras .h5 to tensorflow .pb?
up vote
18
down vote
favorite
I have fine-tuned inception model with a new dataset and saved it as ".h5" model in Keras. now my goal is to run my model on android Tensorflow which accepts ".pb" extension only. question is that is there any library in Keras or tensorflow to do this conversion? I have seen this post so far : https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html but can't figure out yet.
python tensorflow keras
add a comment |
up vote
18
down vote
favorite
I have fine-tuned inception model with a new dataset and saved it as ".h5" model in Keras. now my goal is to run my model on android Tensorflow which accepts ".pb" extension only. question is that is there any library in Keras or tensorflow to do this conversion? I have seen this post so far : https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html but can't figure out yet.
python tensorflow keras
add a comment |
up vote
18
down vote
favorite
up vote
18
down vote
favorite
I have fine-tuned inception model with a new dataset and saved it as ".h5" model in Keras. now my goal is to run my model on android Tensorflow which accepts ".pb" extension only. question is that is there any library in Keras or tensorflow to do this conversion? I have seen this post so far : https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html but can't figure out yet.
python tensorflow keras
I have fine-tuned inception model with a new dataset and saved it as ".h5" model in Keras. now my goal is to run my model on android Tensorflow which accepts ".pb" extension only. question is that is there any library in Keras or tensorflow to do this conversion? I have seen this post so far : https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html but can't figure out yet.
python tensorflow keras
python tensorflow keras
edited Sep 26 at 15:05
jdehesa
22.1k43150
22.1k43150
asked Aug 2 '17 at 16:16
Solix
3011313
3011313
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
up vote
33
down vote
accepted
Keras does not include by itself any means to export a TensorFlow graph as a protocol buffers file, but you can do it using regular TensorFlow utilities. Here is a blog post explaining how to do it using the utility script freeze_graph.py
included in TensorFlow, which is the "typical" way it is done.
However, I personally find a nuisance having to make a checkpoint and then run an external script to obtain a model, and instead prefer to do it from my own Python code, so I use a function like this:
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
Which is inspired in the implementation of freeze_graph.py
. The parameters are similar to the script too. session
is the TensorFlow session object. keep_var_names
is only needed if you want to keep some variable not frozen (e.g. for stateful models), so generally not. output_names
is a list with the names of the operations that produce the outputs that you want. clear_devices
just removes any device directives to make the graph more portable. So, for a typical Keras model
with one output, you would do something like:
from keras import backend as K
# Create, compile and train model...
frozen_graph = freeze_session(K.get_session(),
output_names=[out.op.name for out in model.outputs])
Then you can write the graph to a file as usual with tf.train.write_graph
:
tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)
– jdehesa
Mar 29 at 13:05
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based onconvert_variables_to_constants
(which "freezes" the variables and prunes the graph).
– jdehesa
Dec 7 at 12:46
|
show 4 more comments
up vote
15
down vote
The freeze_session method works fine. But compared to saving to a checkpoint file then using the freeze_graph tool that comes with TensorFlow seems simpler to me, as it's easier to maintain. All you need to do is the following two steps:
First, add after your Keras code model.fit(...)
and train your model:
from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')
Then cd to your TensorFlow root directory, run:
python tensorflow/python/tools/freeze_graph.py
--input_meta_graph=/tmp/keras_model.ckpt.meta
--input_checkpoint=/tmp/keras_model.ckpt
--output_graph=/tmp/keras_frozen.pb
--output_node_names="<output_node_name_printed_in_step_1>"
--input_binary=true
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the errorKeras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.
– Tahlil
May 2 at 6:58
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
add a comment |
up vote
1
down vote
The following simple example (XOR example) shows how to export Keras models (in both h5
format and pb
format), and using the model in Python and C++:
train.py:
import numpy as np
import tensorflow as tf
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])
model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)
# inputs: ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])
# outputs: ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])
model.save('./xor.h5')
frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)
predict.py:
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model('./xor.h5')
# 0 ^ 0 = [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))
# 0 ^ 1 = [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))
# 1 ^ 0 = [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))
# 1 ^ 1 = [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))
opencv-predict.py:
import numpy as np
import cv2 as cv
model = cv.dnn.readNetFromTensorflow('./xor.pb')
# 0 ^ 0 = [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 0 ^ 1 = [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 0 = [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 1 = [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
predict.cpp:
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
cv::dnn::Net net;
net = cv::dnn::readNetFromTensorflow("./xor.pb");
// 0 ^ 0 = [0.018541215]
float x0 = { 0, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 0 ^ 1 = [0.98295897]
float x1 = { 0, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 0 = [0.98810625]
float x2 = { 1, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 1 = [0.010002014]
float x3 = { 1, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
return EXIT_SUCCESS;
}
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
add a comment |
up vote
0
down vote
If you want the model only for inference, you should first freeze the graph and then write it as a .pb
file. The code snippet looks like this (code borrowed from here):
import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K
sess = K.get_session()
constant_graph = graph_util.convert_variables_to_constants(
sess,
sess.graph.as_graph_def(),
["name_of_the_output_graph_node"])
graph_io.write_graph(constant_graph, "path/to/output/folder",
"output_model_name", as_text=False)
You can do the above using the keras_to_tensorflow tool: https://github.com/amir-abdi/keras_to_tensorflow
The keras_to_tensorflow tool takes care of the above operations, with some extra features for a more diverse solution. Just call it with the correct input arguments (e.g. input_model
and output_model
flags).
If you want to retrain the model in tensorflow, use the above tool with the output_meta_ckpt
flag to export checkpoints and meta graphs.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45466020%2fhow-to-export-keras-h5-to-tensorflow-pb%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
33
down vote
accepted
Keras does not include by itself any means to export a TensorFlow graph as a protocol buffers file, but you can do it using regular TensorFlow utilities. Here is a blog post explaining how to do it using the utility script freeze_graph.py
included in TensorFlow, which is the "typical" way it is done.
However, I personally find a nuisance having to make a checkpoint and then run an external script to obtain a model, and instead prefer to do it from my own Python code, so I use a function like this:
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
Which is inspired in the implementation of freeze_graph.py
. The parameters are similar to the script too. session
is the TensorFlow session object. keep_var_names
is only needed if you want to keep some variable not frozen (e.g. for stateful models), so generally not. output_names
is a list with the names of the operations that produce the outputs that you want. clear_devices
just removes any device directives to make the graph more portable. So, for a typical Keras model
with one output, you would do something like:
from keras import backend as K
# Create, compile and train model...
frozen_graph = freeze_session(K.get_session(),
output_names=[out.op.name for out in model.outputs])
Then you can write the graph to a file as usual with tf.train.write_graph
:
tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)
– jdehesa
Mar 29 at 13:05
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based onconvert_variables_to_constants
(which "freezes" the variables and prunes the graph).
– jdehesa
Dec 7 at 12:46
|
show 4 more comments
up vote
33
down vote
accepted
Keras does not include by itself any means to export a TensorFlow graph as a protocol buffers file, but you can do it using regular TensorFlow utilities. Here is a blog post explaining how to do it using the utility script freeze_graph.py
included in TensorFlow, which is the "typical" way it is done.
However, I personally find a nuisance having to make a checkpoint and then run an external script to obtain a model, and instead prefer to do it from my own Python code, so I use a function like this:
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
Which is inspired in the implementation of freeze_graph.py
. The parameters are similar to the script too. session
is the TensorFlow session object. keep_var_names
is only needed if you want to keep some variable not frozen (e.g. for stateful models), so generally not. output_names
is a list with the names of the operations that produce the outputs that you want. clear_devices
just removes any device directives to make the graph more portable. So, for a typical Keras model
with one output, you would do something like:
from keras import backend as K
# Create, compile and train model...
frozen_graph = freeze_session(K.get_session(),
output_names=[out.op.name for out in model.outputs])
Then you can write the graph to a file as usual with tf.train.write_graph
:
tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)
– jdehesa
Mar 29 at 13:05
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based onconvert_variables_to_constants
(which "freezes" the variables and prunes the graph).
– jdehesa
Dec 7 at 12:46
|
show 4 more comments
up vote
33
down vote
accepted
up vote
33
down vote
accepted
Keras does not include by itself any means to export a TensorFlow graph as a protocol buffers file, but you can do it using regular TensorFlow utilities. Here is a blog post explaining how to do it using the utility script freeze_graph.py
included in TensorFlow, which is the "typical" way it is done.
However, I personally find a nuisance having to make a checkpoint and then run an external script to obtain a model, and instead prefer to do it from my own Python code, so I use a function like this:
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
Which is inspired in the implementation of freeze_graph.py
. The parameters are similar to the script too. session
is the TensorFlow session object. keep_var_names
is only needed if you want to keep some variable not frozen (e.g. for stateful models), so generally not. output_names
is a list with the names of the operations that produce the outputs that you want. clear_devices
just removes any device directives to make the graph more portable. So, for a typical Keras model
with one output, you would do something like:
from keras import backend as K
# Create, compile and train model...
frozen_graph = freeze_session(K.get_session(),
output_names=[out.op.name for out in model.outputs])
Then you can write the graph to a file as usual with tf.train.write_graph
:
tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)
Keras does not include by itself any means to export a TensorFlow graph as a protocol buffers file, but you can do it using regular TensorFlow utilities. Here is a blog post explaining how to do it using the utility script freeze_graph.py
included in TensorFlow, which is the "typical" way it is done.
However, I personally find a nuisance having to make a checkpoint and then run an external script to obtain a model, and instead prefer to do it from my own Python code, so I use a function like this:
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
Which is inspired in the implementation of freeze_graph.py
. The parameters are similar to the script too. session
is the TensorFlow session object. keep_var_names
is only needed if you want to keep some variable not frozen (e.g. for stateful models), so generally not. output_names
is a list with the names of the operations that produce the outputs that you want. clear_devices
just removes any device directives to make the graph more portable. So, for a typical Keras model
with one output, you would do something like:
from keras import backend as K
# Create, compile and train model...
frozen_graph = freeze_session(K.get_session(),
output_names=[out.op.name for out in model.outputs])
Then you can write the graph to a file as usual with tf.train.write_graph
:
tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)
edited Nov 13 at 11:37
answered Aug 2 '17 at 16:33
jdehesa
22.1k43150
22.1k43150
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)
– jdehesa
Mar 29 at 13:05
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based onconvert_variables_to_constants
(which "freezes" the variables and prunes the graph).
– jdehesa
Dec 7 at 12:46
|
show 4 more comments
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)
– jdehesa
Mar 29 at 13:05
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based onconvert_variables_to_constants
(which "freezes" the variables and prunes the graph).
– jdehesa
Dec 7 at 12:46
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
That seems to work with me. However, the output .pb file does not have the same input node names. Is that right? The input node name was input_1 but after freezing, I do not know the new name. Can you tell me what the new name would be?
– Maged Saeed
Mar 26 at 0:35
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
I am getting an error in model.output.op.name. Can you please tell how to resolve this?
– Pawandeep Singh
Mar 29 at 12:58
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@MagedSaeed Graph node names shouldn't change, but sometimes with Keras it is hard to tell what name exactly has it given to particular objects (placeholders, predictions, etc). Visualizing the graph in TensorBoard can help.
– jdehesa
Mar 29 at 13:04
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try
[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)– jdehesa
Mar 29 at 13:05
@PawandeepSingh What error are you getting? Maybe you have multiple outputs? (in that case try
[out.op.name for out in model.outputs]
- actually I'm changing that in the answer since it's more general)– jdehesa
Mar 29 at 13:05
1
1
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based on
convert_variables_to_constants
(which "freezes" the variables and prunes the graph).– jdehesa
Dec 7 at 12:46
@gebbissimo Well, this "prunes" the graph so only the operations and variables that you need to compute the given outputs are actually exported (so training-related variables should not get exported unless you actually request training operations). But yes, the post you linked is another valid solution, and in fact is pretty much equivalent, since both are based on
convert_variables_to_constants
(which "freezes" the variables and prunes the graph).– jdehesa
Dec 7 at 12:46
|
show 4 more comments
up vote
15
down vote
The freeze_session method works fine. But compared to saving to a checkpoint file then using the freeze_graph tool that comes with TensorFlow seems simpler to me, as it's easier to maintain. All you need to do is the following two steps:
First, add after your Keras code model.fit(...)
and train your model:
from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')
Then cd to your TensorFlow root directory, run:
python tensorflow/python/tools/freeze_graph.py
--input_meta_graph=/tmp/keras_model.ckpt.meta
--input_checkpoint=/tmp/keras_model.ckpt
--output_graph=/tmp/keras_frozen.pb
--output_node_names="<output_node_name_printed_in_step_1>"
--input_binary=true
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the errorKeras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.
– Tahlil
May 2 at 6:58
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
add a comment |
up vote
15
down vote
The freeze_session method works fine. But compared to saving to a checkpoint file then using the freeze_graph tool that comes with TensorFlow seems simpler to me, as it's easier to maintain. All you need to do is the following two steps:
First, add after your Keras code model.fit(...)
and train your model:
from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')
Then cd to your TensorFlow root directory, run:
python tensorflow/python/tools/freeze_graph.py
--input_meta_graph=/tmp/keras_model.ckpt.meta
--input_checkpoint=/tmp/keras_model.ckpt
--output_graph=/tmp/keras_frozen.pb
--output_node_names="<output_node_name_printed_in_step_1>"
--input_binary=true
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the errorKeras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.
– Tahlil
May 2 at 6:58
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
add a comment |
up vote
15
down vote
up vote
15
down vote
The freeze_session method works fine. But compared to saving to a checkpoint file then using the freeze_graph tool that comes with TensorFlow seems simpler to me, as it's easier to maintain. All you need to do is the following two steps:
First, add after your Keras code model.fit(...)
and train your model:
from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')
Then cd to your TensorFlow root directory, run:
python tensorflow/python/tools/freeze_graph.py
--input_meta_graph=/tmp/keras_model.ckpt.meta
--input_checkpoint=/tmp/keras_model.ckpt
--output_graph=/tmp/keras_frozen.pb
--output_node_names="<output_node_name_printed_in_step_1>"
--input_binary=true
The freeze_session method works fine. But compared to saving to a checkpoint file then using the freeze_graph tool that comes with TensorFlow seems simpler to me, as it's easier to maintain. All you need to do is the following two steps:
First, add after your Keras code model.fit(...)
and train your model:
from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')
Then cd to your TensorFlow root directory, run:
python tensorflow/python/tools/freeze_graph.py
--input_meta_graph=/tmp/keras_model.ckpt.meta
--input_checkpoint=/tmp/keras_model.ckpt
--output_graph=/tmp/keras_frozen.pb
--output_node_names="<output_node_name_printed_in_step_1>"
--input_binary=true
answered Feb 22 at 6:19
Jeff Tang
1,5391116
1,5391116
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the errorKeras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.
– Tahlil
May 2 at 6:58
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
add a comment |
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the errorKeras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.
– Tahlil
May 2 at 6:58
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
1
1
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the error
Keras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.– Tahlil
May 2 at 6:58
I had to set K.set_learning_phase(0) before saving the checkpoint. Otherwise I faced the error
Keras error “You must feed a value for placeholder tensor 'keras_learning_phase' with dtype bool”
while running it on android. I set 0 because I only need the model for inference.– Tahlil
May 2 at 6:58
2
2
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
K.set_learning_phase must be called before loading the model.
– Tahlil
May 2 at 8:09
add a comment |
up vote
1
down vote
The following simple example (XOR example) shows how to export Keras models (in both h5
format and pb
format), and using the model in Python and C++:
train.py:
import numpy as np
import tensorflow as tf
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])
model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)
# inputs: ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])
# outputs: ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])
model.save('./xor.h5')
frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)
predict.py:
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model('./xor.h5')
# 0 ^ 0 = [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))
# 0 ^ 1 = [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))
# 1 ^ 0 = [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))
# 1 ^ 1 = [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))
opencv-predict.py:
import numpy as np
import cv2 as cv
model = cv.dnn.readNetFromTensorflow('./xor.pb')
# 0 ^ 0 = [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 0 ^ 1 = [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 0 = [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 1 = [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
predict.cpp:
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
cv::dnn::Net net;
net = cv::dnn::readNetFromTensorflow("./xor.pb");
// 0 ^ 0 = [0.018541215]
float x0 = { 0, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 0 ^ 1 = [0.98295897]
float x1 = { 0, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 0 = [0.98810625]
float x2 = { 1, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 1 = [0.010002014]
float x3 = { 1, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
return EXIT_SUCCESS;
}
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
add a comment |
up vote
1
down vote
The following simple example (XOR example) shows how to export Keras models (in both h5
format and pb
format), and using the model in Python and C++:
train.py:
import numpy as np
import tensorflow as tf
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])
model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)
# inputs: ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])
# outputs: ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])
model.save('./xor.h5')
frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)
predict.py:
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model('./xor.h5')
# 0 ^ 0 = [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))
# 0 ^ 1 = [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))
# 1 ^ 0 = [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))
# 1 ^ 1 = [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))
opencv-predict.py:
import numpy as np
import cv2 as cv
model = cv.dnn.readNetFromTensorflow('./xor.pb')
# 0 ^ 0 = [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 0 ^ 1 = [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 0 = [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 1 = [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
predict.cpp:
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
cv::dnn::Net net;
net = cv::dnn::readNetFromTensorflow("./xor.pb");
// 0 ^ 0 = [0.018541215]
float x0 = { 0, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 0 ^ 1 = [0.98295897]
float x1 = { 0, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 0 = [0.98810625]
float x2 = { 1, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 1 = [0.010002014]
float x3 = { 1, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
return EXIT_SUCCESS;
}
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
add a comment |
up vote
1
down vote
up vote
1
down vote
The following simple example (XOR example) shows how to export Keras models (in both h5
format and pb
format), and using the model in Python and C++:
train.py:
import numpy as np
import tensorflow as tf
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])
model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)
# inputs: ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])
# outputs: ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])
model.save('./xor.h5')
frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)
predict.py:
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model('./xor.h5')
# 0 ^ 0 = [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))
# 0 ^ 1 = [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))
# 1 ^ 0 = [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))
# 1 ^ 1 = [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))
opencv-predict.py:
import numpy as np
import cv2 as cv
model = cv.dnn.readNetFromTensorflow('./xor.pb')
# 0 ^ 0 = [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 0 ^ 1 = [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 0 = [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 1 = [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
predict.cpp:
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
cv::dnn::Net net;
net = cv::dnn::readNetFromTensorflow("./xor.pb");
// 0 ^ 0 = [0.018541215]
float x0 = { 0, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 0 ^ 1 = [0.98295897]
float x1 = { 0, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 0 = [0.98810625]
float x2 = { 1, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 1 = [0.010002014]
float x3 = { 1, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
return EXIT_SUCCESS;
}
The following simple example (XOR example) shows how to export Keras models (in both h5
format and pb
format), and using the model in Python and C++:
train.py:
import numpy as np
import tensorflow as tf
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
"""
Freezes the state of a session into a pruned 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
pruned so subgraphs that are not necessary 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.
"""
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 = tf.graph_util.convert_variables_to_constants(
session, input_graph_def, output_names, freeze_var_names)
return frozen_graph
X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])
model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)
# inputs: ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])
# outputs: ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])
model.save('./xor.h5')
frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)
predict.py:
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model('./xor.h5')
# 0 ^ 0 = [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))
# 0 ^ 1 = [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))
# 1 ^ 0 = [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))
# 1 ^ 1 = [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))
opencv-predict.py:
import numpy as np
import cv2 as cv
model = cv.dnn.readNetFromTensorflow('./xor.pb')
# 0 ^ 0 = [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 0 ^ 1 = [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 0 = [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))
# 1 ^ 1 = [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))
predict.cpp:
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
cv::dnn::Net net;
net = cv::dnn::readNetFromTensorflow("./xor.pb");
// 0 ^ 0 = [0.018541215]
float x0 = { 0, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 0 ^ 1 = [0.98295897]
float x1 = { 0, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 0 = [0.98810625]
float x2 = { 1, 0 };
net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;
// 1 ^ 1 = [0.010002014]
float x3 = { 1, 1 };
net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;
return EXIT_SUCCESS;
}
answered Nov 20 at 4:37
Amir Saniyan
5,1601161101
5,1601161101
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
add a comment |
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
Thank you very much for a complete example. Could I ask you to include an additional sentence? If people use directly keras instead of tf.keras, they also need to use "keras.backend.get_session()" instead of "tf.keras.backend.get_session()" in the function call, otherwise you will get an error concerning uninitialized variables. I didn't realize you were using the prefix "tf.keras" before and that small difference cost me an hour...
– gebbissimo
Dec 5 at 8:55
add a comment |
up vote
0
down vote
If you want the model only for inference, you should first freeze the graph and then write it as a .pb
file. The code snippet looks like this (code borrowed from here):
import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K
sess = K.get_session()
constant_graph = graph_util.convert_variables_to_constants(
sess,
sess.graph.as_graph_def(),
["name_of_the_output_graph_node"])
graph_io.write_graph(constant_graph, "path/to/output/folder",
"output_model_name", as_text=False)
You can do the above using the keras_to_tensorflow tool: https://github.com/amir-abdi/keras_to_tensorflow
The keras_to_tensorflow tool takes care of the above operations, with some extra features for a more diverse solution. Just call it with the correct input arguments (e.g. input_model
and output_model
flags).
If you want to retrain the model in tensorflow, use the above tool with the output_meta_ckpt
flag to export checkpoints and meta graphs.
add a comment |
up vote
0
down vote
If you want the model only for inference, you should first freeze the graph and then write it as a .pb
file. The code snippet looks like this (code borrowed from here):
import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K
sess = K.get_session()
constant_graph = graph_util.convert_variables_to_constants(
sess,
sess.graph.as_graph_def(),
["name_of_the_output_graph_node"])
graph_io.write_graph(constant_graph, "path/to/output/folder",
"output_model_name", as_text=False)
You can do the above using the keras_to_tensorflow tool: https://github.com/amir-abdi/keras_to_tensorflow
The keras_to_tensorflow tool takes care of the above operations, with some extra features for a more diverse solution. Just call it with the correct input arguments (e.g. input_model
and output_model
flags).
If you want to retrain the model in tensorflow, use the above tool with the output_meta_ckpt
flag to export checkpoints and meta graphs.
add a comment |
up vote
0
down vote
up vote
0
down vote
If you want the model only for inference, you should first freeze the graph and then write it as a .pb
file. The code snippet looks like this (code borrowed from here):
import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K
sess = K.get_session()
constant_graph = graph_util.convert_variables_to_constants(
sess,
sess.graph.as_graph_def(),
["name_of_the_output_graph_node"])
graph_io.write_graph(constant_graph, "path/to/output/folder",
"output_model_name", as_text=False)
You can do the above using the keras_to_tensorflow tool: https://github.com/amir-abdi/keras_to_tensorflow
The keras_to_tensorflow tool takes care of the above operations, with some extra features for a more diverse solution. Just call it with the correct input arguments (e.g. input_model
and output_model
flags).
If you want to retrain the model in tensorflow, use the above tool with the output_meta_ckpt
flag to export checkpoints and meta graphs.
If you want the model only for inference, you should first freeze the graph and then write it as a .pb
file. The code snippet looks like this (code borrowed from here):
import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K
sess = K.get_session()
constant_graph = graph_util.convert_variables_to_constants(
sess,
sess.graph.as_graph_def(),
["name_of_the_output_graph_node"])
graph_io.write_graph(constant_graph, "path/to/output/folder",
"output_model_name", as_text=False)
You can do the above using the keras_to_tensorflow tool: https://github.com/amir-abdi/keras_to_tensorflow
The keras_to_tensorflow tool takes care of the above operations, with some extra features for a more diverse solution. Just call it with the correct input arguments (e.g. input_model
and output_model
flags).
If you want to retrain the model in tensorflow, use the above tool with the output_meta_ckpt
flag to export checkpoints and meta graphs.
answered Oct 10 at 7:28
AHA
959718
959718
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45466020%2fhow-to-export-keras-h5-to-tensorflow-pb%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown