DeepLearning ハンズオン @ MaruLabo × JAWS-UG #2

# この資料で書いていること

ディープラーニング・ハンズオン [@MaruLabo × JAWS-UG AI #2](https://jawsug-ai.connpass.com/event/50202/) で利用する資料です。


# ハンズオン環境

* Python2 系 GPU / CPU 版 TensorFlow
* AWS の設定
 - 本ハンズオン用に作成した AMI を利用
 - GPU インスタンス（使えない方は CPU 版を利用）
 - ポートは TensorBoard に 6006、とデモアプリに 80 を開放


# 1. AWS マネジメントコンソールでの操作


## 1.1 マネジメントコンソールにログイン

https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Instances

* 今回のハンズオンは無料枠の範囲ではないインスタンスタイプを利用します
* クーポンを利用する際は該当のアカウントであることを確認しましょう


## 1.2 AMI の指定

以下のリンクをクリックし、ハンズオンに利用する AMI を選択します。

▼ バージニアリージョンなら

https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#LaunchInstanceWizard:ami=ami-821fcb94

▼ オレゴンリージョンなら

https://console.aws.amazon.com/ec2/v2/home?region=us-west-2#LaunchInstanceWizard:ami=ami-f9ba3b99

* NVIDIA ドライバ 367.48、CUDA 8.0、cuDNN 5.1 がインストールされています
* 本ハンズオン後に非公開にします（※事情: ライセンス）


## 1.3 GPU インスタンスの指定

*  `g2.2xlarge` を選択します
*  **GPU 起動を事前に申請できなかった方**は `c4.4xlarge` を
*  `次の手順: インスタンスの詳細を設定` に進みましょう

![gpu.png](https://qiita-image-store.s3.amazonaws.com/0/66457/2afd781a-64bf-a774-db39-5d5d71a98a97.png)


## 1.4 パブリック IP などの確認

* **自動割り当てパブリック IP** が `有効` であることを確認
* EC2 に慣れている方は `スポット価格の設定` もぜひどうぞ
* `次の手順: ストレージの追加` に進みましょう

![type.png](https://qiita-image-store.s3.amazonaws.com/0/66457/b68ba320-9be0-cfd8-9767-cc07f1c0c44c.png)


## 1.5 公開ポートの設定

* `ストレージ` と `タグ` の設定はそのまま次の手順へ
* `ルールの追加` から、**80 番**と **6006 番**ポートを追加
* `確認と作成` を押します

![sg.png](https://qiita-image-store.s3.amazonaws.com/0/66457/cede0c58-5695-4c02-1259-75f48cd04677.png)


## 1.6 起動インスタンスの確認

* **cuDNN v5.1 for CUDA 8.0 on Ubuntu 16.04**
* g2.2xlarge（または c4.4xlarge）
* 22 / 80 / 6006 番ポートの解放
* `作成` を押します

![confirm.png](https://qiita-image-store.s3.amazonaws.com/0/66457/c738ff33-4d95-5e88-28f7-386aec20099e.png)


## 1.7 SSH 鍵のダウンロード

* `新しいキーペアの作成` を選択します
* 適当な名前をつけて `キーペアのダウンロード` を押しましょう
* `インスタンスの作成` を押します

![create.png](https://qiita-image-store.s3.amazonaws.com/0/66457/fa7fdd66-be0e-7afd-4283-113096e6406e.png)


# 2. TensorFlow 動作確認


## 2.1 サーバのパブリック IP の確認

起動したインスタンスを選択し、パプリック IP アドレスを確認します。
https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Instances

![public-ip.png](https://qiita-image-store.s3.amazonaws.com/0/66457/a611417f-a8a2-d666-72a3-43b0cf5f6d41.png)


## 2.2 サーバへ SSH 接続

* ダウンロードした pem を使って SSH ログイン
* 不慣れな方は [こちら](http://dev.classmethod.jp/cloud/aws/aws-beginner-ec2-ssh/) をご覧ください..
* ユーザ名は `ec2-user` ではなく `ubuntu` です。ご注意を。

```sh:例
$ chmod 400 keypair.pem
$ ssh -i keypair.pem ubuntu@<ec2.public.ip.address>
```


## 2.3 GPU の確認

* （GPU でない方は飛ばしてください）
* Deep Learning AMI はなんと NVIDIA ドライバもインストール済！
* 以下のコマンドで GPU の状況を確認してみましょう

```sh
$ nvidia-smi

Mon Feb 20 07:20:25 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GRID K520           Off  | 0000:00:03.0     Off |                  N/A |
| N/A   37C    P8    17W / 125W |      0MiB /  4036MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```


## 2.4 TensorFlow のインストール

**GPU 版** TensorFlow のインストール[^1]

```sh
sudo apt install -y python-pip
pip install "tensorflow_gpu==0.12"
```

**CPU 版** TensorFlow のインストール

```sh
sudo apt install -y python-pip
pip install "tensorflow==0.12"
```

以下共通

```sh
# TensorFlow バージョン確認 (応答まで 1 分程度かかります）
python -c 'import tensorflow as tf; print(tf.__version__)'

# 確認用 Python スクリプトの取得
git clone --depth 1 https://github.com/tensorflow/tensorflow.git
cd tensorflow/tensorflow/examples/tutorials/mnist/

# MNIST (softmax 版) の動作確認
python mnist_softmax.py

# MNIST (DNN 版) の動作確認
python fully_connected_feed.py
```




# 3. TensorFlow 実習

## 3.1 デモアプリ概要

以下のアプリは、MaruLabo 管理者の [古川さん](http://qiita.com/ornew) が作成したものです。
TensorFlow チュートリアル「Deep MNIST for Experts」（[原文](https://www.tensorflow.org/versions/r0.11/tutorials/mnist/pros/)｜[翻訳](http://ornew.net/tensorflow-deep-mnist-for-experts)）のMNIST モデルの学習状況をブラウザで閲覧できるようにしたものです。

## 3.2 デモアプリのダウンロード

```
cd ~
wget https://github.com/ornew/mnist-visual/releases/download/v3.0.1/mnist-visualize-example_3.0.1.tar.gz
tar zxvf mnist-visualize-example_3.0.1.tar.gz
cd ~/mnist-visualize-example_3.0.1
```

## 3.3 サンプルサーバの起動

```
# 依存パッケージのインストール
pip install scipy tornado futures Pillow

# (GPU 版のみ) CUDA ライブラリのリンク
sudo ldconfig /usr/local/cuda/lib64

# 起動
sudo python server.py -p 80
```

## 3.4 Web ブラウザから訓練を実施

パプリック IP アドレスをブラウザの URL に入力してアプリに接続します。

ブラウザでアクセスしたら「**訓練を開始する**」というボタンを押してください。少し待っているとテスト結果が表示され始めます。

## 3.5 テスト結果の見方

- 緑 → テストで正解したもの
- 赤 → テストで間違えたもの

![スクリーンショット 2017-01-16 13.59.17.2.png](https://qiita-image-store.s3.amazonaws.com/0/143108/cfab7938-0dcc-9395-119d-72aab9846faf.png)

### 参考: 100 ステップ目

![スクリーンショット 2017-01-16 13.59.17.png](https://qiita-image-store.s3.amazonaws.com/0/143108/70e2b2ac-2066-b514-3e23-6e543f1f6c66.png)

### 参考: 1,000 ステップ目

![スクリーンショット 2017-01-16 13.59.27.png](https://qiita-image-store.s3.amazonaws.com/0/143108/6c41774e-bde1-3234-c3d1-4f6cc6f5abd9.png)

### 参考: 20,000 ステップ目

![スクリーンショット 2017-01-16 15.34.28.png](https://qiita-image-store.s3.amazonaws.com/0/143108/4d0bef94-f465-5ba1-17a2-38b8dc76e1f0.png)

## 3.6 手書きテスト

実際に訓練で作ったモデルを試すことが出来ます。ステップを選択したら、枠線の中に数字を書いて評価してみてください。下部に結果と分布が表示されます[^2]。

![スクリーンショット 2017-01-18 23.11.38.png](https://qiita-image-store.s3.amazonaws.com/0/143108/ffebe823-0cd0-0ecd-cd90-9ea15481a37f.png)

同じ数字のまま、ステップだけを切り替えてみると、学習状況によって判定が変わっていくのが確認できます。「なんとなく精度が上がっている」のが見てとれると思います。

## 3.7 TensorBoard の起動・アクセス

```
tensorboard --logdir ~/mnist-visualize-example_3.0.1/var --noinspect &
```

この状態でインスタンスの IP アドレスの 6006 番ポートにアクセスすると TensorBoard にアクセスできます。

## 3.8 クロスエントロピーの推移

精度が上がっていることをきちんと数値で示すと以下のようなグラフになります。これは、クロスエントロピーの値を学習ステップごとにプロットしたものです。

<img width="1008" alt="スクリーンショット 2017-01-16 19.00.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/143108/76c1c54b-e07b-479e-b0c1-16a56ac910fc.png">

最初の 100 ステップで大幅に下がったのち、徐々に 0 に収束していくのが確認できます。

## 3.9 誤差の評価

このモデルでは、算出した確率分布と本当の答えが「どのくらい間違ってるのか」（これは、見方を変えれば「どのくらい正しいのか」を示す値でもあります）をクロスエントロピーという手法で定式化して計算しています。

```python
cross_entropy = tf.reduce_mean(
  tf.nn.softmax_cross_entropy_with_logits(
    inference, # 予測された値
    label))    # 正解の値
```

この値は、両者の値の誤差を示すもので、両者の値が近づくほどに小さくなります。つまり、この値が０に収束するということは、正解の値に近づいている＝精度が上がっているということを示します。

## 3.10 誤差をどうやって小さくしている？

```
tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
```

このプログラムは、「cross_entropy を最小化するようにグラフを ADAM オプティマイザで最適化する」という意味です。

ディープラーニングでは、この誤差が小さくなるように確率的勾配降下法などを利用してモデルを訓練をしていくのが一般的です。このサンプルでは ADAM オプティマイザを利用しています。

TensorFlow では、この一行ですべてやってくれます。学習率を調整したければ`1e-4` を変更するだけです。ADAM オプティマイザ以外の最適化アルゴリズムも組み込みで用意されています。理論を知らなくても、TensorFlow に組み込みのオプティマイザを使うことができますし、独自のものを自分で定義する能力も TensorFlow には用意されています。

　

[^1]: ここで `0.12` を指定せず `pip install tensorflow_gpu` とすれば、v1.0 がインストールされます。
[^2]: この分布はソフトマックスで正規化して**いません**。これは、訓練によって中身がどう変わっているのかを直感的に確認することが、このサンプルの目的であるためです。意図的なものです。