Python
機械学習
Keras
TensorFlow
PlaidML

Macでも高速に機械学習できるかもしれないPlaidMLを試してみた

Kerasの作者のfcholletさんがTwitterで紹介していた、PlaidMLという新しい機械学習用のライブラリを試してみた。Early Alpha Qualityとのことであるが、試してみたらとても速いしKerasで書いてたコードが(ほぼ)そのまま使えて感激した。これは機械学習が捗る…かも?

短くまとめると

  • PlaidMLという新しいフレームワークを使うと、nVidia積んでないMacでもGPU使って高速に機械学習できるかも
  • Kerasのバックエンドとして使えるので、今まで書いてきたKerasのコードを(ほぼ)そのまま使える
  • 動かしてみたら、確かに速い。
  • 10月に試した段階では不具合があったが、アップデートで修正された!

PlaidML

https://github.com/plaidml/plaidml

TensorFlowと違って、OpenCLサポートがあるためAMDのGPUでもハードウェアアクセラレーションが効くらしい。そして、このPlaidMLはKerasのバックエンドとして使える。つまり、今まで書いてきたKerasのコードを、そのままバックエンドをPlaidMLに切り替えるだけで高速に実行できる可能性があるということ。

これはMacで機械学習を楽しむ上ではとても意味のあることなので、早速試してみた。

OpenCLが使えるか調べる

clinfoを使って、使用中のMacのGPUでOpenCLが使えるか調べておこう。

brew install clinfo
clinfo

Number of platformsが1以上になっていたらOK。

インストール

2017年10月末現在、PlaidMLはpip経由でのインストールが可能になっている。基本的にはpip経由でインストールする方が手軽でオススメ。

pipでインストールする

2017/10/27から、Mac版もpip経由でのインストールが可能になったので、特別理由がなければpip経由でインストールするのが良い(2017/10/29追記)

virtualenvで環境を作る

必須ではないが、試行錯誤するにあたって環境を汚したくないのでvirtualenvで新しい環境を作る。

virtualenv --system-site-packages ~/plaidml
source ~/plaidml/bin/activate
pip install setuptools --upgrade

pipでインストールする

pip install plaidml-keras

ソースコードからビルドする(リリース前の実装を試したい場合)

レポジトリ上の最新のコードからビルドしたい場合は、下記の手順でビルドできる。

必要なライブラリを入れる

brewで必要なライブラリを入れておく。古い場合は適宜アップデートすること。(特にbazelは0.6.0以降が必要)

brew install bazel
brew install bison
brew install flex

virtualenvで環境を作る

必須ではないが、試行錯誤するにあたって環境を汚したくないのでvirtualenvで新しい環境を作る。

virtualenv --system-site-packages ~/plaidml
source ~/plaidml/bin/activate
pip install setuptools --upgrade

setuptoolsが古いとビルド/インストールに失敗するため、念のためアップデートしておく。36.6.0ではうまくいった。

ソースコードをクローンする

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

ビルド+インストール

bazelを使ってビルド、作成されたwheelをインストールする。

bazel build -c opt plaidml:wheel plaidml/keras:wheel
pip install -U bazel-bin/plaidml/*whl bazel-bin/plaidml/keras/*whl

PlaidMLの設定

インストールが完了したら、plaidml-setupを実行して環境の設定を行う。ここで計算に使用するGPUを指定する。

plaidml-setup 

基本的には質問に答えていくだけ。

PlaidML Setup (0.0.0.dev0)

...

Default Config Devices:
   No devices.

Experimental Config Devices:
   amd_radeon_pro_570_compute_engine.0 : AMD AMD Radeon Pro 570 Compute Engine
   intel(r)_core(tm)_i5-7500_cpu_@_3.40ghz.0 : Intel Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz

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

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

検証されていないハードウェアだとExperimentalにリストされるようだが、とりあえず試してみる。

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

   1 : amd_radeon_pro_570_compute_engine.0
   2 : intel(r)_core(tm)_i5-7500_cpu_@_3.40ghz.0

Default device? (1,2)[1]:1

Selected device:
    amd_radeon_pro_570_compute_engine.0

AMDを選んでみた。

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

Enable telemetry reporting? (y,n)[y]: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/foo/.plaidml? (y,n)[y]:
Success!

マトリクスの計算が行われ、どうやらうまく動いたようだ。この設定を.plaidmlに保存すると、次回以降PlaidMLを実行する際に、このハードウェア設定が使われるようだ。

Kerasのバックエンドとして使ってみる

Kerasのバックエンドとして使う場合は、import kerasより前に下記のコードを呼んであげれば良い。

import plaidml.keras
plaidml.keras.install_backend()

VGG-LIKEなサンプルで比較してみる

試しに、KerasのホームページにあるVGG-LIKEのサンプルをそれぞれのバックエンドで実行してパフォーマンスを計測してみた。fitの処理にかかった時間のみを計測。参考までに、FloydHub(GPU使用)の結果も。

なお、処理が早く終わりすぎてしまうのでEPOCHは50に増やした。

ライブラリ マシン 時間(四捨五入)
TensorFlow Intel Core i5 2.9GHz 145秒
TensorFlow Intel Core i5 3.4GHz 117秒
PlaidML Intel Iris Graphics 550 110秒
PlaidML AMD Radeon Pro 570 55秒
TensorFlow FloydHub(GPUインスタンス) 14秒
  • iMac 2017 CPU 3.4 GHz Intel Core i5 + AMD Radeon Pro 570
  • MacBook Pro 2016 CPU 2.9GHz Intel Core i5 + Intel Iris Graphics 550

なるほど。

本題から外れるけど、FloydHub圧倒的にはええ。

自分のコードで試してみた結果

バックエンドの置き換えは簡単

自分のコードでも試してみた。

TensorFlow + Kerasでフレンズ識別する - その1: 学習データの準備編

こちらの記事で使ったコードのバックエンドをPlaidMLに置き換えてみた。バックエンドの置き換え自体は本当に簡単で

import plaidml.keras
plaidml.keras.install_backend()

を加える以外、ほとんどやることはなかったのだが、TensorBoardなど一部TensorFlowの機能に依存した実装部分は当然外す必要があった。

学習に失敗した(不具合、解決済み)

ただ実際に学習を走らせてみたところ、途中でTrain Loss / Train Accuracy / Val Loss / Val Accuracy全てがゼロに収束してしまうという現象が起きてしまい、うまくいかなかった。

2017.10.23追記: どうやら、これはMac版のバグのようだ。

model.fit() loss: nan #26

Thanks Andy, we've seen issues on Mac as well and are working on tracking them down. Once we get that all ironed out we'll mark Mac "supported" and ship a new release with binaries.

2017.11.04追記: アップデートで対策された。

Inconsistent computations #47

Yes, the CPU issue is an known limitation of Apple's CPU OpenCL which allows only 1 thread per work-group. We have not addressed this, as the resulting CPU performance is likely to be underwhelming. As for the main issue, I've tracked the problem down to a set of kernels that behave incorrectly, but only on AMD and only on Apple's drivers. I'm still checking, but the kernels strongly appear to be correct, and I believe this may be a bug in the OpenCL drivers themselves. There is some discussion of similar correctness issues with Apple's OpenCL drivers in other OpenCL projects. That said, it appears to happen only for a subset of kernels. There is a configuration change that seems to work around the problem by avoiding such kernels. There may be a performance penalty for the change, and since I don't know what the specific driver issue is, I'm not sure if this workaround will fully resolve all correctness issues. However, it did fix the issue for me.

どうやら、この問題はmacOS用のOpenCLドライバーの問題のようだ。パフォーマンスは若干犠牲になるが、Ver.0.1.2でこの問題にはワークアラウンドが適用され、正しい計算結果が出るようになった。今後、ドライバーが修正されることを期待したい。

まだ使うには早すぎるが、今後にとても期待

Macは公式には未対応、Early Alpha Qualityの段階ということもあり、まだ実戦で使うには早すぎるのは当然かもしれないが、OpenCL対応で、かつKerasのコードをそのまま使えるというのは本当にありがたい。数週間以内にMacにも公式に対応予定とのことで、今後に期待したい。

リンク