windows10ユーザーがJupyterNotebookでtensorflow-gpuを動かそうとした話(2018/10/21)

##おことわり
この記事の出来事は記事タイトルにあるように、2018/10/21当時のものです。
数か月後には全く参考にならなくなっているかもしれません。

##tensorflow-gpuの導入
新しいPCを購入してpythonで機械学習する環境を整えていた時のこと。
「せっかくグラボ買ったんだからtensorflow-gpuを使おう」と思い立ち、Anaconda Prompt上でCondaコマンドを使ってGPU計算用の環境を作成した。
今はKerasで勉強中なのでKerasもインストールした。
グラフィックドライバーは既にインストール済みだったと思う。
以下の記事を参考にしつつ進めていく。

**GPUありWindowsでTensorFlowを使う**
https://qiita.com/hiraokusoy/items/fa01f9fc7eccbe299b89

**Jupyterで複数カーネルを簡単に選択するための設定**
https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e

```
#仮想環境の作成、ついでにパッケージのインストール
(base) conda create --name=pyMLgpu jupyter keras tensorflow-gpu tensorboard
```

インストールをしばらく待ち、エラーログもなく無事にインストールできたようだ。
まずはインストールされたパッケージのチェック。

```
#仮想環境の有効化
(base) activate pyMLgpu

#パッケージのリストを取得
(pyMLgpu) conda list
# packages in environment at C:\Users\(username)\Anaconda3\envs\pyMLgpu:
#
# Name                    Version                   Build  Channel
_tflow_select             2.1.0                       gpu
...
cudatoolkit               9.0                           1
cudnn                     7.1.4                 cuda9.0_0
...
jupyter                   1.0.0                    py36_7
jupyter_client            5.2.3                    py36_0
jupyter_console           6.0.0                    py36_0
jupyter_core              4.4.0                    py36_0
keras                     2.2.4                         0
keras-applications        1.0.6                    py36_0
keras-base                2.2.4                    py36_0
keras-preprocessing       1.0.5                    py36_0
...
python                    3.6.6                hea74fb7_0
...
tensorboard               1.11.0           py36he025d50_0
tensorflow                1.11.0          gpu_py36h5dc63e2_0
tensorflow-base           1.11.0          gpu_py36h6e53903_0
tensorflow-gpu            1.11.0               h0d30ee6_0
```

どうやらtensorflow-gpuのインストールのついでに、必要なパッケージであるCUDAやCuDNNもインストールしてくれたようだ。
ググるとわかるように、以前はバージョン依存性に気を使いながらそれぞれ用意する必要があって大変だったようだ。
今はtensorflow-gpuの側で対応してくれているのだろうか？
ともかく、次はこの環境上で本当にtensorflow-gpuやKerasが動くのかチェックする。

```
(pyMLgpu) python
Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 11:27:44) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import keras
Using TensorFlow backend.
>>> import tensorflow as tf
>>> s = tf.Session()
2018-10-21 19:11:53.230696: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2
2018-10-21 19:11:53.532436: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1411] Found device 0 with properties:
name: GeForce GTX 1060 6GB major: 6 minor: 1 memoryClockRate(GHz): 1.7085
pciBusID: 0000:26:00.0
totalMemory: 6.00GiB freeMemory: 4.97GiB
2018-10-21 19:11:53.537131: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1490] Adding visible gpu devices: 0
2018-10-21 19:11:53.922823: I tensorflow/core/common_runtime/gpu/gpu_device.cc:971] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-10-21 19:11:53.925468: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977]      0
2018-10-21 19:11:53.927039: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990] 0:   N
2018-10-21 19:11:53.928693: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1103] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 4720 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060 6GB, pci bus id: 0000:26:00.0, compute capability: 6.1)
```

いろいろごちゃごちゃと出ているが、どうやらtensorflow-gpuがグラボを認識してくれているようだ。Kerasのインポートも問題なし。

##JupyterNotebookで仮想環境を読み込む
次に、この仮想環境をJupyterNotebookが読み込めるようにして動かしたい。
以下のように打ち込めば仮想環境をJupyterNotebookに読み込ませることができる。

```
#JupyterNotebookにカーネルを自動で読み込ませる
#--nameで仮想環境名，--display-nameで表示される名前を指定
ipython kernel install --user --name=pyMLgpu --display-name=pyML(GPU)
```

出力を見る限りでは特にエラーもなく処理が終わったようだった。
このときにactivateしていた仮想環境が何だったのか覚えていないが、これが後述の不具合につながったのかもしれない。

最後にJupyterNotebookを起動して適当なテスト用のファイルを開き、Kernelsから仮想環境を切り替えてテストをする。
すると、以下のようなエラーが出た。
![jupyter1.png](https://qiita-image-store.s3.amazonaws.com/0/286956/3cac66cc-e11b-40d6-cbcd-375c9bc33502.png)

？？？なんでKerasの段階でimportに失敗しているの？
tensorflowもimportしようとするとno module...と怒られる。
有効化している仮想環境は確かにtensorflow-gpu用に今作ったものだった。(画像では見えないが)


上記のようにAnaconda Prompt上ではうまくいっていたのでJupyterNotebook側の問題だと考え、いろいろ探ったところ、原因はカーネルの設定ファイルに見つかった。
自分の場合では`C:\Users\(username)\AppData\Roaming\jupyter\kernels\pymlgpu\`にある`kernel.json`をテキストエディタなどで見てみると、

```
{
 "argv": [
  "C:\\Users\\(username)\\Anaconda3\\python.exe",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "pyML(GPU)",
 "language": "python"
}

```
オイオイ、仮想環境じゃなくてbaseのpython.exeを読み込んでいるじゃないか。
3行目にある実行ファイルのパスをきちんと直してやる：


```
  "C:\\Users\\(username)\\Anaconda3\\envs\\pyMLgpu\\python.exe",
```

保存してからJupyterNotebookを再起動し、もう一度テストファイルを実行する。
![jupyter2.png](https://qiita-image-store.s3.amazonaws.com/0/286956/be2c3a89-6ebd-f032-b3d8-f2a5e02720ed.png)
今度はきちんと動いた！

「コマンドライン上ではKerasやtensorflowが読み込めるけどJupyterNotebookではダメ」という方は`kernel.json`をチェックしてみるといいんじゃないでしょうか。

##めでたしめでたし
というわけでtensorflow-gpuをJupyterNotebook上で動かすことに成功したのでした。
古いPCで10時間、新しいPCのCPU(通常のtensorflow)でも1000秒ほどかかっていた計算がtensorflow-gpuでは47秒で終わるなどしています。キモチイイ。