Juliaで深層学習 Vol.2

はじめに

今回は前回に引き続き、下記の内容を解説します。

  • Juliaによる深層学習モデルの実装
  • JuliaでMNISTを解く・コードの解説
  • JuliaとPythonの学習速度の比較

MNISTとは

  • MNISTは、手書き数字の画像を集めたデータセットで、画像分類の入門やチュートリアルでよく使用されます
  • データの中身はグレースケールの0~9の手書き数字で、6万件の学習データと1万件のテストデータから構成されています
  • グレースケールの色の濃淡は0~255の値で表されており、学習する際は、これらの数値を正規化してモデルに入力します
MNIST sample images
MNISTデータセット

JuliaでMNISTを解く

実際に、サンプルコードを用いて、JuliaによるMNISTの学習とテストをやってみます。こちらにGoogle Colabで実行できるJuliaのサンプルコードを用意してありますので、ダウンロードしてください。

ダウンロードしたipynbファイルをGoogle Colabで開くと、一番上に次のようなセルがあると思いますので、実行してください。

ファイルを開くと一番上にあるセル

実行が完了したら、上のメニューから「ランタイム」->「ランタイムのタイプを変更」を選択してください。そうすると、Juliaのバージョンが記されたダイアログが出てくるので、「保存」を押してください。

Juliaのバージョンが記されたダイアログ

これで、ランタイムがリセットされ、Juliaの実行環境が整いました。

あとは順番に、後に続くセルを実行してください。実行していくと「学習」と書かれたセルがあるかと思いますが、下記のようにlossが減少していく過程が表示されていれば、問題なく学習ができています。

学習過程が表示される

同じく、「テスト」と書かれている以下のセルを実行してください。下記のように正解率が返ってくれば、問題なくテストも実行することができました。

テストの結果、成果率が出力される

コード解説

MNISTの学習とテストを実行できたと思いますので、次はコードの内容について解説していきます。

データ読み込み

MLDatasetsからMNISTをロード
  • ここでは、MLDatasetsから、MNISTの学習用データとテスト用データを読み込んでいます
  • MLDatasetsは機械学習で使用される一般的なデータを提供するパッケージです
  • train_data(Float32)で学習用の入力データ(train_x)と正解データ(train_y)を出力します
  • テスト用のデータも同じ要領です

では、実際にMNISTに含まれる手書き数字の画像を表示させてみましょう。

MNISTに入っている最初の画像

5と書かれた数字のグレースケール画像を表示させることができました。画像にコンバートしないで表示させてみると以下のようになります。

画像を行列で表したもの

学習時には、このような0~1の数値で表された行列をモデルに入力します。

モデル定義

モデル定義
  • ここでは、MNISTを解くための深層学習モデルを定義しています
  • レイヤーには全結合層とドロップアウトを用いており、入力層が28×28、中間層が32、出力層が10(0~9までの数値に対する確率)というようになっています
  • Chainは、複数のレイヤーや関数をチェーンして、特定の入力で順番に呼び出せるようにします

パラメータ

modelをFlux.paramsに渡す
  • 学習時に更新するモデルのパラメータをFlux.paramsに渡しています
  • パラメータは目的関数の勾配を計算するために使用されます

最適化関数

最適化関数を定義
  • 最適化関数にはADAMオプティマイザーを使用します

損失関数

損失関数を定義
  • 損失関数にはlogitcrossentropyを用います
  • 処理的にはcrossentropy(softmax(ŷ), y)と同じですが、crossentropyで個別にsoftmaxを使用するよりも数値的に安定しています

コールバック関数

コールバック関数を定義
  • バッチごとにlossの結果を返すコールバック関数を定義しています

学習

学習を実行
  • train!に損失関数、パラメータ、学習データ、最適化関数を渡すことで、学習を実行することができます
  • 先頭に@epochs num_epochsとつけることで、エポック数を設定することができます
  • cb = throttle(evalcb, 5)は、各エポック5数秒間に最大1回コールバック関数を実行するように設定しています
  • train!はモデルのパラメーターを自動で更新してくれるので、単純なモデルを学習させる場合に便利です

テスト

accuracy関数
  • ここでは、バッチごとに正解率を計算し、最終的に正解率の平均をとるようにaccuracyという関数を定義しています
testmode!にmodelを渡し、accuracy関数を実行
  • DropoutやBatch Normalizationなどはテスト時には無効にしたいため、testmode!とします
  • accuracy関数にtest_dataを渡して実行すると正解率が返ってきます
  • test_dataは最初にMLDatasetsから読み込んだ1万件の手書き数字画像です

Pythonとの比較

  • ここまでJuliaでMNISTをやってきましたが、ここからはPython(TensorFlow)でも同じコードを作成し、学習速度の比較を行いたいと思います
  • 今回比較で使用するPythonコードはこちらにあります

実験設定

速度計測の対象は、学習が完了するまでの時間で、条件の詳細は下記になります。

  • 計測対象:学習開始から完了まで
  • 計測方法:5回計測し、学習時間の平均を比較対象とする
  • 実行環境:Google Colaboratory、GPUはTesla T4を使用する
  • Epoch数:10
  • 使用データ:MNISTの学習用データ(6万件)
  • Juliaでの計測方法
BenchmarkTools.jlを使用し、実行速度を計測
  • Pythonでの計測方法
%timeで実行速度を計測

結果

学習速度の結果を下記に示します。
Juliaの学習時間はPythonに比べて3倍程度速い結果となりました。

 回数 Julia  Python 
  1回目  9.2  31.7
  2回目  9.2  31.5
  3回目  9.6  33.3
  4回目  9.9  31.6
  5回目  9.4  31.7
 平均 9.46 31.96
学習時間の測定結果(s)

続いて、MNISTのテストデータ(1万件)の正解率を示します。念のため、正解率も出してみましたが、JuliaとPythonで大きな差はなく、どちらもMNISTを解けているようです。

 回数 Julia  Python 
  1回目 0.966  0.962
  2回目 0.965  0.966
  3回目 0.968  0.963
  4回目 0.966  0.967
  5回目 0.969  0.960
 平均 0.967 0.964
正解率の測定結果

おわりに

今回は、JuliaでMNISTを解く深層学習モデルを実装し、学習時間をPythonと比較しました。Juliaの方が3倍速いという結果になりましたが、パッケージの読み込みやコンパイル時間を含めた全体の実行時間では、まだまだPythonの方が速く、使いやすい気がしました。今回はMNISTということでしたが、より複雑な問題であれば、Juliaにも明確な優位性が出てくるのかもしれません。

(K.K)

追記:関連

 Julia関連記事については、次にもまとめてあります。

タイトルとURLをコピーしました