Build and Train Neural Network with Tensorflow C++

Thomas Ho
4 min readFeb 6, 2018

--

Tensorflow has became one of the most adapted framework for deep neural network projects. Currently Tensorflow provides rich APIs in Python. Using Keras, it is very easy to construct and train a deep neural network. Its C++ APIs are far less mature now. It is much difficult to construct a Tensorflow DNN graph using C++. Here I describe some of my experimental codes that build and train a sample neural network for traffic light classification from images in simulation environment. The goal is to provide a Keras like C++ APIs in the future. The code can be found in my github.

Sample Network Architecture

The deep neural network in our example is a CNN network developed by Nvidia for estimating driving angle. We’ll train this network to classify traffic light image. Following shows the network architecture

Construct and Train Model

The model class in tfplusplus.h provides a simple API to construct a sequential DNN that allows user to add NN layers intuitively.

template <typename T, typename... args>
void build_seq(const T& op, const args&... others);

Following is the code that builds the sample neural network in main.cc:

model m({BATCH_SIZE, 96, 128, 3});m.build_seq (
conv2d({5, 5, 24}, {1, 2, 2, 1}, "SAME"),
elu(),
maxpool({1, 2, 2, 1}, {1, 1, 1, 1}, "SAME"),
conv2d({5, 5, 36}, {1, 2, 2, 1}, "SAME"),
elu(),
maxpool({1, 2, 2, 1}, {1, 1, 1, 1}, "SAME"),
conv2d({5, 5, 48}, {1, 2, 2, 1}, "SAME"),
elu(),
maxpool({1, 2, 2, 1}, {1, 1, 1, 1}, "SAME"),
conv2d({3, 3, 64}, {1, 1, 1, 1}, "SAME"),
elu(),
maxpool({1, 2, 2, 1}, {1, 1, 1, 1}, "SAME"),
conv2d({3, 3, 64}, {1, 1, 1, 1}, "SAME"),
elu(),
flatten(),
dense2d(1164, activation::Elu),
dense2d(100, activation::Elu),
dense2d(50, activation::Non),
dense2d(10, activation::Non),
dense2d(3, activation::Non),
softmax()
);

Once we build the graph, we need to initialize the variables before training. The initialize API in model class initializes all variables in the model, adds gradient operations and applies specified optimizer:

m.initialize(optimizer::Adam);

The train API in model class trains a batch of data. Following code show how to train for multiple epochs. This API probably should be implemented to train multiple epochs as Keras fit_generator does.

for(int i = 0; i < EPOCHS; i++) {
std::cout << "EPOCHS " << i << " start..." << std::endl;
std::shuffle(tldata.begin(), tldata.begin()+train_num, g);
float loss = 0.0, err = 0.0, accu = 0.0;
for(int k = 0; k < bnum; k++) {
std::vector<Tensor> outputs;
int bsize = BATCH_SIZE;
int start = k*BATCH_SIZE;
if(start + bsize > train_num) {
bsize = train_num - start;
}
GetBatch(bsize, start, tldata, outputs); const Tensor& images = outputs[0];
const Tensor& labels = outputs[1];
auto rec = m.train(images, labels);
loss += rec[0];
err += rec[1];
accu += rec[2];
}
loss /= bnum;
err /= bnum;
accu /= bnum;
std::cout << "training loss for epoch " << i << " is " << loss;
std::cout << " cost " << err;
std::cout << " accuracy " << accu << std::endl;
}

Build and Run

To compile the code, you’ll first need to create the C++ Tensorflow library first. This tutorial describes the steps to create a C++ library that you can link and build the Tensorflow C++ application with GCC. The command to build the sample code is:

g++ -I/usr/local/include -L/usr/local/lib -g -std=c++14 model.cc -ltensorflow_cc -ltensorflow_framework -lstdc++fs

Result

After 160 epochs of training, the accuracy slowly approach to 92%.

EPOCHS 0 start...
training loss for epoch 0 is 1.6298 cost 0.27303 accuracy 0.397382
EPOCHS 1 start...
training loss for epoch 1 is 0.730628 cost 0.26032 accuracy 0.401182
EPOCHS 2 start...
training loss for epoch 2 is 0.455526 cost 0.240752 accuracy 0.402872
EPOCHS 3 start...
training loss for epoch 3 is 0.354437 cost 0.246685 accuracy 0.401182
EPOCHS 4 start...
training loss for epoch 4 is 0.297292 cost 0.239769 accuracy 0.401182
EPOCHS 5 start...
training loss for epoch 5 is 0.280813 cost 0.248006 accuracy 0.403294
EPOCHS 6 start...
training loss for epoch 6 is 0.257736 cost 0.237312 accuracy 0.402449
EPOCHS 7 start...
...
EPOCHS 80 start...
training loss for epoch 80 is 0.0185297 cost 0.00611639 accuracy 0.848395
EPOCHS 81 start...
training loss for epoch 81 is 0.0198371 cost 0.00765664 accuracy 0.841639
EPOCHS 82 start...
training loss for epoch 82 is 0.0211765 cost 0.00902148 accuracy 0.839105
EPOCHS 83 start...
training loss for epoch 83 is 0.0241919 cost 0.0117377 accuracy 0.827703
EPOCHS 84 start...
training loss for epoch 84 is 0.0250288 cost 0.0121114 accuracy 0.86951
EPOCHS 85 start...
training loss for epoch 85 is 0.0291566 cost 0.0159336 accuracy 0.852196
EPOCHS 86 start...
training loss for epoch 86 is 0.0283943 cost 0.0145831 accuracy 0.856841
EPOCHS 87 start...
training loss for epoch 87 is 0.0214014 cost 0.00760166 accuracy 0.887669
...
EPOCHS 152 start...
training loss for epoch 152 is 0.00992104 cost 0.00213582 accuracy 0.906672
EPOCHS 153 start...
training loss for epoch 153 is 0.0123421 cost 0.00472957 accuracy 0.920186
EPOCHS 154 start...
training loss for epoch 154 is 0.0106575 cost 0.00296814 accuracy 0.931588
EPOCHS 155 start...
training loss for epoch 155 is 0.00905419 cost 0.00153432 accuracy 0.927365
EPOCHS 156 start...
training loss for epoch 156 is 0.00870481 cost 0.00141313 accuracy 0.92652
EPOCHS 157 start...
training loss for epoch 157 is 0.00854244 cost 0.00144911 accuracy 0.928632
EPOCHS 158 start...
training loss for epoch 158 is 0.00824191 cost 0.00133372 accuracy 0.928209
EPOCHS 159 start...
training loss for epoch 159 is 0.00809524 cost 0.00135928 accuracy 0.928209
EPOCHS 160 start...
training loss for epoch 160 is 0.00796224 cost 0.00139161 accuracy 0.925253

This is much worse than the same model constructed using Keras, which converges to 99% validation accuracy after 20 epochs. Part of the reason probably is due to some operations used in the Keras model that are not available in C++ yet. Like xavier initialization and dropout.

Conclusion

We demonstrate the Tensorlfow C++ APIs can be used to build and train a DNN neural network, although the performance is not comparable with Keras implementation. It will take some time for C++ APIs to mature. My goal is to provide a Keras like C++ API to make build and train Tensorflow C++ model easier.

--

--