Anaconda + Keras でGPUを使用する環境を構築する

#はじめに
Keras（Tensorflow）でGPUを利用するための手順は、調べればいくらでも情報がでてきます。
逆を言えば、みんな躓いてるんだなぁ...って思いました。

私は、`バージョンの対応関係の把握`と`GPUが使われてるかどうかの確認の仕方`に手間取ったので、そこを注視してまとめてみました。

# 追記（2021/07/13）
仮想環境として**venv**を使った環境構築方法もまとめました。
基本的には本記事と同じですが、**tensorflow-gpu 2.4.0**を使用して環境構築をしています。

https://qiita.com/nemutas/items/86563b164b72ca41c7d6

#環境
Windows10 Pro
NVIDIA GeForce GTX 1070 Ti
MSVC 2017 (Microsoft Visual Studio C++)
CUDA v10.0
cuDNN 7.4

Python 3.6
Anaconda
TensorFlow-GPU 2.0.0
Keras 2.3.1

#一番重要なこと
***バージョンの確認です***

最初に、インストールするモノのバージョンの対応関係を抑えておきます。

まず、今回使いたい`Keras`が対応している`Python`のバージョンを調べます。
ドキュメントによれば、「KerasはPython 2.7-3.6に対応しています．」となっています。
つまり、対応しているもので最新の`Python 3.6`を使うことになります。
https://keras.io/ja/

次に、`Python 3.6`に対応している`tensorflow_gpu`のバージョンを調べます。
対応しているもので最新の`tensorflow_gpu-2.0.0`を選択しました。
また、これに対応する`MSVC`のバージョン`2017`、`cuDNN`は`7.4`、`CUDA`は`10.0`であることがわかりました。
https://www.tensorflow.org/install/source_windows?hl=ja
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/44b5ab34-c4cc-8315-0751-1d7b4518abfc.png)


まとめると、インストールするバージョンは以下のようになります。

- Python（3.6）
- TensorFlow-GPU（2.0.0）
- MSVC（2017）
- cuDNN（7.4）
- CUDA（10.0）

#仮想環境の構築
バージョンに配慮が必要なため、仮想環境を構築する必要があります。
私は、GUIナビゲーターで仮想環境を管理できる「Anaconda」を利用しています。
※インストールは[こちら](https://buralog.jp/python-execute-from-vscode/)を参考に。VSCodeと絡めた開発環境を構築しています。

ナビゲーターを起動して、「Enviroments」から「Create」を押して、仮想環境を作成します。
Pythonのバージョンは、先ほど確認した`3.6`を選択します。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/e31848cb-89d8-6533-a6e7-cad75296260d.png)
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/dae6a6c1-393e-b11e-8c55-58abcaabd819.png)

#MSVC（Microsoft Visual Studio C++）のインストール
[tensorflowのドキュメント](https://www.tensorflow.org/install/source_windows?hl=ja)によれば、Visual Stadio 2019でテストされているそうなので、`Visual Studio Community 2019`をインストールします。([ダウンロード](https://visualstudio.microsoft.com/ja/downloads/))
インストール手順は[こちら](https://visualstudio.microsoft.com/ja/vs/getting-started/mobile-install/)を参照してください。

留意点としては、インストールする際に「コンポーネントの選択」しますが、ここで`C++によるデスクトップ開発`を選択します。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/6f7fe0f1-54f4-6c55-6e05-4f205e275e37.png)

すでにVisual Studio Community 2019をインストールされている方は、Visual Studio Installerから追加することもできます。
[変更]を選択して、上図より選択します。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/3d21d03d-f401-bffc-e68b-c56285fee01c.png)


#CUDA、cuDNNのインストール
バージョンに注意して、以下を参考にインストールをします。
https://qiita.com/jonpili/items/e5444c31fbd16f30725a
https://keita-blog.com/data_science/keras-tensorflow-gpu

#TensorFlow-GPU、Kerasのインストール
作成した仮想環境のcondaプロンプトを起動します。
![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/b98d17aa-4253-8210-6c92-8be5fa81de73.png)

```condaプロンプト.
(Keras-gpu-py36) C:\Users\...>
```
TensorFlow-GPUをインストールします。

```
conda install tensorflow-gpu==2.0.0
```
Kerasをインストールします。

```
conda install keras
```
インストールが終わったら、以下を実行してインストールされているパッケージを確認します。

