c++erのためのDeep Learningライブラリtiny-dnnの簡単な導入とそのための超絶vim設定

# [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn)
  
Deep Learningが昨今，流行っています．機械系なのに輪講でDeep Learningの本とか読む研究室は多いのではないでしょうか．輪講当番になった心労は察するにあまりあります．
また，c++とpythonの両方に対応していることを謳っているフレームワークは多いですが，実際は実装がc++でされているだけであって，ドキュメントがpythonしか無いということは良くあります．
そこで，このtiny-dnnです．c++erのためのDeep Learningライブラリを謳っているだけあって，サンプルやドキュメントもc++erへ向けて書かれています．ちなみにOriginanl authorは日本の方で[こちら](https://qiita.com/nyanp/items/11c6bb6fb539486c5069)にqiitaにご本人による解説記事も上がっています．
今回は，導入に関して説明をしたく思います．
  
## 1. Installation
  
[tiny-dnn](https://github.com/tiny-dnn/tiny-dnn) はc++14を使用しているヘッダーオンリーのライブラリです．私はヘッダーオンリーのライブラリを作成したことがあるのですが，ヘッダーが２つのみの単純なものでした．
  
このtiny-dnnは非常に複雑なヘッダーオンリーのライブラリで，私の知識不足も手伝って，導入に苦労したのでこれを記します．単純にgithubからcloneしてきてヘッダーが収められているディレクトリを **/usr/local/include/** 以下にコピーすればいいかと思っていましたが，標準ではそうではありませんでした．おそらく，最小構成ではtiny-dnnが謳っている通りにコピーだけでインストールが終了すると思われます．
  
ここでは，従来のビルドライブラリのインストールに慣れすぎた諸兄に，そして私の備忘録としてtiny-dnnのインストールの仕方を個々に記録しておくことにします．
ちなみに，使用している環境はLinux mint 18.2(Ubuntu 16.04)です．
  
1. githubからダウンロード
  
   ```
   cd ~/opt
   git clone https://github.com/tiny-dnn/tiny-dnn.git
   cd tiny-dnn
   ```
  
2. ドキュメントをビルド
  
   ```
   cd docs
   doxygen Doxyfile
   cd ../
   cmake-gui .
   ```
  
   - configureボタンを押す
   - BUILD_DOCSのチェックを入れる
   - BUILD_EXAMPLEのチェックを入れる
   - generateボタンを押す
  
3. サンプルをビルド&インストール
  
   ```
   make
   sudo make install
   sudo cp cereal /usr/local/include
   ```
  
   ヘッダーライブラリの宿命なのですが,導入は早いのですが，プログラムをコンパイルするときに非常に時間がかかります．多分，簡単なプログラムでも１０秒位はかかるんじゃないでしょうか．したがって，全サンプルのコンパイルにも１５分位かかります．気長に待ちましょう．
  
   また，**sudo  make install** ではcerealディレクトリが，**/usr/local/include**にインストールされないので，手動でコピーしました．
  
以上で，tiny-dnnはいつもどおり，**/usr/local/include/** に配置されました．では，次にちゃんとインストールされたか確認してみましょう．
  
## 2. 確認
  
  
実際にtiny-dnnのヘッダーをインクルードしたtest_installation.cppファイルとCMakeLists.txtを用意して，コンパイルが通るかどうか確認しましょう．
  
1. test_installation.cpp

```cpp
#include <iostream>
#include <tiny_dnn/tiny_dnn.h>
  
int main(int argc, char const* argv[])
{
  
	return 0;
}
  
```  
  
2. CMakeLists.txt

```txt
cmake_minimum_required(VERSION 3.5)
  
add_definitions("-std=c++14")
  
add_executable(test_installation test_installation.cpp)
  
target_link_libraries(test_installation pthread)
  
```  
  
   最後に，**target_link_libraries**で**pthread**をビルドに加えているのがミソです．どこにも書いてありませんでしたが，これがないとエラーを起こします．いや，もしかしたら，どこかに書いてあって，見落としたかもしれません．
  
   これでビルドしてみて，うまくコンパイルされていれば，インストールはうまく行っています．
  
   ```
   cmake .
   make
   ```
  
   先程も述べましたが，tiny-dnnはコンパイルに１０秒位時間がかかるので，気長に待ちましょう．
  
# サンプル確認（MNIST)
  
導入が終了したので，サンプルプログラムの１つでも動かしてみることにしましょう．サンプルプログラムは**tiny-dnn/example**においてあります．手始めに**example_mnist_train**を動かしてみましょう．MNISTとは乱暴に書かれた手書きの数字を０から９のどれかに判別する問題のことで，Deep Learningの入門ではよく使用されます．MNISTの学習を行うためにはデータセットと正解ラベルが必要であり，それらは**tiny-dnn/data**にあります．では下記のようにして，実行しましょう．１３分ほど時間がかかります．
  
`````
./example_mnist_train --data_path ../data
`````
  
終了したら，ディレクトリ内にLeNet-modelというファイルが作成されます．
これが学習結果です．同じexampleディレクトリ内にある**example_mnist_test**に手書き文字が書かれた写真を渡すことで，その文字がどの数字なのかを判定することができます．判定にはLeNet-modelが利用されます．4の書かれた画像を保存して，**example_mnist_test**と同一ディレクトリに置き，下記のコマンドを実行してください．
  
![4](https://i.imgur.com/zX5maHJ.png )
  
```
./example_mnist_test 4.bmp
```
すると，判定結果が下記のように表示されます．
  
```
4,110.452
7,64.5806
8,54.7664
```
これは，４，７，８の３つの数字が候補に上がっていて，４，７，８の順に，そうである確率が高いことを示しています．今回は４が書かれた画像を渡したので，4である確率が高くなっていることがわかります．
  
# vim編集用プラグイン導入
  
  
コーディングに様々なエディターが世間では使用されていますが，私はvimを使用してコーディングをしています．tiny-dnnを用いたプログラムを作成するときも，私は当然のように私は当然のようにvimを使用しました．vimには様々なプラグインがあり，その振る舞まいを自由にカスタマイズすることが可能であり，それが人気の秘訣でもあります．そんな中，私は，補完を行うためにYouCompleteMeというとてもおしゃれな名前のプラグインを使用しています．当然，tiny-dnnを使用したプログラムでも完璧に補完してくれるものだと思っていました．
  
しかしながら，そうではありませんでした．どうやら，tiny-dnnはテンプレートテクニックを使用しすぎているのかc++の闇魔術を使用しているのか原因はわかりませんが，うまく補完が聞いてくれませんでした．試しに最新版(2018-6-2現在)の[Visual Studio Code](https://www.microsoft.com/ja-jp/dev/products/code-vs.aspx )をダウンロードしてきてIntellisenseで補完が効くかどうか試したところ，必要なヘッダーが見つからないとエラーをはいてしまって，うまく補完されませんでした．
  
しかしながら補完が効かないエディタでコーディングをするのは，武器を持たずに戦場に赴くのに等しい行為です．そこで，YoucCompleteMeの設定ファイルを作成して読み込ませることにより，YouCompleteMeの補完やエラー表示を行えるようになりましたので，その方法をご紹介いたします．
  
## 1. YCM-Generator
  
[YCM-Generator](https://github.com/rdnetto/YCM-Generator/tree/stable )とはYouCompleteMeの設定ファイル(.ycm_extra_conf.py)をMakefileから生成してくれるものです．通常，YouCompleteMeはパスが通っているディレクトリのライブラリに関しては補完を行ってくれるのですが，パスが取っていない場所にライブラリがあったりすると補完をしてくれません．それどころかエラーチェック機能によって，「その場所にライブラリ無いよ」とYouCompleteMeに怒られてしまいます．今回は，**/usr/local/include** 以下にtiny-dnnをインストールしたので，問題ないはずなのですが，何かやんごとなき理由で，うまく補完がされませんでした．そういうわけで，YouCompleteMeに補完するときに，「ここに置いてあるライブラリも考慮してよ」という指示を行うための設定ファイルを自動で作成してくれるのがYCM-Generatorになります．
  
導入は簡単で，特に設定とか入りません．私はプラグインマネージャにdeinを使用しているので，下記のように **~/.config/nvim/init.vim**に書くことによってすぐに導入できました．ここに関しましては各人の宗教によって定まっているプラグインマネージャーをご利用ください．
  
```
call dein#add('rdnetto/YCM-Generator')
```
  
## 2. 確認
  
このYCM-GeneratorはMakefileによって設定ファイルを作成するので，プログラム本体とCMakeLists.txtを作ったら，一回だけ**cmake**を実行する必要があります．試しに，先ほどのtest_installationで試してみましょう．
  
まず，vimでtest_installation.cppを開き，下記のコマンドを打ち込みエンターをおします．
```
:YcmGenerateConfig
```
![Screenshot from 2018-06-03 17-30-52](https://i.imgur.com/WNHJ8sp.png )
  
そのあと，一回ファイルを閉じるか，再読込すると下記のように設定ファイルが見つかりましたが読み込むかどうかを聞かれるので，**o**をおしてOkしましょう．
  
![Screenshot from 2018-06-03 17-30-13](https://i.imgur.com/ipKgHkT.png )
  
すると，下記のように補完が効くようになり，快適なtiny-dnnライフを送れる準備が整いました．
![Screenshot from 2018-06-03 18-03-54](https://i.imgur.com/6obxB2W.png )