因爲最近的一個模型需要使用C++落地,平時使用的是python,在問google中,發現了tiny-dnn,於是着手去研究下這個庫。tiny-dnn是一個C++實現的輕量的深度學習庫,裏面實現了主流的模型代碼框架,如DNN、CNN、RNN。主流模型的示例很完整,示例有手寫識別、圖片分類等常用的深度學習示例。簡單瞭解下代碼組織,我們從兩方面去看這個庫算很完整了。
1、可以支持自定義的網絡結構
static void construct_net(tiny_dnn::network<tiny_dnn::sequential> &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文件,這就是我們模型的參數文件了。暫時沒有深入研究裏面的數據及文件的讀寫方式,先到些吧,後面再深入研究再介紹。