Pythonと機械学習

Pythonも機械学習も初心者ですが、頑張ってこのブログで勉強してこうと思います。

多層パーセプトロンの実装

目次

はじめに

  • 前回前々回は多層パーセプトロン理論編でした。今回は実装編です。

  • 基本的なネットワークの構成は、全結合と活性化関数を1セットにして中間層分だけ入れて、最後にソフトマックス関数と交差エントロピーを入れるようにしてやります。

  • 全結合と活性化関数の処理をするクラスを、全体の処理をする多層パーセプトロンクラスとは別に作ることにしました。

  • 全結合と活性化関数のクラスには、順伝播と逆伝播を実行する関数を個別に作成しています。こうする事で、容易に中間層の数を増やせるようになります。

  • 実装後は学習結果をscikit-learnの多層パーセプトロンの結果と比較しました。

  • また今回は深層学習用のモジュールkerasを使って学習した結果とも比較してみました。

活性化関数の実装部

  • シグモイド関数tanh関数、ReLU関数の他に、入力をそのまま出力するlinear関数を実装しています。

  • 順伝播と逆伝播の処理をする関数forward_prop()back_prop()を作りました。

ソフトマックス関数の実装部

  • ソフトマックス関数は逆伝播が特殊なので、活性化関数クラスと分けることにしました。

  • 逆伝播時は交差エントロピーと一緒に処理させることにしてます。

全結合の実装部

  • 入力に重みをかけて閾値を足す全結合クラスです。

  • 基本的には、順伝播と逆伝播の処理をすればいいのですが、重みと閾値の初期化関数initialize_weights()を追加しました。

  • 今まで重みと閾値の初期化に関してあまり気にしていませんでしたが実は超重要です。

  • 層が深くなった場合は、特に重みの初期値をうまく設定しないと活性化関数にReLUを使っても全然学習が進みません。

  • 活性化関数にシグモイド関数tanhを使う場合は、Glorotの初期値。ReLUを使う場合はHeの初期値にするといいみたいです。

  • __init__()引数のkernel_initializerは重みの初期設定、bias_initializer閾値の初期設定です。(kerasのドキュメントを参考にしました。)

  • また、重み・閾値のアップデート関数(46行目のupdate_weights())も追加しています。サンプル数で割って1サンプルあたりの平均値にしていることに注意してください。

多層パーセプトロン実装部

  • 活性化関数クラスと全結合クラスを組み合わせて複数レイヤーを実装するようにしています。(71行目のcreate_layers())

  • 順伝播(91行目のforward_prop())と逆伝播(106行目のback_prop())では、活性化関数クラスと全結合クラスのforward_prop()back_prop()をレイヤー順に呼び出すようにしています。

  • 活性化関数と全結合の処理を別クラスに分けることで、中々小綺麗に実装できたのではないかと思います。

  • 125行目の重み・閾値アップデート関数update_weights()では、各レイヤーの全結合クラスのupdate_weights()を順番に呼び出すようにしています。

  • 131行目の交差エントロピー関数cross_entropy()ですが、ミニバッチのサンプル数に依存しないように、こちらもサンプル数で割って1サンプル当たりの平均値にしていることに注意してください。

学習実施

  • 例によってアヤメのデータを使います。いい加減アヤメを使うのは飽きてきましたが、データを変えると今まで色々やってきた結果との比較ができないですし...。まあ、分かりやすいのでアヤメを使っておきましょう。

  • データの前処理(アヤメデータのロード、教師データのonehotエンコーディング、データのシャッフル、トレーニング・テストデータ分割、特徴量の標準化)は全部scikit-learnの関数を使ってます。

  • 学習器を多層パーセプトロンに変更しただけで、多クラスロジスティック回帰を実装したときとほぼ一緒です。

  • MultiLayerPerceptronの引数hidden_layer_sizes=(10,10,10)で、ユニット数10の中間層を3層入れてます。入力層と出力層合わせて全部で5層あります。

  • hidden_layer_sizes=(10,)*100などとするとユニット数10の中間層が100層入ります。

  • 以下学習履歴のグラフと、最終エポックでのトレーニングとテストの正答率を出力する様にしています。うまく学習できていますね。

acc_train: 1.0   acc_test:0.9555555555555556

scikit-learnで実行した結果

  • 最終エポックでのトレーニングとテストの正答率です。まあこんなもんでしょう。
acc_train: 1.0   acc_test: 0.9555555555555556

Kerasで多層パーセプトロン

  • 今回はscikit-learnだけでなく、ディープラーニングのモジュールのkerasを使って結果を比較してみました。

  • kerasは、tensorflowをバックエンドで動かすラッパーなのですが、非常に使いやすくなってます。ちょっとscikit-learnに似てます。

  • tensorflowをそのまま使ってもいいのですが、文法が少々特殊で慣れるまで結構難しいです。

  • kerasはscikit-learnを使ったことがあれば、ちょっと似ているので、すんなり使えるようになると思います。

  • いずれにしろWindowsのPython2.7では、動かないので、今回Anacondaを導入することにしました。

  • ちなみにPython環境ですが、Windows版のAnaconda3-4.3.25でPython3.6.1を使ってます。

  • Python2.7も入ったままですが、環境変数PATHからC:\Python27とC:\Python27\Scriptsを削除しておけば問題ないです。

  • Anacondaは非常に楽ですね。numpy、scipy、pandas、matplotlib、jupyter等が最初から入ってますし、Anacondaナビゲーターと言うGUIで仮想環境を作れたり、モジュールをインストールできたりするツールがあるので楽です。

  • scikit-learnとtensorflowはAnacondaナビゲーターからインストールできますが、kerasはインストールできるリストにないのでpipを使ってインストールします。

  • Anaconda、tensorflow、kerasのWindowsへのインストールは、全く難しくありませんのでwebで適当に検索してみてください。

  • 以下がkerasで多層パーセプトロンを実装した例です。

  • 最終エポックでのトレーニングとテストの正答率です。自作版、scikit-learn版と大体一致ですね。
acc_train: 1.0   acc_test: 0.9555555582046509

学習履歴の比較

  • 最後に自作版、scikit-learn版、keras版で学習履歴をプロットして比較してみました。(scikit-learn版はトレーニングデータの学習履歴しか取ってこれませんでした。)

  • ハイパーパラメータはほぼ同じ設定にしたと思うのですが、keras版は収束が速いですね。

  • 結局、keras版で収束が速くなる原因は分からなかったのですが、まあ、そこまで気にする違いでも無いので、取り敢えずは良しとしときましょう。