因为最近的一个模型需要使用C++落地,平时使用的是python,在问google中,发现了tiny-dnn,于是着手去研究下这个库。tiny-dnn是一个C++实现的轻量的深度学习库,里面实现了主流的模型代码框架,如DNN、CNN、RNN。主流模型的示例很完整,示例有手写识别、图片分类等常用的深度学习示例。简单了解下代码组织,我们从两方面去看这个库算很完整了。
1、可以支持自定义的网络结构
static void construct_net(tiny_dnn::network &nn,
tiny_dnn::core::backend_t backend_type) {
// connection table [Y.Lecun, 1998 Table.1]
#define O true
#define X false
// clang-format off
static const bool tbl[] = {
O, X, X, X, O, O, O, X, X, O, O, O, O, X, O, O,
O, O, X, X, X, O, O, O, X, X, O, O, O, O, X, O,
O, O, O, X, X, X, O, O, O, X, X, O, X, O, O, O,
X, O, O, O, X, X, O, O, O, O, X, X, O, X, O, O,
X, X, O, O, O, X, X, O, O, O, O, X, O, O, X, O,
X, X, X, O, O, O, X, X, O, O, O, O, X, O, O, O
};
// clang-format on
#undef O
#undef X
// construct nets
//
// C : convolution
// S : sub-sampling
// F : fully connected
// clang-format off
using fc = tiny_dnn::layers::fc;
using conv = tiny_dnn::layers::conv;
using ave_pool = tiny_dnn::layers::ave_pool;
using tanh = tiny_dnn::activation::tanh;
using tiny_dnn::core::connection_table;
using padding = tiny_dnn::padding;
nn << conv(32, 32, 5, 1, 6, // C1, 1@32x32-in, 6@28x28-out
padding::valid, true, 1, 1, 1, 1, backend_type)
<< tanh()
<< ave_pool(28, 28, 6, 2) // S2, 6@28x28-in, 6@14x14-out
<< tanh()
<< conv(14, 14, 5, 6, 16, // C3, 6@14x14-in, 16@10x10-out
connection_table(tbl, 6, 16),
padding::valid, true, 1, 1, 1, 1, backend_type)
<< tanh()
<< ave_pool(10, 10, 16, 2) // S4, 16@10x10-in, 16@5x5-out
<< tanh()
<< conv(5, 5, 5, 16, 120, // C5, 16@5x5-in, 120@1x1-out
padding::valid, true, 1, 1, 1, 1, backend_type)
<< tanh()
<< fc(120, 10, true, backend_type) // F6, 120-in, 10-out
<< tanh();
}
从上面的代码看,定义CNN网络结构的过程,并且能够很自由,无论从卷积层定义、传递函数还是池化层,都可以自由去定义,并且是很简单地去定义。
2、激活函数够丰富
activation_layer.h elu_layer.h relu_layer.h sigmoid_layer.h softplus_layer.h tanh_layer.h
asinh_layer.h leaky_relu_layer.h selu_layer.h softmax_layer.h softsign_layer.h tanh_p1m2_layer.h
从这些头文件的命令来看,并且确认这些都有实现了,虽然没有完整去验证函数的准确性,但这个库能支持的传递函数足够完成日常的建模或落地的需求了,给个赞。
现在去编译测试下这个库,我编译的环境是ubuntu 16,编译非常简单,编译的步骤如下:
cmake . -DBUILD_EXAMPLES=ON
make
编译是有生成example的,看了下里面的目录,里面生成了如下程序:
example_deconv_train
example_mnist_test
benchmarks_all
example_ssd_test
example_cifar_train
example_mnist_quantized_train
example_cifar_test
example_recurrent_addition
example_test_char_rnn
example_train_char_rnn
example_deconv_visual
example_mnist_train
example_sinus_fit
里面一看就是训练和测试的程序了。首先上来我们就尝试下mnist示例吧。
./example_mnist_train --data_path /home/linxiaojie1/workspace/dnn/tiny-dnn-master/data --learning_rate 1 --epochs 30 --minibatch_size 16 --backend_type internal
Running with the following parameters:
Data path: /home/linxiaojie1/workspace/dnn/tiny-dnn-master/data
Learning rate: 1
Minibatch size: 16
Number of epochs: 30
Backend type: Internal
load models...
start training
0% 10 20 30 40 50 60 70 80 90 100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Epoch 1/30 finished. 149.407s elapsed.
9454/10000
....
....
0% 10 20 30 40 50 60 70 80 90 100%
|----|----|----|----|----|----|----|----|----|----|
end training.
accuracy:98.92% (9892/10000)
* 0 1 2 3 4 5 6 7 8 9
0 976 0 1 0 1 2 5 0 2 1
1 0 1130 0 0 0 0 2 4 0 2
2 1 1 1024 1 1 0 1 7 1 0
3 0 0 1 1001 0 2 1 0 3 0
4 0 0 1 0 970 0 1 0 1 5
5 0 2 0 2 0 886 4 0 1 5
6 1 1 0 0 3 1 942 0 2 0
7 2 1 4 3 0 1 0 1012 2 4
8 0 0 1 1 2 0 2 1 961 2
9 0 0 0 2 5 0 0 4 1 990
从上面的结果来看,最终的训练数据的精确率是98.92%。然后我再观察到在example目录中,生成一个名为LeNet-model文件,这就是我们模型的参数文件了。暂时没有深入研究里面的数据及文件的读写方式,先到些吧,后面再深入研究再介绍。