×

Tensorflow in C++

With cppflow, you can execute TensorFlow models in C++ without Bazel, TensorFlow installation, or TensorFlow compilation. Tensor manipulation, eager execution, and running stored models straight from C++ are all possible.

Knowing the C++ library in detail

The TensorFlow repository includes the TensorFlow Lite for Microcontrollers C++ library. It is intended to be legible, adaptable, thoroughly tested, simple to integrate, and backward compatible with standard TensorFlow Lite.

The basic organization of the C++ library is described in the accompanying text, along with instructions for developing your project.

Tensorflow C++

Document structure:

The micro root directory's structure is rather basic, given that it is housed within the vast TensorFlow repository.

Key files:

There are tests and the most crucial files for utilizing the TensorFlow Lite for Microcontrollers interpreter at the project's root.

all_ops_resolver.h or micro_mutable_op_resolver.h

All ops resolver.h takes a lot of memory because it includes every available operation. Use micro mutable op resolver. h to only include the operations your model requires in production applications. This can supply the commands the interpreter needs to run the model.

micro_error_reporter.h

Produces debugging data.

micro_interpreter.h

Includes code for handling and running models.

The build system enables the implementation of certain files on different platforms. These can be found under a directory bearing the platform's name, like sparkfun_edge.

Other directories include the following:

  • Kernel, which includes the code and operation implementations.
  • A collection of build tools and their output is called tools.
  • Examples include a code snippet.

Start a new project

We advise utilizing the Hello World example as a model for new projects.

Implement the Arduino library:

If you're using Arduino, which you can get from the Arduino IDE and in Arduino Create, includes the Hello World example.

Go to File -> Examples after the library has been added. The final item on the list should be a TensorFlowLite: hello world example. Click hello world after selecting it to load the sample. After that, you can make a copy of the example and use it as the foundation for your work.

Conceive projects for several platforms.

With the help of a Makefile, TensorFlow Lite for Microcontrollers may produce standalone projects with all the required source files. Keil, Make, and Mbed are the currently supported environments.

Due to the necessity of downloading some substantial toolchains for the dependencies, this will require some time. When done, you should notice that a path like gen/Linux x86 64/prj/ has been generated with a few directories (the exact path depends on your host operating system). The produced project and source files are located in these directories.

You'll be able to locate the Hello World after executing the commanding gen/Linux x86 64/prj/hello world projects. The Keil project, for instance, will be located in hello world/Keil.

Execute the tests: 

Use the next command to construct the library and launch all of its unit tests:

Make -f test tensorflow/lite/micro/tools/make

Use the following command to execute a specific test, substituting test name> with the test's name:

Make -f test name> tensorflow/lite/micro/tools/make/Makefile

The test names can be found in the project's Makefiles. Names of the tests in the "Hello World" example are specified in examples/hello-world/Makefile.inc, for instance.

Create binaries

Use the command below, swapping out "project name" for the name of the project you desire to build, to create a runnable binary for the provided project (such as an example application):

Use the command make -f tensorflow/lite/micro/tools/make/Makefile <project_name>_bin.

As an illustration, the command shown below will create a binary for the application Hello World:

Make -f hello world bin tensorflow/lite/micro/tools/make

The project will, by default, be built for the host operating system. Use TARGET= to indicate a different target architecture. The SparkFun Edge's Hello World example can be built using the example below:

TARGET=sparkfun edge hello world bin build -f tensorflow/lite/micro/tools/make

Target-specific source files will be utilized in place of the original code when a target is selected. The file constants, Cc and output handler. Cc, for instance, has SparkFun Edge implementations in the subfolder examples/hello-world/SparkFun edge, which are utilized when the target Sparkfun edge is provided.

The project's Makefiles contain the project names. The example of Hello World's binary names is specified in examples/hello-world/Makefile.inc, for instance.

Enhanced kernels

The reference kernels in the root of the tensorflow/lite/micro/kernels are developed entirely in C/C++ and do not use hardware optimizations tailored to particular platforms.

Subdirectories include kernels that have been optimized. For instance, the kernels/cms is-nn directory includes several CMSIS-NN-based improved kernels.

Replace "subdirectory name" in the following command with the name of the subdirectory containing the optimizations to create projects utilizing optimized kernels:

Makefile TAGS= tensorflow/lite/micro/tools/make=<subdirectory_name> generate_projects

You can add your own by designating a new subdirectory for your improvements. Pull submissions for fresh, improved implementations are welcomed.

Make an Arduino library:

