【環境構築】VSCode + venv + Keras で GPU 環境を構築する

<!-- =================================================== -->
# 概要
<!-- =================================================== -->
以下の記事の **venv**版です。

https://qiita.com/nemutas/items/c7d9cca91a7e1bd404b6

<!-- =================================================== -->
# 環境
<!-- =================================================== -->
- Windows10
- NVIDIA GeForce GTX 1070 Ti
- VSCode

<!-- =================================================== -->
# バージョンの特定
<!-- =================================================== -->
インストールするパッケージのバージョンを確認します。

https://keras.io/ja/

https://www.tensorflow.org/install/source_windows?hl=ja#gpu

今回インストールバージョンは、以下の通りです。

- Python 3.6
- tensorflow-gpu 2.4.0
- Keras 2.4.3（最新）
- cuDNN 8.0
- CUDA 11.0

<!-- =================================================== -->
# cuDNN・CUDA のインストール
<!-- =================================================== -->
### インストール
**CUDA 11.0**

https://developer.nvidia.com/cuda-11.0-download-archive

**cuDNN 8.0**
Download cuDNN v8.0.4 (September 28th, 2020), for CUDA 11.0

https://developer.nvidia.com/rdp/cudnn-archive

### 設定

1. CUDAをインストールすると、`C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0`が作成されます。
2. cuDNNのzipを解凍すると、`bin`，`include`，`lib`フォルダがあるので、それを上記のフォルダ内に上書きします。
3. 環境変数の**path**に以下を設定します。

```
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\libnvvp
```

<!-- =================================================== -->
# 仮想環境の構築
<!-- =================================================== -->
※ Python 3.6 を導入していない方は先にインストールしてください。

仮想環境を置くフォルダを作成します。（**.venv**など）
フォルダ内で、以下を実行します。

```:cmd
py -3.6 -m venv keras-tfgpu24-py36
```
※ `keras-tfgpu24-py36`は仮想環境名なので、お好きなように決めてください。

作成した仮想環境をactivateします。

```:cmd
.venv\keras-tfgpu24-py36\Scripts\activate
```
acivateすると、コマンドプロンプトの表示が以下のようになります。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/9b0d92ab-ee73-f7fb-426f-4c22c31ff106.png)

この状態で、パッケージをインストールします。

```:cmd（keras-tfgpu24-py36）
pip install tensorflow-gpu==2.4.0
pip install keras
```

インストールができたら、GPUが認識されるか確かめます。

```:cmd（keras-tfgpu24-py36）
python
>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()
```

認識されれば、以下のように表示されます。

```.js:cmd（keras-tfgpu24-py36）
...
name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 2210712780
locality {
  bus_id: 1
  links {
  }
}
...

```

<!-- =================================================== -->
# VSCode
<!-- =================================================== -->
### 拡張機能
以下の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-python.python

### ファイルの作成
mnistを使用したテストファイルを作成します。

```main.py
# -------------------------------------------------------
# メモリの制限 tensorflow-gpu
# -------------------------------------------------------
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")

print("===============================================")
# -------------------------------------------------------
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])

# モデルの保存
model.save('out/model.h5')
```

メモリの制限について

https://www.tensorflow.org/guide/gpu?hl=ja#gpu_%E3%81%AE%E3%83%A1%E3%83%A2%E3%83%AA%E5%A2%97%E5%8A%A0%E3%82%92%E5%88%B6%E9%99%90%E3%81%99%E3%82%8B

### インタープリンターの選択
以下の手順で、`.venv\keras-tfgpu24-py36\Scripts`内にある**python.exe**を選択します。

![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/a21d0048-3765-e6a8-ce2a-ba1f8c4a494e.png)

以下のように表示が切り替わればOKです。
![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/3931d524-c096-80fe-bce7-234dd1061bfa.png)

### 実行環境の設定
プロジェクトに以下を追加します。

```.json:.vscode/launch.json
{
	"version": "0.2.0",
	"configurations": [
		{
			"name": "Python: main.py",
			"type": "python",
			"request": "launch",
			"program": "${workspaceFolder}\\main.py",
			"console": "integratedTerminal"
		}
	]
}
```

### 動作確認
以上の設定が終了したら、実行します。
ログで、以下のように表示されれば、、GPUが使用されていることになります。

```
memory growth: True
```

また、タスクマネージャーのGPU使用率を見てもいいかもしれません。

<!-- =================================================== -->
# まとめ
<!-- =================================================== -->
バージョンをしっかり確認しましょう。
環境変数をしっかり設定しましょう。

あと、なぜかPython 3.7, 3.8 は、うまくTensorflow-gpuがインストールされないです。:neutral_face:

<!-- =================================================== -->
# Tips：venv コマンド
<!-- =================================================== -->
### 仮想環境の作成

```.js:cmd
py -m venv vname  // バージョン指定なし
py -3.6 -m venv vname // バージョン指定あり
```
vnameは、好きな仮想環境名

### アクティベート

```:cmd
...\vname\Scripts\activate
```

### 非アクティベート
```:cmd（vname）
deactivate
```

### パッケージ インストール
```:cmd（vname）
pip install numpy
```

### パッケージ アンインストール
```:cmd（vname）
pip uninstall numpy
```

### パッケージ一覧表示
```:cmd（vname）
pip list
```

### エクスポート
```:cmd（vname）
pip freeze > requirements.txt
```

### インポート
```:cmd（vname）
pip install -r requirements.txt
```

### コードの実行
```:cmd（vname）
py sample.py
```

<!-- =================================================== -->
# 参考
<!-- =================================================== -->

https://keita-blog.com/data_science/keras-tensorflow-gpu