オブジェクト指向の申し子!?JavaでDeep Learningをやってみた(お試し編)

[FUJITSU Advent Calendar 2019](https://qiita.com/advent-calendar/2019/fujitsu) 23日目の記事です。
オブジェクト指向の申し子的言語と言えばJavaなのではないでしょうか？歴史的にはC++やSmalltalkが先に世に出た様ですが、Cとの互換性を考慮して開発されたC++はオブジェクト指向による実装を強制しません。Smalltalkに至っては筆者は寡聞にしてその存在を知りませんでした。。。:sweat_smile:以前ある書籍で「再利用性を考慮したプログラムを比較的簡単に実装できる開発思想＝オブジェクト指向」を代表する言語はJavaと読んだ記憶が有りますが、あながち間違っていないのではないかと思います。[人気プログラミング言語の変遷、1965～2019年（Python視点）](https://www.atmarkit.co.jp/ait/articles/1911/25/news031.html)からも分かりますが、ソフトウェア開発でも広く利用されて来た言語です。因みに社内のソフトウェア開発では現在でも圧倒的なシェア！？を握っている様です。(俗説で統計データは有りません:sweat_smile:)但し、近年はPythonの様な生粋のオブジェクト指向言語では無い？言語の台頭も有り、今後勢力図が書き換わるやもしれません。。。:scream:

## やりたいこと
前置きがとても長くなりましたが、要はJavaでDeep Learningをやってみると言うのが本記事の内容です。

## なぜJavaなのか？
競技プログラミングが三度の飯より好きな友人が、以前はJavaでプログラミングをやっていたのが、最近Rustに乗り換えたと言っていました。何でも流行の言語をやってみたかったとのこと。前掲の[人気プログラミング言語の変遷](https://www.atmarkit.co.jp/ait/articles/1911/25/news031.html)からも分かる様にどうも他の言語に押され気味のJava。。。古い言語という様な表現する人も居たりと散々の扱い。。。オブジェクト指向の申し子がまだまだ現役で戦えるということを証明するには昨今流行のDeep Learningをやってのけるぐらいのことをやらなければと思いやってみました。但し、今回は表題にも有る通りお試し編です。:dancer_tone1::dancer::dancer_tone2::dancer_tone3::dancer_tone4::dancer_tone5:

![samurai-duke.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/a9f7516a-637d-e001-7c62-ad7e9207cce9.png)
The Last Java Samurai[^samurai]

:yum: 因みに筆者は非情報系の出身で、学生時代にJavaを勉強しようとして挫折し、入社後勉強してJavaの良さが初めて分かりました。

## Java ∩ Deep Learning ∩ OSSが実は存在する
Deep Learningを含む機械学習の世界ではPythonが圧倒的なシェアを握り、大半のOSS機会学習用ライブラリもPythonで実装されていますが、以前からJavaでDeep Learningのモデルを用いて学習や推論が可能なOSS[^4j]は有りました。しかし、今回は2019年12月3日に新しくリリースされたOSS「[Deep Java Library (以下DJL)](https://djl.ai/)[^djl]」を使ってみようと思います。

## Deep Java Library (DJL) でDeep Learning (漸く本題)
記事が長くなってしまっていますが漸く本題です。現在の所、頼れる情報は[公式サイト](https://djl.ai/)や[参考記事](https://qiita.com/omix222/items/b77d8f8102f56458d39d)だけの様です。:scream: :ghost:

<img width="1440" alt="djl.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/a89c3bc1-e6bd-3e11-cf52-ab1ac5608675.png">

### 環境構築
[参考記事](https://qiita.com/omix222/items/b77d8f8102f56458d39d)では[Gradle](https://gradle.org/)を用いた方法でAWS上で環境構築を行っていましたが、今回はローカル環境でDocker + Jupyter Notebookを用いてコンテナ上で実行する方法を採用したいと思います。Jupyter NotebookはPython用の可視化ツールというイメージが有りますが、最近は多言語対応が進んでおり、益々便利になっています。

#### 実行環境
macOS Mojave 10.14.6(CPU:Corei5-8210Y 1.6GHz, DRAM:16GB)[^nogpu]
Docker 19.03.5

#### ソースのクローン
[GitHub](https://github.com/awslabs/djl)からリポジトリをクローンします。

```bash
git clone https://github.com/awslabs/djl.git
```

#### `djl`ディレクトリ配下の`jupyter`ディレクトリに移動

```bash
cd djl/jupyter/
```

#### コンテナの起動

```docker
docker container run -itd -p 127.0.0.1:8888:8888 -v $PWD:/home/jupyter deepjavalibrary/jupyter
```

Dockerfileを編集してイメージをビルドすることも出来ますが、今回はデフォルトのまま起動しました。

#### コンテナの起動確認

```docker
$ docker container ls
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                      NAMES
03791a7b1641        deepjavalibrary/jupyter   "jupyter notebook --…"   4 minutes ago       Up 4 minutes        127.0.0.1:8888->8888/tcp   suspicious_brattain
```

### Jupyterを起動

`http://localhost:8888`にアクセスして以下のページが表示されれば成功です。

<img width="1440" alt="jupyter.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/7ae0cd0f-49e1-f74e-04b1-a72903fd799c.png">

よく見るとチュートリアルが各々のノートブックとして既に格納済です。Javaでやると豪語しつつJupyter Notebookのお手軽さに屈してしまいました。。。:sob:


### Multi Layer Perceptron (MLP) の実行

`train_your_first_model.ipynb`を起動します。MLPを用いた手書き文字認識(MNIST)のサンプルです。学習の実行はShit + Enterで順にセル上のコマンドを実行していくだけです。とてもお手軽に実行出来ます。main関数やclassの記述も不要なのには最初驚きました。

<img width="1440" alt="mlp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/11444ddf-3116-d374-c2ca-e25862f209d1.png">

モデル保存時に以下のメッセージが出力されました。正答率が約97%ですが、これはあくまで学習時の評価用データでの数値で、今回テストデータによる正答率は測定していません。。。。:stuck_out_tongue_closed_eyes:

```
Model (
	Name: mlp
	Model location: /home/jupyter/build/mlp
	Data Type: float32
	Accuracy: 0.96991664
	Epoch: 2
)
```


### Model Zoo(Deep Learning)で推論を実行
今回はオブジェクト認識のサンプルを実行してみます。`object_detection_with_model_zoo.ipynb`を起動します。前掲の[参考記事](https://qiita.com/omix222/items/b77d8f8102f56458d39d)でModel Zooを試していたため、別のサンプルを試そうと思ったのですが、ライブラリの詳細な使い方をまだ理解出来ていないのと、学習には矢張りGPU環境が必須であるため(CPUではMLPの学習でも時間が。。。)今回は学習済モデル([SSD:Single Shot MultiBox Detector](https://qiita.com/YutoHagiwara/items/4b66442ff1e09936f1d0))によるオブジェクト認識(推論)を試しました。

<img width="1440" alt="modelzoo.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/53cd86af-553f-bc2c-d90e-90ab1ca22522.png">

オブジェクト認識を以下の画像で試します。犬、自転車、車が写っている写真です。

<img width="1440" alt="dog_byke_car.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/2abdf729-ffc5-57ea-6874-723036f82a54.png">

#### 推論結果
実行結果を以下に示します。正しくオブジェクト(犬、自転車、車)を認識出来ています。

<img width="1440" alt="detection_results.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/fdc4c9c4-0427-2ca3-ae13-7d833f864b62.png">

推論結果(数値)を以下に示します。各々のオブジェクトが高い確度で認識されていることが分かります。

```
[
	class: "car", probability: 0.99991, bounds: [x=0.612, y=0.137, width=0.293, height=0.160]
	class: "bicycle", probability: 0.95365, bounds: [x=0.162, y=0.207, width=0.594, height=0.590]
	class: "dog", probability: 0.93471, bounds: [x=0.168, y=0.350, width=0.274, height=0.594]
]
```


## まとめと今後の課題
JavaでDeep Learningが実行可能なJDLを試しました。AWS上での実行を想定している様ですが、ローカル環境上のDockerでも問題無く動作しました。今回はお試し編でしたが、今後調査を進めてもう少し高度なことに挑戦したいと思います。最後に今後の課題を以下に記載します。

* GPU環境への導入(まずはGPUマシーンの構築から)
* 各種APIやモジュールの使い方を調査して自分で実装したモデルの学習、評価等まで実行

以上、オブジェクト指向の申し子によるDeep Learningの実行お試し編でした。来年も頑張って記事の投稿を続けていきたいと思います。

[^samurai]: https://blog.heroku.com/samurai-duke-and-the-legend-of-openjdk

[^4j]: [Deeplearning4j](https://deeplearning4j.org/)です。日本語の書籍として「[Deep Learning Javaプログラミング 深層学習の理論と実装 (巣籠 悠輔著; インプレス; 2016年)](https://www.amazon.co.jp/Deep-Learning-Java85-impress/dp/4844381288)」が出版されています。
[^djl]: AWSでの利用を想定して開発された様です。([参考情報](https://aws.amazon.com/jp/about-aws/whats-new/2019/12/introducing-deep-java-library-develop-and-deploy-machine-learning-models-in-java/))

[^nogpu]: 今回はDJLを試してみることを目標としているため、GPU＋CUDAが動作する環境ではなく、CPU上で実行します。故に、今回の検証はMulti Layer Perceptronの学習やDeep Learningの学習済モデルを用いた推論を試すことに留めます。GPU上での動作は後日試してみることにします。