複数のGPUを使ってCloudML上でモデルをトレーニングする

こんにちは、GMOアドマーケティングのS.Rです。

良いモデルを作るには、大きなサイズの学習データが必要です。そして、高速にモデルをトレーニングすることができれば、イテレーションの短縮になります。今回は高速にモデルをトレーニングするために、複数のGPUでディープラーニングのモデルをトレーニングする方法を投稿します。本記事中の図説は、筆者が自らの環境で作成したものを含みます。

1. LibraryとTool:

今回は下記のディープラーニングのツールまたはライブラリを利用していました。

  • Tensorflow

ディープラーニングに対応しており、Googleの各種サービスなどでも広く活用されている。 2017年2月15日に TensorFlow 1.0 がリリースされた。
対応プログラミング言語はC言語、C++、Python、Java、Go。 対応OSは64ビットのLinux(ただしバイナリ配布はUbuntu用)、macOS、Windows。ハードウェアは CPU、NVIDIA GPU、Google TPU、Snapdragon Hexagon DSP などに対応していて、Android Neural Networks API 経由で Android 端末のハードウェアアクセラレータも使用できる。TensorFlow、 2018年6月22日、ウィキペディア日本語版、https://ja.wikipedia.org/wiki/TensorFlow

  •  Keras

Kerasの公式より下記の紹介があります。

Kerasは,Pythonで書かれた,TensorFlowまたはCNTK,Theano上で実行可能な高水準のニューラルネットワークライブラリです。 Kerasは,迅速な実験を可能にすることに重点を置いて開発されました。 アイデアから結果に到達するまでのリードタイムをできるだけ小さくすることが、良い研究をするための鍵になります。(Keras: Pythonの深層学習ライブラリ、https://keras.io/ja/

  • Google Cloud ML(Machine Learning) Engine

Google Cloud Machine LearningEngine はGoogleさんが提供している機械学習用クラウドサービスです。このサービス使うと下記の利点があります:

  1.  開発の負担を軽減:環境構築せずにTensorflow/Kerasのプログラムを実行できます。
  2. Hardwareを購入しなくて良い:ML  EngineでSingle CPUから最新のTPUまで様々なDeviceを選べます。実際の利用時間から課金されています。
  3. メンテナンスの手数がかからない:クラウドサービスですので、Googleさんがメンテナンスを行い、運用の手間がかかりません。

2. マルチGPUのAPI:

KerasはマルチGPUのAPI を提供しています。APIの詳細情報は下記です。

APIの関数名

入力引数

  • model: Kerasのモデルインスタンスです。OOMエラーを避けるためにこのインスタンスのモデルはCPU上でビルドされるべきです。
  • gpus: 使ってるGPUの数です。gpus の範囲が2以上の整数です。

返り値

初めに用いられたmodelに似たKerasのModelインスタンスですが,複数のGPUにワークロードが分散されたものです。

関数の流れ

マルチGPUでモデルをトレーニングする流れは(図1)三つステップがあります。

  1. モデルの入力のバッチサイズをGPU数と同じ分のサブバッチに分割します。例えば入力のバッチサイズが32、GPU数4の場合にサブバッチは32/4 = 8です。
  2. サブバッチのごとにモデルのコピーをして各GPUへ配布します。
  3. 各GPUでモデルをトレーニングした結果よりCPUにビルドされたモデルを更新します。

 

図1:GPUでモデルをトレーニングする流れ

4. ML Engineの利用方法:

4.1 コマンドのフォーマット

ML Engineを利用するためにGoogle Cloud Accountの申請が必要です。申請の方法がGoogle Cloudの公式サイトに参考してください。

ML EngineでJobをSubmitするコマンドを説明します。

コマンドのFlagの説明が下記です。

  • job_id:  submitするジョブの名前です。この名前はユニークである必要があります
  •  –job-dir: Google Storgeでtemp directoryのURLです。
  • –package-path:  submitしたいジョブのソースコードの格納先です。
  • –config: ML engineのInstanceの設定ファイルです。

4.2 設定ファイルのフォーマット

設定ファイルのフォーマットは下記です。scaleTierスケール階層(図2)です、今回の例でBASICを設定しました。インスタンスの種類 (図3)です。今回の例でcomplex_model_m_gpuを設定しました。

図2:Cloud ML Engine のスケール階層

 

図3:インステンスの種類

5.利用例:

今回はMNISTのデータを使って、マルチGPUで利用する例を作ってみました。MNISTは手書き数字画像(図3)70000枚を集めた画像データセットになります, その中に60000枚は学習データ、10000枚がテストデータに設定されています。

図4:MNISTの画像例

5.1ソースコードのファイル構造:

  •  –config_gpu4.yaml:  ML engineのインステンスの設定ファイルです。
  •  –task.py:  実行するソースコードの本体です
  • –setup.py : ソースコードが依存するLibrayの初期化のScriptです。
図5: ソースコードのファイル構造:

5.2初期化のScript:

Kerasのモデルを保存するためにライブラリ h5pyが必要ですので初期化のScriptへh5pyを追加します。

 

5.3ソースコード:

Step1:使ってるLibarayをImportします。

Step2:MINISTのデータをダウンロードします。

Step3:インスタンスのGPU数を、環境情報から取得します。

Step4:Kerasのモデルをbuildする。

ソースコードで使ったモデルのレイアウトは下記です。

Step5:Kerasのモデルをfitする。

Step6:fitしたモデルを保存します:

マルチGPUのモデルを保存するには,multi_gpu_modelの返り値のモデルではなく,テンプレートになった(multi_gpu_modelの引数として渡した)モデルで.save(fname)か.save_weights(fname)を使ってください.

Step7:実行時間を比較するために同じモデルをSingle GPUで実行する部分も追加します:

 

6. 利用する流れ:

1  Google CloudのAccountを作る:

Google Cloudの公式サイトにGoogle CloudのAccountを作成します。

2 Google Storgeにジョブを実行するBuketを作る:

例で「gs://mgpu/ml_job_temp/」を作ります。

2  ML engineへジョブをsubmitする:

submitするコマンドは下記です。

3.実行した結果:

実行した結果のログよりシングルGPUの実行する時間はマルチGPUの実行する時間より55%(21s ->9s)を改良できました。

図6: マルチGPUのfitする時間
図7: シングルGPUのfitする時間

 

7. まとめ

今回はKerasでマルチGPUをとってモデルのトレーニングを高速化する方法を紹介しました。いかがだったでしょうか。もし今回のブログが皆さんのディープラーニングの運用のお役に立てれば幸いです。