Windows 10とTensorFlowでGPU Deep Learning学習環境を構築してみた（TensorFlow 2.3 と RTX で Tensor Coreと混合精度）

新しい記事は[こちら](https://qiita.com/kekekekenta/items/ad737c8de0eb9609f991)です。[Windows 10 と NVIDIA RTX で TensorFlow 2.4 を動かす](https://qiita.com/kekekekenta/items/ad737c8de0eb9609f991)

こんにちは。2018年12月に Windows 10 の Deep Learning モデル開発環境を紹介しましたが、約2年経過し色々環境が変っているので、2020年9月時点の環境構築方法を紹介します。NVIDIA GeForce RTX 2070 が搭載された Windows 10 に TensorFlow をインストールしていきます。

- 2018年12月の「Windows 10にNVIDIA GPUを使用したDeep Learning環境をインストール。（CUDA10、VS2017、Chainerのインストール）」
 - https://qiita.com/kekekekenta/items/a46a899956b1c756ddce

あと、動作確認のプログラムも載せてほしいとコメントも頂いていたので、せっかくのGeForce RTXなので、TensorFlow 2.3 を使用した 混合精度 と Tensor Core も動かしてみました。（プログラムとしては、GeForce GTX でも動きますが、混合精度 や Tensor Core に関してはGeForce RTX のように速くは動きません。今なら[RTX 2060 Super](https://amzn.to/2HbS2Db)とかお手頃かも。あ買うまでもなくクラウドで試したい場合は、Azureの[NCv3シリーズ](https://docs.microsoft.com/ja-jp/azure/virtual-machines/ncv3-series)をご利用ください。）

混合精度については@ksasakiさんの記事を参考にしてください
https://qiita.com/ksasaki/items/52a829b63c8deb022c50#%E6%B7%B7%E5%90%88%E7%B2%BE%E5%BA%A6%E3%83%88%E3%83%AC%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0

Tensor Coreについても同じく@ksasakiさんの記事をご参考に
https://qiita.com/ksasaki/items/52a829b63c8deb022c50#tensor-%E3%82%B3%E3%82%A2%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BE%E3%81%99%E3%81%8B

Deep Learning 環境としては Linuxを使用した記事が多く紹介されていますが、Windows 10 は使いやすいディスクトップ環境と NVIDIA GPUを使うことができるので、モデル開発作業環境としては最適だと思います。(WSL2 が使えるようになると更に色々できるようになりますが、今回は Windows ネイティブ（？）です。)

# NVIDIA CUDA と cuDNN のインストール
まず、最新のNVIDIAドライバをインストールしてください。TensorFlow2.3の場合は、CUDA 10.1 と cuDNN 7.6.x をNVIDIAのサイトからダウンロードしてください。

- NVIDIAドライバダウンロード
 - https://www.nvidia.co.jp/Download/index.aspx?lang=jp
- CUDA Toolkit 10.1
 - https://developer.nvidia.com/cuda-toolkit-archive
- The NVIDIA CUDA® Deep Neural Network library (cuDNN) for CUDA 10.1
 - https://developer.nvidia.com/rdp/cudnn-archive
 - （Downloadページから、「Download cuDNN v7.6.5 (November 5th, 2019), for CUDA 10.1」を選択、次に「cuDNN Library for Windows 10」を選択してダウンロードを行います。）

初めにCUDAのインストーラーを実行してインストールします。CUDAをインストールした後にcuDNNをインストールします。ダウンロードしたcuDNNのzipを展開して、CUDAのインストールフォルダ（C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1 ）にコピーします。CUDAのフォルダ名称に合わせてcuDNNのファイルをコピーしてください。なお、cuDNNのダウンロードには、ユーザの登録が必要になりますので、先に登録しておいてください。

# Pythonのインストール
プログラミング環境を整えていきます。機械学習をはじめとしたプログラミング言語としてはPythonが人気です。Python環境としてはAnacondaが有名で分析や機械学習を行うためのライブラリも問題なく利用できます。

Anacondaは下記のサイトよりダウンロードします。利用しているOSに合わせて適切なパッケージをインストールしてください。ボタンをそのままクリックし続ける（標準の設定）だけで大丈夫です。

- Anaconda Download
 - https://www.continuum.io/downloads

## Python の 環境の作成
スタートメニューからAnaconda Promptを実行して、環境を作成していきます。環境を作ることで作業環境を分けることができます。

```powershell
conda create -n py38 python=3.8
```

# TensorFlow のインストール
TensorFlowをインストールします。TensorFlowは容易に複雑なネットワークを作ることができるDeep Learningのフレームワークです。

インストールする前に環境を先ほど作成した環境に変えておきます。

```powershell
activate py38
```

次に、下記のコマンドでTensorFlowをインストールします。

```powershell
pip install tensorflow==2.3
```
# TensorFlow で GeForce RTX の機能を使ってみる

ソースコードは、以下のGitHubに mnist の Jupyter notebook として置いておきました。RTX 2070で動かしています。

https://github.com/KentaroAOKI/tf_tensorcore_test/blob/master/tensorcore_test-mixed_float16.ipynb
（https://www.tensorflow.org/guide/mixed_precision より)

## 混合精度
混合精度を使う場合、mixed_precision.set_policyで'mixed_float16'を設定します。以下の箇所で設定しています。
トレーニングの速度を確認したい方は、mixed_precision.set_policyで'float32'を設定するか、以下の箇所を実行しないでトレーニングを実施してください。
https://www.tensorflow.org/api_docs/python/tf/keras/mixed_precision/experimental/Policy

```python
policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_policy(policy)
print('Compute dtype: {}'.format(policy.compute_dtype))
print('Variable dtype: {}'.format(policy.variable_dtype))
```
## Tensor Core
Tensor Coreは、次元を8の倍数にすることにより動作します。以下の箇所でDenseのユニット数を設定しています。
トレーニングの速度を確認したい方は、num_units を 4095 など8の倍数ではない数字を設定してみてください。

```python
if tf.config.list_physical_devices('GPU'):
  print('The model will run with 4096 units on a GPU')
  num_units = 4096
```

Dense以外では、以下のように8の倍数を設定することによりTensorCoreが使われるようです。
https://www.tensorflow.org/guide/mixed_precision#gpu_performance_tips

```python
tf.keras.layers.Dense(units=64)
tf.keras.layers.Conv2d(filters=48, kernel_size=7, stride=3)
tf.keras.layers.LSTM(units=64)
tf.keras.Model.fit(epochs=2, batch_size=128)
```

以下に、4096のDenseと、4095のDenseの結果を載せておきます。

4096（8の倍数）の場合（RTX 2070）

```
Epoch 1/5
6/6 [==============================] - 0s 77ms/step - loss: 3.8920 - accuracy: 0.4055 - val_loss: 0.7667 - val_accuracy: 0.7740
Epoch 2/5
6/6 [==============================] - 0s 53ms/step - loss: 0.7409 - accuracy: 0.7681 - val_loss: 0.4063 - val_accuracy: 0.8844
Epoch 3/5
6/6 [==============================] - 0s 53ms/step - loss: 0.3158 - accuracy: 0.9053 - val_loss: 0.4937 - val_accuracy: 0.8342
Epoch 4/5
6/6 [==============================] - 0s 50ms/step - loss: 0.3538 - accuracy: 0.8878 - val_loss: 0.2201 - val_accuracy: 0.9359
Epoch 5/5
6/6 [==============================] - 0s 49ms/step - loss: 0.1910 - accuracy: 0.9427 - val_loss: 0.2384 - val_accuracy: 0.9235
313/313 - 1s - loss: 0.2396 - accuracy: 0.9224
Test loss: 0.23963715136051178
Test accuracy: 0.9223999977111816
```

4095（8の倍数ではない）の場合（RTX 2070）

```
Epoch 1/5
6/6 [==============================] - 1s 155ms/step - loss: 7.9496 - accuracy: 0.3171 - val_loss: 1.3666 - val_accuracy: 0.6119
Epoch 2/5
6/6 [==============================] - 1s 131ms/step - loss: 0.9348 - accuracy: 0.7105 - val_loss: 0.6787 - val_accuracy: 0.7974
Epoch 3/5
6/6 [==============================] - 1s 131ms/step - loss: 0.4062 - accuracy: 0.8820 - val_loss: 0.2575 - val_accuracy: 0.9198
Epoch 4/5
6/6 [==============================] - 1s 131ms/step - loss: 0.3525 - accuracy: 0.8835 - val_loss: 0.2172 - val_accuracy: 0.9347
Epoch 5/5
6/6 [==============================] - 1s 129ms/step - loss: 0.2179 - accuracy: 0.9338 - val_loss: 0.4614 - val_accuracy: 0.8520
313/313 - 1s - loss: 0.4632 - accuracy: 0.8520
Test loss: 0.4632183015346527
Test accuracy: 0.8519999980926514
```

おまけ、GTX 1070 の結果

```
Epoch 1/5
6/6 [==============================] - 1s 184ms/step - loss: 0.2427 - accuracy: 0.9254 - val_loss: 0.4252 - val_accuracy: 0.8668
Epoch 2/5
6/6 [==============================] - 1s 178ms/step - loss: 0.2358 - accuracy: 0.9268 - val_loss: 0.1491 - val_accuracy: 0.9532
Epoch 3/5
6/6 [==============================] - 1s 178ms/step - loss: 0.3751 - accuracy: 0.9006 - val_loss: 0.1945 - val_accuracy: 0.9454
Epoch 4/5
6/6 [==============================] - 1s 179ms/step - loss: 0.1235 - accuracy: 0.9646 - val_loss: 0.1145 - val_accuracy: 0.9638
Epoch 5/5
6/6 [==============================] - 1s 178ms/step - loss: 0.1186 - accuracy: 0.9636 - val_loss: 0.1877 - val_accuracy: 0.9424
313/313 - 1s - loss: 0.1996 - accuracy: 0.9372
Test loss: 0.19959908723831177
Test accuracy: 0.9372000098228455
```

# NVIDIA GPUの状態を知る
あと、下記のコマンドを使うことによりGPUの状態を知ることができます。

```powershell
cd C:\Program Files\NVIDIA Corporation\NVSMI
nvidia-smi.exe
```

```
(py38) C:\Program Files\NVIDIA Corporation\NVSMI>nvidia-smi.exe
Fri Sep 18 01:39:16 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 426.00       Driver Version: 426.00       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name            TCC/WDDM | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 2070   WDDM  | 00000000:01:00.0  On |                  N/A |
| 41%   38C    P8    13W / 185W |   1078MiB /  8192MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+
```

# さいごに
WSL2が使えるようになったら、公開されているdockerイメージが使えるようになりそうですね。

WSL2も@ksasakiさんの記事がお勧めです。
https://qiita.com/ksasaki/items/ee864abd74f95fea1efa

WSL2が使えるようになったとしても、LinuxでもWindowsでも動くPythonコードを書くように心がけるのが大事だとおもいます。
GeForce RTX 30-が気になるー。d(´∀`*)ではー。