简体   繁体   中英

tensorflow and tflearn c++ API

At first I am new on both tensorflow and python to start with.

I have a python code that contains a TFlearn DNN network. I need to convert that code to C++ to later on convert it into a library to be used in mobile application development.

I read about the C++ API for tensorflow (of which documentations are real vague and not clear). so I took the code line by line to try converting it.

The first step was loading the saved model that was was previously trained and saved in python (I don't need training to be done in c++ so just loading the tflearn model is enough)

The python code to save the file was as follows:

network = input_data(shape=[None, 100, 100, 1], name='input')
network = conv_2d(network, 32, 5, activation='relu')
network = avg_pool_2d(network, 2)
network = conv_2d(network, 64, 5, activation='relu')
network = avg_pool_2d(network, 2)
network = fully_connected(network, 128, activation='relu')
network = fully_connected(network, 64, activation='relu')
network = fully_connected(network, 2, activation='softmax',restore=False)
network = regression(network, optimizer='adam', learning_rate=0.0001,
                    loss='categorical_crossentropy', name='target')

model = tflearn.DNN(network, tensorboard_verbose=0)
model.fit(X, y.toarray(), n_epoch=3, validation_set=0.1, shuffle=True,
        show_metric=True, batch_size=32, snapshot_step=100,
        snapshot_epoch=False, run_id='model_finetuning')

model.save('model/my_model.tflearn')

To load the model python code was:

network = input_data(shape=[None, 100, 100, 1], name='input')
network = conv_2d(network, 32, 5, activation='relu')
network = avg_pool_2d(network, 2)
network = conv_2d(network, 64, 5, activation='relu')
network = avg_pool_2d(network, 2)
network = fully_connected(network, 128, activation='relu')
network = fully_connected(network, 64, activation='relu')
network = fully_connected(network, 2, activation='softmax')
network = regression(network, optimizer='adam', learning_rate=0.001,
                     loss='categorical_crossentropy', name='target')
model = tflearn.DNN(network, tensorboard_verbose=0)
model.load('model/my_model.tflearn')

and this code worked like a charm in python, yet the model save file was actually 4 files inside the model folder as follows:

model
|------------checkpoint
|------------my_model.tflearn.data-00000-of-00001
|------------my_model.tflearn.index
|------------my_model.tflearn.meta

now I come to the c++ part of it. After a lot of research I came up with the following code:

#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"

#include <iostream>

using namespace tensorflow;
using namespace std;

int main()
{
    Session* session;
    Status status = NewSession(SessionOptions(), &session);
    if (!status.ok())
    {
        cerr << status.ToString() << "\n";
        return 1;
    }
    else
    {
        cout << "Session created successfully" << endl;
    }
    tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1,100,100,1}));
    GraphDef graph_def;

    status = ReadBinaryProto(Env::Default(), "/home/user/PycharmProjects/untitled/model/my_model.tflearn", &graph_def);
    if (!status.ok())
    {
        cerr << status.ToString() << "\n";
        return 1;
    }
    else
    {
        cout << "Read Model File" << endl;
    }
    return 0;
}

And now for my questions, the code compile correctly (with no faults) using the bazel build (as described in the "Short" explanation of tensorflow C++ API. but when I tried to run it the model file is not found.

Is what I did in c++ correct? Is this the correct way to load the saved model (which I don't know why 4 files are generated during save)? or is there another approach to do it?

Is there any "Full and descent" manual for the tensorflow c++ API?

If you just want to load an already trained model, a c++ loader already exists. Directly on tensorflow look here and here

Patwie also got a really good example for loading a saved model Code from Patwie .

tensorflow::Status LoadModel(tensorflow::Session *sess, std::string graph_fn, std::string checkpoint_fn = "") {
  tensorflow::Status status;

  // Read in the protobuf graph we exported
  tensorflow::MetaGraphDef graph_def;
  status = ReadBinaryProto(tensorflow::Env::Default(), graph_fn, &graph_def);
  if (status != tensorflow::Status::OK())
    return status;

  // create the graph in the current session
  status = sess->Create(graph_def.graph_def());
  if (status != tensorflow::Status::OK())
    return status;

  // restore model from checkpoint, iff checkpoint is given
  if (checkpoint_fn != "") {

    const std::string restore_op_name = graph_def.saver_def().restore_op_name();
    const std::string filename_tensor_name = graph_def.saver_def().filename_tensor_name();

    tensorflow::Tensor filename_tensor(tensorflow::DT_STRING, tensorflow::TensorShape());
    filename_tensor.scalar<std::string>()() = checkpoint_fn;

    tensor_dict feed_dict = {{filename_tensor_name, filename_tensor}};
    status = sess->Run(feed_dict,
                       {},
                       {restore_op_name},
                       nullptr);
    if (status != tensorflow::Status::OK())
      return status;
  } else {
    // virtual Status Run(const std::vector<std::pair<string, Tensor> >& inputs,
    //                  const std::vector<string>& output_tensor_names,
    //                  const std::vector<string>& target_node_names,
    //                  std::vector<Tensor>* outputs) = 0;
    status = sess->Run({}, {}, {"init"}, nullptr);
    if (status != tensorflow::Status::OK())
      return status;
  }

Unfortunatly there isn't a "full and descent" manual for tensorflow c++ API yet (AFAIK)

I wrote the steps how to save a TFLearn checkpoint correctly:

...
model = tflearn.DNN(network)

class MonitorCallback(tflearn.callbacks.Callback):
  # Create an other session to clone the model and avoid effecting the training process
  with tf.Session() as second_sess:
    # Clone the current model
    model2 = model
    # Delete the training ops
    del tf.get_collection_ref(tf.GraphKeys.TRAIN_OPS)[:]
    # Save the checkpoint
    model2.save('checkpoint_'+str(training_state.step)+".ckpt")
    # Write a text protobuf to have a human-readable form of the model
    tf.train.write_graph(second_sess.graph_def, '.', 'checkpoint_'+str(training_state.step)+".pbtxt", as_text = True)
  return

mycb = MonitorCallback()
model.fit({'input': X}, {'target': Y}, n_epoch=500, run_id="mymodel", callbacks=mycb)
...

After you have the checkpoint, you can load in C++:

https://github.com/kecsap/tensorflow_cpp_packaging#load-a-checkpoint-in-c

...and you it for inference:

https://github.com/kecsap/tensorflow_cpp_packaging#inference-in-c

You can also find example code for C and how to freeze a model then load in C++.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM