PlaidMLを使ってMacのGPU(AMD)で画像分類を試してみた


MacBookにAMDのGPUが搭載されていたのでPlaidMLを使って画像分類を試してみました。
![plaidml-demo20.gif](https://qiita-image-store.s3.amazonaws.com/0/245670/7ad41d5f-d523-2cae-69f7-ff59d2215755.gif)

PlaidMLのGitHub： https://github.com/plaidml/plaidml


【環境】
PC: MacBook Pro (15-inch, 2017)
OS: macOS High Sierra(10.13.3)
GPU: Radeon Pro 560 (4GB)
Python3(virtualenv)

まずは手持ちのMacでOpenCLが使えるか確認するためにbrewでclinfoをインストールします

```
$ brew install clinfo
```

確認

```
$ clinfo
```

大丈夫そうですね

```
Number of platforms                               1
```

AMDのGPUを発見

```
clGetPlatformInfo(NULL, CL_PLATFORM_NAME, ...)  Apple
  clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, ...)   Success [P0]
  clCreateContext(NULL, ...) [default]            Success [P0]
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_DEFAULT)  Success (2)
    Platform Name                                 Apple
    Device Name                                   Intel(R) HD Graphics 630
    Device Name                                   AMD Radeon Pro 560 Compute Engine
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_CPU)  Success (1)
    Platform Name                                 Apple
    Device Name                                   Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU)  Success (2)
    Platform Name                                 Apple
    Device Name                                   Intel(R) HD Graphics 630
    Device Name                                   AMD Radeon Pro 560 Compute Engine
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_ACCELERATOR)  No devices found in platform
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_CUSTOM)  <checkNullCtxFromType:2437: create context from type CL_DEVICE_TYPE_CUSTOM : error -30>
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_ALL)  Success (3)
    Platform Name                                 Apple
    Device Name                                   Intel(R) HD Graphics 630
    Device Name                                   AMD Radeon Pro 560 Compute Engine
    Device Name                                   Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
```

Pythonの環境を用意

```
$ mkvirtualenv plaidmlPy3 -p python3
```

```
Running virtualenv with interpreter /usr/local/bin/python3
Using base prefix '/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6'
New python executable in /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/python3.6
Also creating executable in /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/python
Installing setuptools, pip, wheel...done.
virtualenvwrapper.user_scripts creating /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/predeactivate
virtualenvwrapper.user_scripts creating /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/postdeactivate
virtualenvwrapper.user_scripts creating /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/preactivate
virtualenvwrapper.user_scripts creating /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/postactivate
virtualenvwrapper.user_scripts creating /Users/ユーザー名/.virtualenvs/plaidmlPy3/bin/get_env_details
```

PlaidMLをインストール

```
$ pip install plaidml-keras
```



```
Collecting plaidml-keras
  Downloading plaidml_keras-0.3.1-py2.py3-none-any.whl
Collecting six (from plaidml-keras)
  Using cached six-1.11.0-py2.py3-none-any.whl
Collecting keras==2.0.8 (from plaidml-keras)
  Downloading Keras-2.0.8-py2.py3-none-any.whl (276kB)
    100% |████████████████████████████████| 276kB 615kB/s
Collecting plaidml (from plaidml-keras)
  Downloading plaidml-0.3.1-py2.py3-none-macosx_10_10_x86_64.whl (14.1MB)
    100% |████████████████████████████████| 14.1MB 113kB/s
Collecting pyyaml (from keras==2.0.8->plaidml-keras)
  Using cached PyYAML-3.12.tar.gz
Collecting scipy>=0.14 (from keras==2.0.8->plaidml-keras)
  Downloading scipy-1.0.1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (16.4MB)
    100% |████████████████████████████████| 16.4MB 95kB/s
Requirement already satisfied: numpy>=1.9.1 in ./.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from keras==2.0.8->plaidml-keras)
Collecting enum34>=1.1.6 (from plaidml->plaidml-keras)
  Downloading enum34-1.1.6-py3-none-any.whl
Collecting requests (from plaidml->plaidml-keras)
  Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 1.2MB/s
Collecting idna<2.7,>=2.5 (from requests->plaidml->plaidml-keras)
  Downloading idna-2.6-py2.py3-none-any.whl (56kB)
    100% |████████████████████████████████| 61kB 2.0MB/s
Collecting urllib3<1.23,>=1.21.1 (from requests->plaidml->plaidml-keras)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 150kB/s
Collecting certifi>=2017.4.17 (from requests->plaidml->plaidml-keras)
  Downloading certifi-2018.1.18-py2.py3-none-any.whl (151kB)
    100% |████████████████████████████████| 153kB 1.1MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests->plaidml->plaidml-keras)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 1.2MB/s
Building wheels for collected packages: pyyaml
  Running setup.py bdist_wheel for pyyaml ... done
  Stored in directory: /Users/ユーザー名/Library/Caches/pip/wheels/2c/f7/79/13f3a12cd723892437c0cfbde1230ab4d82947ff7b3839a4fc
Successfully built pyyaml
Installing collected packages: six, pyyaml, scipy, keras, enum34, idna, urllib3, certifi, chardet, requests, plaidml, plaidml-keras
Successfully installed certifi-2018.1.18 chardet-3.0.4 enum34-1.1.6 idna-2.6 keras-2.0.8 plaidml-0.3.1 plaidml-keras-0.3.1 pyyaml-3.12 requests-2.18.4 scipy-1.0.1 six-1.11.0 urllib3-1.22
```

PlaidMLの環境をセットアップしていきます

```
$ plaidml-setup
```

「y」をタイプ

```
PlaidML Setup (0.3.1)

Thanks for using PlaidML!

Some Notes:
  * Bugs and other issues: https://github.com/plaidml/plaidml
  * Questions: https://stackoverflow.com/questions/tagged/plaidml
  * Say hello: https://groups.google.com/forum/#!forum/plaidml-dev
  * PlaidML is licensed under the GNU AGPLv3

Default Config Devices:
   No devices.

Experimental Config Devices:
   llvm_preview_cpu.0 : LLVM_preview_CPU
   amd_radeon_pro_560_compute_engine.0 : AMD AMD Radeon Pro 560 Compute Engine
   intel(r)_hd_graphics_630.0 : Intel Inc. Intel(R) HD Graphics 630
   opencl_cpu.0 : Intel OpenCL CPU

Using experimental devices can cause poor performance, crashes, and other nastiness.

Enable experimental device support? (y,n)[n]:y
```

PlaidMLで使用できるデバイスIDが表示されます。
AMDのRADEON PRO 560を使用したいので、そのインデックス番号の「2」をタイプ

```
Multiple devices detected (You can override by setting PLAIDML_DEVICE_IDS).
Please choose a default device:

   1 : llvm_preview_cpu.0
   2 : amd_radeon_pro_560_compute_engine.0
   3 : intel(r)_hd_graphics_630.0
   4 : opencl_cpu.0

Default device? (1,2,3,4)[1]:2
```

PlaidMLを応援したいので「y」をタイプ! (別にレポートしたくない方は「n」を選択)

```
Selected device:
    amd_radeon_pro_560_compute_engine.0

PlaidML sends anonymous usage statistics to help guide improvements.
We'd love your help making it better.

Enable telemetry reporting? (y,n)[y]:y
```

`/Users/ユーザー名/.plaidml`に設定を保存したいので「y」をタイプ

```
Almost done. Multiplying some matrices...
Tile code:
  function (B[X,Z], C[Z,Y]) -> (A) { A[x,y : X,Y] = +(B[x,z] * C[z,y]); }
Whew. That worked.

Save settings to /Users/ユーザー名/.plaidml? (y,n)[y]:y
Success!
```

サンプルを動かしたいのでクローンします

```
$ git clone https://github.com/plaidml/plaidbench.git
```

```
Cloning into 'plaidbench'...
remote: Counting objects: 296, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 296 (delta 2), reused 5 (delta 1), pack-reused 287
Receiving objects: 100% (296/296), 9.68 MiB | 757.00 KiB/s, done.
Resolving deltas: 100% (141/141), done.
```


移動

```
$ cd plaidbench
```

必要なモジュールをインストールする前に一応内容を確認

```
$ cat requirements.txt
```

fmfm

```
h5py>=2.7.0
plaidml-keras>=0.3.0
onnx-plaidml>=0.3.0
```

インストール開始

```
$ pip install -r requirements.txt
```

```
Collecting h5py>=2.7.0 (from -r requirements.txt (line 1))
  Downloading h5py-2.7.1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (4.7MB)
    100% |████████████████████████████████| 4.8MB 288kB/s
Requirement already satisfied: plaidml-keras>=0.3.0 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from -r requirements.txt (line 2))
Collecting onnx-plaidml>=0.3.0 (from -r requirements.txt (line 3))
  Downloading onnx_plaidml-0.3.1-py2.py3-none-any.whl
Requirement already satisfied: six in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from h5py>=2.7.0->-r requirements.txt (line 1))
Requirement already satisfied: numpy>=1.7 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from h5py>=2.7.0->-r requirements.txt (line 1))
Requirement already satisfied: keras==2.0.8 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: plaidml in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Collecting onnx>=1.1.0 (from onnx-plaidml>=0.3.0->-r requirements.txt (line 3))
  Downloading onnx-1.1.1.tar.gz (940kB)
    100% |████████████████████████████████| 942kB 1.1MB/s
Collecting click (from onnx-plaidml>=0.3.0->-r requirements.txt (line 3))
  Downloading click-6.7-py2.py3-none-any.whl (71kB)
    100% |████████████████████████████████| 71kB 20kB/s
Requirement already satisfied: pyyaml in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from keras==2.0.8->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: scipy>=0.14 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from keras==2.0.8->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: enum34>=1.1.6 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: requests in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Collecting protobuf (from onnx>=1.1.0->onnx-plaidml>=0.3.0->-r requirements.txt (line 3))
  Using cached protobuf-3.5.2.post1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from requests->plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: urllib3<1.23,>=1.21.1 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from requests->plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: idna<2.7,>=2.5 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from requests->plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: certifi>=2017.4.17 in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from requests->plaidml->plaidml-keras>=0.3.0->-r requirements.txt (line 2))
Requirement already satisfied: setuptools in /Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages (from protobuf->onnx>=1.1.0->onnx-plaidml>=0.3.0->-r requirements.txt (line 3))
Building wheels for collected packages: onnx
  Running setup.py bdist_wheel for onnx ... done
  Stored in directory: /Users/ユーザー名/Library/Caches/pip/wheels/40/c3/23/6190428e9a6f136bc0b3f8181b0eda5fcb56124c40b6d38878
Successfully built onnx
Installing collected packages: h5py, protobuf, onnx, click, onnx-plaidml
Successfully installed click-6.7 h5py-2.7.1 onnx-1.1.1 onnx-plaidml-0.3.1 protobuf-3.5.2.post1
```

ちゃんとインストールされている確認するためにMobileNetを起動してみましょう

```
$ python plaidbench.py mobilenet
```

大丈夫そう！

```
/Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Running 1024 examples with mobilenet, batch size 1
INFO:plaidml:Opening device "amd_radeon_pro_560_compute_engine.0"
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.6/mobilenet_1_0_224_tf.h5
16752640/17225924 [============================>.] - ETA: 0sModel loaded.
Example finished, elapsed: 1.9480268955230713 (compile), 9.947688102722168 (execution), 0.009714539162814617 (execution per example)
Correctness: PASS, max_error: 1.9290237105451524e-05, max_abs_error: 1.0132789611816406e-06, fail_ratio: 0.0
```


ではでは本題の画像分類に取り掛かりましょう

plaidvisionをクローン

```
git clone https://github.com/plaidml/plaidvision.git
```

移動

```
cd plaidvision/
```

インストールする内容を確認

```
$ cat requirements.txt
```

```
h5py>=2.7.0
imageio>=2.2.0
Pillow>=4.2.1
pygame>=1.9.3
plaidml-keras>=0.1.0a5
opencv-python>=3.3.0.10
```

実行

```
$ python plaidvision.py mobilenet
```

別ウィンドウが起動します！

```
Using PlaidML backend.
/Users/ユーザー名/.virtualenvs/plaidmlPy3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
INFO:plaidml:Opening device "amd_radeon_pro_560_compute_engine.0"
```

その画面をスクショしてみました！


<img width="695" alt="スクリーンショット 2018-04-13 21.06.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/245670/c0b610e7-6300-a0bb-b864-3a250ae0c6d1.png">


ちゃんとwater_bottleと認識されていますね。
<img width="277" alt="スクリーンショット 2018-04-13 21.06.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/245670/e21ce697-6211-7504-af71-f48ce318a328.png">


先ほどmobilenetを指定しましたが他にinception_v3, resnet50, vgg16, vgg19, xceptionのモデルもあるようです。

```
$ python plaidvision.py xception
```



CUDAのセットアップを経験した人なら分かると思いますが、非常に簡単にセットアップできた思います。
あと、kerasのバックエンドの置き換えはこれだけみたいです。

```
import plaidml.keras
plaidml.keras.install_backend()
```

NVIDIAのGPUじゃなくても機械学習捗りそうですね！
プライベードで画像を集めてkerasを使って作成したデモがあるのでPlaidMLで動いたら別の機会に紹介します。





【ネタ編】


オワカリイタダケタダロウカ？
<img width="564" alt="スクリーンショット 2018-04-13 19.24.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/245670/af48b60f-5e9d-f056-9543-640780512d06.png">





モウイチド...

<img width="563" alt="スクリーンショット 2018-04-13 19.28.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/245670/762d07be-3f3a-64c7-22b5-e5b8d58265f2.png">


<img width="318" alt="スクリーンショット 2018-04-13 19.29.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/245670/d3dcba4c-f892-8dc8-8687-f9971c0b8e78.png">


だれがトイプードルじゃ！