tensorflow+kerasを扱うためのPython仮想環境はvenvとAnacondaどちらを使うべきか

# 結論
Anacondaを使おう

# 環境
OS:Ubuntu 18.04

# 背景
今日のディープラーニング界隈では技術の進化が飛躍的に早く、それに合わせて
tensorflowやkerasといったフレームワークの更新が頻繁に行われている。
ここで問題となるのが各モジュール間のバージョンには依存関係があり、適切なバージョンの組み合わせでないとプログラムが動作しないといったことが頻繁に発生する。
特にCUDA,cuDNN,tensorflow-gpu間の依存関係はかなりシビアで、バッチレベルが少しでも異なると平気で動かなくなる。
tensorflow公式が[テスト済みの依存関係](https://www.tensorflow.org/install/source#common_installation_problems)を発表しているが、このバージョンに合わせてライブラリをインストールしてもうまく動作しないことがある。
現にtensorflow-gpu-1.31.1, cuDNN-7.4, CUDA-10.0, Python3.6の組み合わせだとうまく動作しなかった。
![Screenshot from 2019-09-29 21-41-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72035/d37cf05f-d865-64c0-e1ab-4e567225a26f.png)
特に厄介なのが、一見うまく動いているようで実はうまく動いていない場合がある。
たとえばtensorflow-gpuを使っているのにもかかわらず、GPUが認識されずCPUでモデルの学習が行われてしまうといった症状がある。
これは一見正常に学習が進んでいるように見えるのだが、実際はCPUで学習が行われてしまうため、学習に莫大な時間がかかってしまう。
fit()した際に以下のメッセージが表示されている場合はGPUで学習が行われていない。

```
2019-09-22 14:52:41.548583: E tensorflow/stream_executorcuda
/cuda_dnn.cc:329] Could not create cudnn handle:
 CUDNN_STATUS_INTERNAL_ERROR
```
# なぜ仮想環境を使うのか
こういった背景がある中で、仮想環境を使っていない場合、
特定のモジュールを更新した際に過去に作成したプログラムのモジュールバージョンの依存関係を満たせなくなり動かなくなる。といったことがある。
そのため、Pythonを使う場合仮想環境を使うことが一般的である。
仮想環境といってもVMwareやVirtualBoxのようなハイパーバイザー型仮想環境とは異なり、
venvやAnacondaはライブラリのパスの切り方を変えているだけなので、ホストマシンの性能を最大限に活かすことができる。

# なぜAnacondaを使うのか
Pythonの仮想環境といえばvenvを使うのが一般的だが、ディープラーニングをやりたいのであればAnacondaが最良だという結論に至った。
Anacondaを使う理由は次の通り。

- 環境構築が楽
- モジュールのバージョン変更が楽
- 複数バージョンのCUDAを扱うことができる

特に大きな理由が３番目の"複数バージョンのCUDAを扱うことができる"部分である。
Anacondaを使わずに複数バージョンのCUDAを同一環境で共存させようとすると環境変数の管理が大変なことになる。
更にCUDAのバージョンアップさせる際にも癖があり、最悪ホストマシンが起動しなくなるといったこともある（経験済み）。
そのため、同一環境でCUDAを複数管理したい場合はAnacondaが最良の選択となる。
venvではこれが実現できない（パスの切り方工夫したらできるかも？）。
# Anacondaを扱う上で注意する点

- pipは使わない
- conda install "モジュール名"ではモジュールが見つからない時がある。

Anaconda環境下でpipを使うと環境が壊れてしまうことがあるため、Anaconda環境下ではpipは使わない方が良い
これに関しては以下の記事が参考になる。
　　[condaとpip：混ぜるな危険](http://onoz000.hatenablog.com/entry/2018/02/11/142347)
また、conda installでモジュールが見つからない場合は[Anaconda Cloud](https://anaconda.org/)で探せば大抵見つかる。
現時点ではAnaconda Cloudで使いたいモジュールが見つからなかったことはない。


# Anacondaでモジュールのバージョンを変更する
Anacondaで仮想環境作成済み、モジュールインストール済みを前提として説明する。
以下のコマンドでAnaconda-Navigatorを起動する

```
anaconda-navigator
```
Environments→作成した仮想環境を選択→右側のコンボボックスが"Installed"になっていることを確認し、バージョンを変更したいモジュール名をSearch Packagesから検索する
モジュールがインストールされていれば表示されるので、☑のところを右クリックし、"mark for specific version installation"内から変更先のバージ
ョンを選択する。

すると☑がオレンジ色になるのでApply→Applyを選択するとバージョンの変更が完了となる。
![Screenshot from 2019-09-29 22-53-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72035/cf506898-cc9f-efa9-ca8e-2ac1468434ff.png)

![Screenshot from 2019-09-29 22-55-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72035/592c9d5b-20df-2aca-99d6-12233af4602f.png)
![Screenshot from 2019-09-29 22-55-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72035/cc1beda2-37c6-d01d-68bb-fec845034b7d.png)


# 2019/09/29時点でのおすすめ組み合わせ
上記でも述べた通り、各モジュールには依存関係があるため、tensorflow(-gpu), cudatoolkit, cudnnの組み合わせは適切なバージョン同士でなければ動作しない。
そのため、最新のモジュールを入れても動作しないことがある。
また、公式発表の[テスト済みの依存関係](https://www.tensorflow.org/install/source#common_installation_problems)の表通りに導入しても動かないことがある。
Anaconda環境下で動作確認済み(GPU環境)のバージョンの組み合わせは次の通り

| モジュール名       | バージョン    | 
|:-----------------|:------------------|
| keras-gpu  | 2.2.4 |        This        |
| tensorflow-gpu           | 1.12.0 |    
| cudatoolkit          | 9.0 |    
| cudnn          | 7.3.1 |    
※Python3.6を使用