How to export Keras .h5 to tensorflow .pb?











up vote
18
down vote

favorite
13












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.










share|improve this question




























    up vote
    18
    down vote

    favorite
    13












    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.










    share|improve this question


























      up vote
      18
      down vote

      favorite
      13









      up vote
      18
      down vote

      favorite
      13






      13





      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.










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 26 at 15:05









      jdehesa

      22.1k43150




      22.1k43150










      asked Aug 2 '17 at 16:16









      Solix

      3011313




      3011313
























          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)





          share|improve this answer























          • 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 on convert_variables_to_constants (which "freezes" the variables and prunes the graph).
            – jdehesa
            Dec 7 at 12:46


















          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





          share|improve this answer

















          • 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








          • 2




            K.set_learning_phase must be called before loading the model.
            – Tahlil
            May 2 at 8:09


















          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;
          }





          share|improve this answer





















          • 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


















          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.






          share|improve this answer





















            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
            });


            }
            });














            draft saved

            draft discarded


















            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)





            share|improve this answer























            • 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 on convert_variables_to_constants (which "freezes" the variables and prunes the graph).
              – jdehesa
              Dec 7 at 12:46















            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)





            share|improve this answer























            • 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 on convert_variables_to_constants (which "freezes" the variables and prunes the graph).
              – jdehesa
              Dec 7 at 12:46













            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)





            share|improve this answer














            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)






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 on convert_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










            • 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 on convert_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












            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





            share|improve this answer

















            • 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








            • 2




              K.set_learning_phase must be called before loading the model.
              – Tahlil
              May 2 at 8:09















            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





            share|improve this answer

















            • 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








            • 2




              K.set_learning_phase must be called before loading the model.
              – Tahlil
              May 2 at 8:09













            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





            share|improve this answer












            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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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 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




              K.set_learning_phase must be called before loading the model.
              – Tahlil
              May 2 at 8:09














            • 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








            • 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










            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;
            }





            share|improve this answer





















            • 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















            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;
            }





            share|improve this answer





















            • 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













            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;
            }





            share|improve this answer












            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;
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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


















            • 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










            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.






            share|improve this answer

























              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.






              share|improve this answer























                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.






                share|improve this answer












                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.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Oct 10 at 7:28









                AHA

                959718




                959718






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Costa Masnaga

                    Fotorealismo

                    Sidney Franklin