SONY謹製DeepLearningライブラリNNablaでCifar10実装してみたヅラ【ニッポン万歳】

# SONYがやってくれたらしい
[ソニーがAIの進化を加速する。ディープラーニングのコアライブラリをオープンソース化](http://www.gizmodo.jp/2017/06/sony-deep-learning.html)
※gizmodoさんより引用

SONYが自社製のDeepLearningのライブラリをオープンソースで公開した。
[公式サイト](https://nnabla.org/)
興味の有る方はこちらを参照

一部ではIT後進国と揶揄される日本もがんばってるじゃありませんか。
特に日本の大手企業はソフトウェア関連については正直良い噂を聞かないので…

SONYについてはこんなブログも最近軽く話題になったし…
[ソニー株式会社を退職しました](https://anond.hatelabo.jp/20170403094257)

でかい企業なので、全部が全部このブログの通りなのかは私にはわかりませんが、
私自身、良い印象がなかったのは確かです。
個人的には日本企業だから応援しよう、とかそういう気持ちはあんまりないのですが、
せっかくなのでQiitaにライブラリを使った感想でも書いてみようじゃあないか！

# はい、みんなだいすきCifar10
[コードはこちら](https://github.com/miumiu0917/nnabla-cifar10)

とりあえずね、やっつけでやってやりましたよ。ええ。
クオリティの低さは気にしないで下さい。~~Qiitaで一番にNNabla使ってみたの記事書きたかったので、超速で仕上げた結果がこれだよ！！！~~
時間がなくてモデルは超適当なので精度は気にしないでください。。
ただAPI触ってみたかっただけなので。。

```python:main.py
def convolution(x):
  x = x.reshape([BATCH_SIZE, IMAGE_DEPTH, IMAGE_HEIGHT, IMAGE_WIDTH])
  with nn.parameter_scope("conv1"):
    output = PF.convolution(x, 16, (5, 5), stride=(2, 2), pad=(1, 1))
    output = F.relu(output)
  
  with nn.parameter_scope("conv2"):
    output = PF.convolution(output, 32, (3, 3), stride=(1, 1), pad=(1, 1))
    output = F.relu(output)
  
  with nn.parameter_scope("conv3"):
    output = PF.convolution(output, 64, (3, 3), stride=(1, 1), pad=(1, 1))
    output = F.relu(output)

  output = output.reshape([BATCH_SIZE, int(output.size / BATCH_SIZE)])

  with nn.parameter_scope("fc1"):
    output = PF.affine(output, 1024)
    output = F.relu(output)
  
  with nn.parameter_scope("fc2"):
    output = PF.affine(output, 256)
    output = F.relu(output)
  
  with nn.parameter_scope("softmax"):
    output = PF.affine(output, 10)
    output = F.softmax(output)
  
  return output
```
こんな感じのCNNですわ。
APIリファレンスの[Parametric Functions](http://nnabla.readthedocs.io/en/latest/python/api/parametric_function.html)ってやつは抽象的なAPIでけっこう楽にネットワーク定義できます。
低レイヤーのやつは[こっち](http://nnabla.readthedocs.io/en/latest/python/api/function.html)かな。
（あんまり詳しく見てないんですけど…）

```
Step: 00290 Train loss: 7.17657 Train accuracy: 0.34375
Step: 00300 Test loss: 7.22971 Test accuracy: 0.34990
Step: 00300 Train loss: 7.23585 Train accuracy: 0.28125
Step: 00310 Train loss: 7.26531 Train accuracy: 0.28125
Step: 00320 Train loss: 7.15616 Train accuracy: 0.37500
Step: 00330 Train loss: 7.19948 Train accuracy: 0.29688
Step: 00340 Train loss: 7.23404 Train accuracy: 0.26562
Step: 00350 Train loss: 7.13390 Train accuracy: 0.42188
Step: 00360 Train loss: 7.27805 Train accuracy: 0.20312
Step: 00370 Train loss: 7.08152 Train accuracy: 0.46875
Step: 00380 Train loss: 7.17094 Train accuracy: 0.34375
Step: 00390 Train loss: 7.12861 Train accuracy: 0.39062
Step: 00400 Test loss: 7.21064 Test accuracy: 0.36996
```
実行結果はこんな感じでコンソールに出力されます。
同じようなネットワークをTensorFlowで書いたのに比べるともっさりしてる感じはあります。


# 苦労した点
普段はTensorFlowばっか触っていて、実はTF以外のDeepLearningのライブラリは使ったことがないんです。。お恥ずかしい。
理解を深めるためにスクラッチで組んだりしたことはありますが。

苦労した点は正直あんまりないです。
他のライブラリ使ったことがあれば、特に違和感なく使えるかと。
抽象的なレイヤー定義ができるので楽ですね。
他のライブラリ使ったことがないので何とも言えませんが、この程度のコードであれば同じ感覚で使えました。

あえて苦労した点を言えば、python2系を使うのがすごい久しぶりで、
intの除算の仕様をすっかり忘れてました。

```python:main.py
def accuracy(p, t):
  pred_and_label = [(np.argmax(_p), np.argmax(_t)) for _p, _t in zip(p.d, t.d)]
  return float(len(filter(lambda x: x[0] == x[1], pred_and_label))) / float(len(p.d))
```
ここで出力結果の正解率を計算しているのですが、
こいつがずっと０のままで、、、あれおかしいな、、、ってしばらく考え込んでました。。
これはfloatに直してるので、ちゃんと出力されます。

~~んー。業務でもpython3を使うことがほとんどなので、
ここは早めに3系対応したいですね。~~
python3対応したそうです！コメントありがとうございます！(2017/08/18)

**追記**
---
苦労したというか、時間がなくて見つけられなかっただけかもしれないが、
TensorFlowのshape定義でいうNoneにあたるものが見当たらなかった。
[?, 3, 64, 64]みたいなshapeを定義するやつ。
SampleのGithubのコード見ても、テストデータは訓練と同じサイズのバッチを繰り返して計算していたようなので、僕もそうしました。
バッチサイズは固定しか使えないってのは正直ないと思うので、何か方法あるんだろうけど。。
あとでその辺も調べてみよう。~~時間があればね！！~~


# まとめ
~~個人的にはTensorFlowでおｋ~~
DeepLearning界隈の盛り上がって欲しいですし、頑張って欲しいですね。
ひまがあったらもっと触ってプルリクしてみようかな。

あと、この[DynamicNN](http://nnabla.readthedocs.io/en/latest/python/tutorial/dynamic_and_static_nn.html)ってのがちょっと気になるので、また時間があるときに触ってみます。
Define by runとDefine and runのマルチパラダイムみたいですね。

なんか間違ってるところとかあったら是非教えてください！！