The library manager in the Arduino IDE provides access to a nightly build of the Arduino library.

You can execute the following script from the TensorFlow repository to create a fresh build of the library if necessary:

./tensorflow/lite/micro/tools/ci build/test Arduino.sh


Tensorflow lite.zip, located in the directory gen/arduino x86 64/prj, contains the finished library.

Creating a TensorFlow in C++ 

In general, while developing TensorFlow code, it is best to decouple the development of the graph from its actual execution. This is because the graph is normally created once and then run several times with varied inputs. Even if you do not modify the graph's variables (such as weights), there is no need to construct the graph each time you wish to run it unless the graph is incredibly basic and the separation effort is ineffective.

Complete the data preparation

Let’s take the example for CNN graph, we will see data preparation for CNN and its other necessary information with the help of this we will learn to create the C++ in Tensorflow.

CreateGraphForImage is a method for making a graph.

It accepts a Boolean value indicating whether or not to unstack the picture. When you want to load only one picture, use false, and when you want to load a batch, use true. This is due to the logic that an additional dimension will be added while stacking a batch. However, if you wish to run the CNN with only one picture, you must have all four dimensions.

Note: It should be noted that while switching from unstack to stack, the graph must be recreated.

ReadTensorFromImageFile executes the graph formed by the preceding technique. You input a file's entire path name, and it returns a 3 or 4-dimensional Tensor.

The code for both these methods is almost identical.

Handling folders and path:

ReadFileTensors is concerned with folders and files. It takes a base folder string and a vector of [sub-folder, label value] pairs.

If you downloaded the photographs from Kaggle, you might have noticed two sub-folders under the train, for example, cats and dogs. Each one should be labeled with a number, and these pairings should be supplied as input.

The result is a vector of pairs, each consisting of a Tensor (of an image) and a label.

Here's one way to put it:

base_folder = "/Users/bennyfriedman/Code/TF2example/TF2example/data/cats_and_dogs_small/train";
vector<pair<Tensor, float>> all_files_tensors;
model.ReadFileTensors(base_folder, {make_pair("cats", 0), make_pair("dogs", 1)}, all_files_tensors);

We must open a directory, read its files, 

To join two path strings use

io::JoinPath (include tensorflow/core/lib/io/path.h)

string folder_name = io::JoinPath(base_folder_name, “cats”);

To interact with the file system, use "Env". This utility class (not documented) gives you similar facilitation to C++17 std::filesystem.

Env* penv = Env::Default();
TF_RETURN_IF_ERROR(penv->IsDirectory(folder_name));
vector<string> file_names;
TF_RETURN_IF_ERROR(penv->GetChildren(folder_name, &file_names));
for(string file: file_names)
{
…
}

ReadFileTensors shuffles the images in the vector, allowing us to feed different images while training.

Creating the batches

ReadBatches captures all of the logic's primary requirements. You specify the base folder, the vectors of two subfolders and labels, and the batch size. In response, you will receive two Tensor vectors, one for pictures and one for labels. Each Tensor is a collection of pictures or labels according to your specified size.

It begins by reading the folder's content and subfolders into a vector. It next does some computations to determine how to divide the batches. The pairs of Tensors and labels are then split into two Input vectors, with each any element in the Tensor vector matching the any element in the labels vector.

vector<Input> one_batch_image;
one_batch_image.push_back(Input(tensor));
//Add more tensors
InputList one_batch_inputs(one_batch_image);
Scope root = Scope::NewRootScope();
auto stacked_images = Stack(root, one_batch_inputs);
ClientSession session(root);
vector<Tensor> out_tensors;
TF_CHECK_OK(session.Run({}, {stacked_images}, &out_tensors));
//use out_tensors[0]
As written above, the tensors go in as 3-dimensional tensors, and the batches created are 4-dimensional.

As written above, the tensors go in as 3 dimensional tensors and the batches that are created are 4 dimensional.


Related Topics

Observer Design Pattern in C++

The Observer design pattern is a behavioural design pattern that allows an object (known as the subject) to notify other objects (known as observers) when its state changes. This is...

3 minutes read.

C++ Friend Functions

In C++, friends are special functions that are not a part of a class yet have access to its private and protected members. The friend keyword is used to declare...

4 minutes read.

How the value is passed in C++

Introduction: The call-by-value method of giving arguments to a function duplicates the real value of an argument into the formal parameter of the function. In this instance, modifications to the parameter...

5 minutes read.

C++ Expressions

