MS の Deep Learning Framework CNTK で画風変換～もしも小学生の自分にゴッホを描かせたら？

Microsoft の Deep Learning のフレームワーク Cognitive Toolkit (CNTK) が、2016 年 10 月に Version 2.0 に上がって Python でも使えるようになりました。そこからさらに活発に開発が行われてどんどん進化しているようです。

* **Update (2017/04/05):**  4/4 に CNTK がついに beta が取れて、V 2.0 Release Candidate 1 に Version が上がりました！詳しくは[こちら](https://blogs.technet.microsoft.com/machinelearning/2017/04/03/microsoft-updates-its-deep-learning-toolkit/)から！なので、それに伴って環境構築方法を更新しました。
* **Update (2017/04/23):**  先日、V 2.0 RC 2 に上がりさらに Python 3.6 にも対応しました。環境構築方法を更新しました。

そこで、そもそも CNTKとは、そして CNTK の Python version 環境構築法についてまとめてみようと思います。単に環境構築をしただけでは面白くないので、今回は、公式ページで Jupyter Notebook 形式で提供されているいくつもの Tutorial の 中から Style Transfer を試します。
Style Transfer を使えば、以下のようにコンテンツ画像に対して、スタイル画像の画風を適用して、以下のような生成画像を出力させることができます。

| コンテンツ画像 | スタイル画像 | 生成画像|
|:-----------:|:------------:|:-----------------:|
|![content.png](https://qiita-image-store.s3.amazonaws.com/0/104326/d0ddd1a9-6218-fd16-e40c-b0e35f625834.png)|  ![style.png](https://qiita-image-store.s3.amazonaws.com/0/104326/1d8f8cc2-f238-aecf-354c-f3d973ab05c7.png) | ![output_example.png](https://qiita-image-store.s3.amazonaws.com/0/104326/ba84960d-ed1e-0b5c-4ca1-728362f8ad09.png)|

これを使って、自分が小学校の時に賞を取った絵

![s_young_pic.JPG](https://qiita-image-store.s3.amazonaws.com/0/104326/7560a1fa-55c1-acef-9151-00323eb69ff3.jpeg)

（小学校の時の自分が描いたその絵のタイトルはその名も **「空飛ぶ魚」**！）

からその時の絵画センス（それ以降中学校でも美術の成績だけ散々だったのでたぶん人生での美術センスのピーク）を抽出してゴッホの絵に適用して、もしも小学校時代の自分がゴッホの絵を描いたならを試します。
それにしても今の自分には到底描けないような謎の、不思議な世界観…。

そんな絵の画風を恐れ多くも適用させていただく今回のターゲットは、

![s_sunflower.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/2a5cef7b-c1b2-7f33-e3b5-eef79f0e9307.jpeg)

ゴッホのひまわり！

これで小学校時代の自分がもしゴッホのひまわりを描いてみたらどんな感じだったかが垣間見えるはず！
どのような仕上がりになるかは乞うご期待です。

Style Transfer の Tutorial には、実装済みのアルゴリズムと学習済みモデル、（そして各コードに対するコメントやアルゴリズムの説明）が用意されているので環境構築を行えばすぐ簡単に遊ぶことができます。

# そもそも Cognitive Toolkit (CNTK) とは？

[公式ページ](https://github.com/Microsoft/CNTK)に書いてあることをまとめます。
## 特徴
- Microsoft の Skype リアルタイム翻訳や, Cortana, Bing, Xbox等々色々なサービスに既に使われている
- Microsoft のみならず MIT や Stanford 等の様々な研究者との共同開発
- オープンソースで完全に社内と社外で使っているものが一緒 (Linux, Windows 共に対応)
- Python, C++, BrainScriptに対応、学習済みモデルは C# でもデプロイ可能
- 高速学習が可能
- 2017年4月4日現在 Version 2.0 Release Candidate 1 

MS 社内での活用については、2016年9月29日に MS が、AI関連製品の取り組みにフォーカスした5,000人以上のコンピューターサイエンティストとエンジニアを集めた研究組織である Microsoft AI and Research Group を設立したことを[発表](https://news.microsoft.com/ja-jp/2016/10/06/161006-microsoft-ai-research/#6IW8q3TFAKUpjuBL.99)したことからも、それだけのリソースを割いて、あらゆる MS の BtoB や BtoC のプロダクトへの一層の採用、活用が広がっていくことが予想されます。

### パフォーマンスについて
以下に引用しているのが公式ページ上に記載されている各フレームワークによる学習速度比較です。画像の示している 2015年12月当時は複数サーバー、複数 GPU での並列学習に対応しているのが CNTK のみでした。単ノードの複数 GPU での学習のパフォーマンスも他のフレームワークと比較して高かったようです。
![performance](https://raw.githubusercontent.com/Microsoft/CNTK/master/Documentation/Documents/PerformanceChart.png)
[参照　CNTK GitHub repository read.me](https://github.com/Microsoft/CNTK)

また、Hong Kong Baptist University が出した各フレームワークのパフォーマンス比較の[論文](https://arxiv.org/pdf/1608.07249.pdf)を引用して、

- CNTK’s LSTM performance is 5-10x faster than the other toolkits.
- For convolution (image tasks), CNTK is comparable, but note the authors were using CNTK 1.7.2, and current CNTK 2.0 beta 10 is over 30% faster than 1.7.2.
- For all networks, CTNK's performance was superior to TensorFlow performance.

とも述べられています。

最近では Chainer の分散バージョンも開発されていて、そちらの開発元の PFN の検証 ([参照: @IT PFNの深層学習フレームワーク「Chainer」が大幅な高速化へ、分散処理に対応](http://itpro.nikkeibp.co.jp/atcl/news/17/012700269/))では、
シングルノードでは CNTK の方が未だパフォーマンスが出るものの、複数ノードでは開発中の分散 Version のChainerの方がパフォーマンスが出たそうです。日々追い付き追い越せの世界ですね。

ただ[公式ページ](https://github.com/Microsoft/CNTK)に、
" Historically, CNTK has been a pioneer in optimizing performance on multi-GPU systems. We continue to maintain the edge ([NVidia news at SuperComputing 2016](http://nvidianews.nvidia.com/news/nvidia-and-microsoft-accelerate-ai-together) and [CRAY at NIPS 2016](https://www.onmsft.com/news/microsoft-and-cray-announce-partnership-to-speed-up-deep-learning-on-supercomputers)). "
CNTK はマルチGPUでのパフォーマンス最適化のパイオニアであり、引き続きその Edgeで居続けられるようにすると書いてあるので、そこの部分にはこれからも期待できるのではないかとも思います。
パフォーマンスが出るということは、それだけ出費を抑えられるということ。クラウドで GPU を使用する場合、まだまだコストは大きいので、できるだけ稼働させる時間は減らしたいです。そういった意味ではありがたいですね。

### 注目度

日本では、Deep Learning のフレームワークでいうと、TensorFlow や Chainer、Caffe あたりが人気の印象がありますが、
Chainer と CNTK の GitHub レポジトリの 2017/3/20 時点での Star 数と Fork 数を比較すると、
![image](https://qiita-image-store.s3.amazonaws.com/0/104326/ad6e63f9-84b4-191e-1107-e9bdf600c296.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/104326/889d9cb5-6090-e71e-3440-509e11930ca8.png)


5 倍ほどの違いがあるようなので、グローバルレベルでは注目を集めてきているのでしょうか。

## 歴史
- Microsoft Reasearch の Speech Recognition の研究チームが内部使用のため 2012 年に開発開始（想像してたより昔からだった）
- 2014 年 8 月に CodePlex にてオープンソース化
- 2016 年 1 月に GitHub に移行されてさらに開発が加速

## Model Gallery について

公式ページ中には、[Model Gallery](https://www.microsoft.com/en-us/research/product/cognitive-toolkit/model-gallery/) のページの中に画像認識、言語理解、強化学習等々色々なサンプルが用意されています。
Python のみを選択した場合は、

- Image Recognition
- Finance Timeseries with CNTK, Pandas and Numpy
- Language Understanding with Recurrent Networks
- MNIST Feed Forward OCR
- Reinforcement Learning
- Sequence-to-Sequence
- Video Action Recognition
- Generative Adversarial Networks (GAN)

等々、現時点で 16 種類のサンプルとチュートリアルが用意されているようです。
Brain Script や Brain Script とPython 両方に提供されているものも含めると 48 種類あるようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/104326/ad7e10f2-f281-622d-1897-984974be632e.png)

そのサンプルのシナリオや実装を参考にすれば、ビジネスで需要のあるシナリオにも色々と活用できそうですし、けっこう役に立ちそうな印象です。
画像、スピーチ、テキスト等のカテゴリでも絞れるようになっていますし、どんな Example や Tutorial が用意されているかはぜひ [Model Gallery](https://www.microsoft.com/en-us/research/product/cognitive-toolkit/model-gallery/) からチェックしてみてください。

公式側に常に最新の API Version に合わせて更新される多岐に渡るサンプルがあるのはかなり嬉しいポイントじゃないかなと思います。（他のフレームワークで画像認識を行った際、Qiita 等できれいにまとまった情報を見つけても、試すとこの分野のフレームワークの更新が早い分、記事のコードそのままでは Deprecated になっていて動かなかったり、かといって公式でシナリオベースで情報を探しても Getting started 以上のものは中々わかりにくかったりしたので）

# お手軽環境構築
環境構築方法は[こちらの公式ページ](https://github.com/Microsoft/CNTK/wiki/Setup-CNTK-on-your-machine)に Linux, Windows それぞれにおける CPU, GPU 版がそれぞれ紹介されています。
細かいバージョンアップについていって楽をするためにも基本的には公式ページを参照してください。
一応 2017/4/23 時点での情報をまとめておきます。
共に想定環境は Python 3.5 です。Python 3.6 の場合は、pip install の中の数字を 35→36 に変更してください。
CNTK は Anaconda3 4.1.1 環境でテストがされているみたいなので、

* Windows をお使いの方は [Anaconda3 4.1.1 Python for Windows (64-bit)](https://repo.continuum.io/archive/Anaconda3-4.1.1-Windows-x86_64.exe)
* Linux をお使いの方は [Anaconda3 4.1.1 Python for Linux (64-bit)](https://repo.continuum.io/archive/Anaconda3-4.1.1-Linux-x86_64.sh)

を入れておいてください。

## Linux系 (Ubuntu 16.04) 
### CPU only
```
sudo apt-get install openmpi-bin
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.0rc2-cp35-cp35m-linux_x86_64.whl
```
### GPU
```
sudo apt-get install openmpi-bin
pip install https://cntk.ai/PythonWheel/GPU/cntk-2.0rc2-cp35-cp35m-linux_x86_64.whl
```

## Windows版
### CPU only
```
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.0rc2-cp35-cp35m-win_amd64.whl
```
### GPU
```
pip install https://cntk.ai/PythonWheel/GPU/cntk-2.0rc2-cp35-cp35m-win_amd64.whl
```

## すでに過去 Version を入れていた場合
```
pip install --upgrade --no-deps <url>
```

こちらの URL のところに該当する OS, デバイスにしたがって、上記の4パターンの中から該当する URL を入れれば過去の Version から最新の Version に更新することができます。

## Docker
MS 公式が Docker Hub に Docker Container のイメージも用意しています。
[こちら](https://hub.docker.com/r/microsoft/cntk/)には Python 3.5, 2.7 の CPU, GPU それぞれが用意されています。
GPU が使える最新版のイメージは常に以下のコマンドで pull できます。

```
docker pull microsoft/cntk
```
## Azure の場合
CNTK は Microsoft のフレームワークなので、やはり Azure 上でのサポートは手厚いです。
Linux での使用、Windows での使用共にテンプレートが準備されており、
Azure のポータル上でボタンを数回押せば、GPU が使えるように環境構築されたインスタンスが手に入ります。

### Windows版
[Deep Learning toolkit for Data Science VM](https://azuremarketplace.microsoft.com/ja-jp/marketplace/apps/microsoft-ads.dsvm-deep-learning?tab=Overview)
Windows 版の最初から GPU version で環境構築された VM イメージが出ています。

### Linux版
[Deep Learning on the New Ubuntu-Based Data Science Virtual Machine for Linux](https://blogs.technet.microsoft.com/machinelearning/2017/04/18/deep-learning-on-the-new-ubuntu-based-data-science-virtual-machine-for-linux/) という記事で解説されているように、2017/4/18 に機械学習によく使われるライブラリ群が含まれた VM イメージの GPU 対応版が出て、その中に CNTK も含まれています。
GPU を Deep Leraning Framework で使う際に環境構築が面倒くさい NVIDIA driver, CUDA, cuDNN も入っていますし、Open CV や matplotlib 等のライブラリも最初からプリインストールされていて非常に使いやすいと思います。ぜひこちらを使ってみてください。

他にも docker と nvidia-docker を入れて 

```
docker pull microsoft/cntk
```
で GPU version のイメージを pull する方法も用意されています。
nvidia-docker のインストール手順は[こちら](https://github.com/NVIDIA/nvidia-docker)から

また、複数 VM, 複数 GPU の 環境を簡単に構築するには [Azure Batch Shipyard Recipes](https://github.com/Azure/batch-shipyard/tree/master/recipes) あたりを読んでみるのがよさそうです。

Azure VM テンプレートイメージを使わずに１から環境構築をしたい場合は、Azure 上の GPU インスタンスの特徴とデプロイ、GPU ドライバを入れたり等々の仕方について、
[ついに来た！ Azure GPU インスタンス上に30分で構築する TensorFlow on GPU 実行環境構築手順](http://qiita.com/kosfuji/items/90e54fc0df3186d930de) で詳しくまとめたので、ぜひともそちらもご覧いただければと思います。

また本当に簡単に試すだけなら、Azure 上に CNTK の CPU 環境が構築されその上に Jupyter Notebook がホストされている [Azure Notebooks](https://notebooks.azure.com/CNTK/libraries/tutorials) もあるのでこちらで試してみるのもいいかも。

# 小学校の時の画風をゴッホに適用
これで環境構築も終わったので、ようやく楽しいパートをやってみましょう！
Jupyter Notebook のファイルが Tutorialsの中に上がっているので、こちらの [CNTK_205_Artistic_Style_Transfer.ipynb](https://github.com/Microsoft/CNTK/blob/master/Tutorials/CNTK_205_Artistic_Style_Transfer.ipynb) を順番になぞるだけです。
順番にコードを実行していくだけで、VGG-16 pre-trained model がダウンロードされ、Loss 関数が定義され、コンテンツ画像とスタイル画像がモデルに流し込まれる中でLoss を最適化しながら入力画像のコンテンツ画像側がスタイル画像の画風を取り込んでいきます。
各ステップでの操作とアルゴリズムの意味が Notebook に書かれているのもありがたいですね。

```
style_path = 'style.jpg'
content_path = 'content.jpg'
```

まずはとりあえず試したい場合は、Notebook 中の上の画像のパスを他のものに差し替えれば好きなパターンで動きます。

ということで、ゴッホのひまわりに小学校時代の自分のスタイルを適用してみました！

| コンテンツ画像 | スタイル画像 |
|:-----------:|:------------:|
|![s_sunflower.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/2a5cef7b-c1b2-7f33-e3b5-eef79f0e9307.jpeg)| ![s_young_pic.JPG](https://qiita-image-store.s3.amazonaws.com/0/104326/7560a1fa-55c1-acef-9151-00323eb69ff3.jpeg) |

**結果は…？**

![outputgoh_9.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/2236be4b-9229-cdda-af31-7a075cc18a1b.jpeg)

少し狂気じみた化け物ヒマワリがこの世に生み落とされてしまいました。

せっかくなので海外の作品だけではなく日本の誇る **葛飾北斎の「富嶽三十六景」**

| コンテンツ画像 | スタイル画像 | 
|:-----------:|:------------:|
|![s_The_Great_Wave_off_Kanagawa.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/e9d00cdd-420b-b928-630f-2a641fd3274f.jpeg)| ![s_young_pic.JPG](https://qiita-image-store.s3.amazonaws.com/0/104326/7560a1fa-55c1-acef-9151-00323eb69ff3.jpeg) |

**結果は…？**

![The_Great_Wave_off_Kanagawa_9.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/bd0cd3cf-0a60-21dd-9119-b02ce3246028.jpeg)

大分メルヘンチックな感じになりました笑
これは結構好き。

最後にもう一つ。
CNTK のチュートリアルで使われていた風景写真にも適用してみることにします。

| コンテンツ画像 | スタイル画像 | 
|:-----------:|:------------:|
|![content.png](https://qiita-image-store.s3.amazonaws.com/0/104326/d0ddd1a9-6218-fd16-e40c-b0e35f625834.png)|  ![s_young_pic.JPG](https://qiita-image-store.s3.amazonaws.com/0/104326/7560a1fa-55c1-acef-9151-00323eb69ff3.jpeg) | 


**結果は…？**

![output_9.jpg](https://qiita-image-store.s3.amazonaws.com/0/104326/ff20235b-ed6b-2f54-9168-978234353fd7.jpeg)

風景の面影が大分破壊されているような気もしますが、またまたメルヘンチックな感じで描かれました。
写真だったものが手書きの温かみが感じられる絵に変わるのは面白いですね。

CNTK で提供されているサンプルは、以下の二つの論文に基づいているとのことです。
[A Neural Algorithm of Artistic Style](https://arxiv.org/abs/1508.06576) , Gatys et. al.
[Improving the Neural Algorithm of Artistic Style](https://arxiv.org/abs/1605.04603) , Novak and Nikulin


# 今後のロードマップ (Keras の Backend への採用)

2016年10月19日開催の GTC Japan 2016 での Microsoft Research の人の CNTKのセッションでは今後のロードマップも話されていました。（その際の[スライド](https://www.gputechconf.jp/assets/files/1019.pdf)）
そこには Kerasの Backend への CNTK の統合という話もありました。
調べてみると、Keras 側の repository の [issues](https://github.com/fchollet/keras/issues/2370) に 
**feature request: more backends**
Theano can only support multiple GPU using OpenCL but not CUDA, tensorflow seems slower than other framework using GPU for now.
と書いてあってそこから統合の話が始まったのかもしれません。
CNTK 側の issues にも[このように](https://github.com/Microsoft/CNTK/issues/797)取り上げられています。
最新の情報に関しては Keras 側の repository の [issues](https://github.com/fchollet/keras/issues/5299)に2017年2月7日に
Additionally, **Microsoft is building a CNTK backend for Keras.** 
Microsoft が Keras の CNTK backend を開発中だと書いてあります。
近いうちに出てくるかもしれません。そうなってくると Keras の Backend にパフォーマンスの高い CNTK を使うという流れも出てくるかも。今後に期待ですね。新情報があった場合は更新を行いたいと思います。