```
conda list
```
出力で以下のパッケージのバージョンが、インストールしたCUDAとcuDNNのバージョンに合致していればOKです。
(cuDNNのバージョンが違うけど、エラーが出なかったのでスルーしました...:joy:)

```
cudatoolkit               10.0.130                      0
cudnn                     7.6.5                cuda10.0_0
```

#確認

GPUデバイスが認識されていることを確認します。

condaプロンプトで以下を実行します。

```.py
> python
>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()
```
エラーがなく、以下のように表示されればOKです。

```.py
...
name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 2210712780
locality {
  bus_id: 1
  links {
  }
}
...
```

実モデルで確認してみます。

まず、GPUメモリがオーバーフローしないように制限します。
その後、mnistデータを学習させてみます。
参考：[tensorflow2.0 + kerasでGPUメモリの使用量を抑える方法](https://qiita.com/studio_haneya/items/4dfaf2fb2ac44818e7e0)


```test.py
# -------------------------------------------------------
# メモリの制限 tensorflow-gpu (2.0.0)
# -------------------------------------------------------
import tensorflow as tf
physical_devices = tf.config.experimental.list_physical_devices('GPU')
if len(physical_devices) > 0:
    for k in range(len(physical_devices)):
        tf.config.experimental.set_memory_growth(physical_devices[k], True)
        print('memory growth:', tf.config.experimental.get_memory_growth(physical_devices[k]))
else:
    print("Not enough GPU hardware devices available")

# -------------------------------------------------------
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

batch_size = 128
num_classes = 10
epochs = 20

# モデルの生成関数
def createModel():
    model = Sequential()
    model.add(Dense(512, activation='relu', input_shape=(784,)))
    model.add(Dropout(0.2))
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(10, activation='softmax'))

    model.compile(loss='categorical_crossentropy',
                  optimizer=RMSprop(),
                  metrics=['accuracy'])
    return model

# Mnistデータのロード
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784) # 2次元配列を1次元に変換(訓練データ)
x_test = x_test.reshape(10000, 784) # 2次元配列を1次元に変換(テストデータ)
x_train = x_train.astype('float32') # int型をfloat32型に変換
x_test = x_test.astype('float32') # int型をfloat32型に変換
x_train /= 255                     # [0-255]の値を[0.0-1.0]に変換
x_test /= 255

# 正解ラベルのOne hot vector化
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# モデルの定義
model = createModel()

# 学習の実行
history = model.fit(x_train, y_train,  # 画像とラベルデータ
                    batch_size=batch_size,
                    epochs=epochs,     # エポック数の指定
                    validation_data=(x_test, y_test))

# モデル構成の確認
model.summary()

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
```
以下でGPUが使われていることを確認します。

- エラーがでないこと
- 解析に入る前のログでGPUが認識されていること
- タスクマネージャーでGPUの使用率が上がっていること

```ログの一部.
...
device:GPU:0 with 6358 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1070 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1)     
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
2020-05-30 03:06:15.202155: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cublas64_100.dll
60000/60000 [==============================] - 2s 36us/step - loss: 0.2462 - accuracy: 0.9249 - val_loss: 0.1065 - val_accuracy: 0.9655
Epoch 2/20
...
```

#参考
インストール手順

- [【VS Code】Pythonを実行する方法(Anacondaを利用)](https://buralog.jp/python-execute-from-vscode/)
- [Visual Studio 入門](https://visualstudio.microsoft.com/ja/vs/getting-started/mobile-install/)
- [Windows10でKeras/tensorflowがGPUを使用できない場合のチェックポイント](https://liaoyuan.hatenablog.jp/entry/2017/12/30/000155)
- [初心者がGPU搭載Windows10にPython + Anaconda + TensorFlow + Kerasの環境を構築してみた[2018/4/28]](https://qiita.com/jonpili/items/e5444c31fbd16f30725a)

バージョン対応関係

- [Keras Documentation](https://keras.io/ja/)
- [Tensorflow GPU, CUDA, CuDNNのバージョン早見表](https://qiita.com/chin_self_driving_car/items/f00af2dbd022b65c9068)
- [TensorFlow ドキュメント](https://www.tensorflow.org/install/source_windows?hl=ja)

確認方法

- [tensorflow2.0 + kerasでGPUメモリの使用量を抑える方法](https://qiita.com/studio_haneya/items/4dfaf2fb2ac44818e7e0)