C ++ equations are made up of operators, constants and variables arranged according to language rules. It may also include function calls that give results. To calculate the value, the...

4 minutes read.

C++ Try-Catch

Every useful program will eventually encounter unexpected outcomes. By entering data that are incorrect, users might create mistakes. Sometimes the program's creator didn't consider all of the options or was...

7 minutes read.

How to improve programming skills in C++

Before getting started, one should know why to improve their programming skills. To become a good software developer or programmer, one must be skilled in at least one programming language. Many...

4 minutes read.

Abstract class in C++

In this article, you will get exposure to an abstract class in C++. We will discuss this topic using some practical examples too. To understand the abstract classes, you should...

6 minutes read.

C++ Pipe Tutorial

A pipe is a mechanism for inter-process communication (IPC) in a Unix-like operating system. It allows two or more processes to communicate with each other by sending and receiving data...

3 minutes read.

Reserved Keywords in C++

What are reserved keywords in C++? There are a few keywords that cannot be used as identifiers as those words are reserved for some other purposes, such keywords are called reserved...

15 minutes read.

strcat() vs strncat() in C++

In this tutorial, we will explore about strcat() and strncat() in the most usable language C++. We will also look at the difference between them. strcat() C++ is a computer language with...

4 minutes read.

C++ Comments

Comment/Remark A Comment or a Remark is text that is ignored by the compiler yet is beneficial to programmers. Code is usually annotated with comments for future reference. They are treated...

3 minutes read.

Palindrome Using While Loop in C++

A palindrome is a word, number, phrase, or other sequence of letters that reads the same backward as forward, such as 101 or MOM. Like other programming languages, C++ also allows...

6 minutes read.

Pointer to Object in C++

What is a pointer? A pointer in C++ is used to point the variable by storing the address of the variable. In C++, to print the address of the variable, we...

4 minutes read.

C++ vardiac() function

In the C++ programming language, the flexibility feature is provided by the variadic function. To understand more about flexibility, let's see the following syntax. Syntax: If we have to add two numbers,...

3 minutes read.

C++ Algorithms

There are plenty of programming paradigms that are closely associated with the implementations of code and simulate them into a proper functional one. This is done with the help of...

5 minutes read.

C++ Program to find largest subarray with 0 sum

Write a program to find the largest subarray that has a sum zero. The array contains positive and negative numbers. Print the length of the max subarray whose sum turns...

4 minutes read.

Hierarchical Inheritance

C++ Hierarchical Inheritance Hierarchical inheritance inherits the property of one base class in more than one derived class.   C++ Hierarchical Inheritance Example #include <iostream>   using namespace std;   class Person {       char gender[10];       int age;   public:       void getPerson()       {           cout << "Age: "; cin >> age;           cout << "Gender: "; cin >> gender;       }       void dispPerson()       {           cout << "Age: " << age << endl;           cout << "Gender: " << gender << endl;       }   };   class Employee : public Person {       float salary;   public:       void getEmployee()       {           Person::getPerson();           cout << "Salary: Rs."; cin >> salary;       }       void dispEmployee()       {           Person::dispPerson();           cout << "Salary: Rs." << salary << endl;       }   };   class Student : public Person {       char level[20];   public:       void getStudent()       {           Person::getPerson();           cout << "Class: "; cin >> level;       }       void dispStudent()       {           Person::dispPerson();           cout << "Level: " << level << endl;       }   };   int main()   {       Person per;       Employee emp;       Student stu;       cout << "Student data" << endl;       cout << "Enter data" << endl;       stu.getStudent();       cout << endl << "Displaying data" << endl;       stu.dispPerson();       cout << endl << "Staff Data" << endl;       cout << "Enter data" << endl;       emp.getEmployee();       cout << endl << "Displaying data" << endl;       emp.dispPerson();   } Output: Student data Enter data Age: 10 Gender: f Class: 5 Displaying data Age: 10 Gender: f Employee data Enter data Age:...

1 minute read.

C++ Continue

In C++, the continue statement is a useful tool for avoiding specific scenarios without breaking the loop. It is employed inside loops to move directly to the following iteration and...

4 minutes read.

C++ Continue in for loop

Continue statement: Inside the loop, the continue statement is used to control the loop. C++ utilizes the continue keyword to implement the continue statement, which transfers the program's flow at the start...

4 minutes read.

C++ Multimap

Definition: In C++, a multimap is similar to a map with the additional concept, where multiple elements possess the same keys. It is also not necessary that the key values and...

4 minutes read.