[ 機械学習 ] MNISTデータの画像認識実装(ライブラリ不使用) 2.モデル作成 ~ 失敗まで

[ 機械学習 ] MNISTデータの画像認識実装(ライブラリ不使用) 2.モデル作成 ~ 失敗まで

本記事は、学習機能を伴ったニューラルネットワークを作成し、学習を行い、失敗するところまでを取り扱います。
失敗したものを記事にするのはどうかとも思ったのですが、個人的な記録としては価値あるものなのであえて書くことにします。

 

今回の内容は前回の続きとなりますので、まだそちらをご覧で無ければ前回記事からお読みいただければ幸いです。

[ 機械学習 ] MNISTデータの画像認識実装(ライブラリ不使用) 1.知識まとめ~データの準備まで

記事構成

  1. データの準備(前回記事)
  2. モデルの定義
  3. 学習の実行
  4. 失敗まとめ
  5. 画像の判定実験

前回のまとめ(1. データの準備)

前回の記事では、画像認識に使用する画像データを用意しました。

単にデータを用意すると言っても、画像データそのままではニューラルネットワークに読み込ませることはできません。機械学習を行うためにはいくつかの前処理が必要となります。

簡単におさらいすると、次のようなことを行なったのでした。

  1. MNISTデータの呼び出し
  2. 画像データの標準化
  3. 正解データの行列化
  4. 訓練データの抽出

詳しくは、前回記事を参照してください。

 

実装

2. モデルの定義

ここではニューラルネットワークのモデルを定義します。
また、モデルで使用するいくつかの関数についてもここで実装を行います。

必要な関数は次の通りです。

  1. シグモイド関数
  2. ソフトマックス関数
  3. 交差エントロピー誤差関数
  4. 勾配取得関数

モデル本体には、次のような機能をもたせます。

  1. モデルの初期化関数(___init___)
    モデルを初めて呼び出した時に、パラメータをランダムな値で初期化する。
  2. パラメータの形状確認関数(printParamsShape)
    設定されたパラメータのshapeを確認する。必須ではない。
  3. 予測値出力関数(predict)
    現在設定されているパラメータに基づき、予測値を出力する。
  4. 損失取得関数(get_loss)
    現在設定されているパラメータに基づき取得された予測値と正解データを比較し、損失を出力する。
  5. 勾配取得関数(call_get_gradients)
    現在設定されているパラメータについて、損失関数に対する勾配を取得する。

 

では、上記のような仕様に基づいて関数及びモデルの実装を行います。

関数群及びモデルの定義

 

3. 学習の実行(失敗)

ここまでで、使用する画像データの準備とモデルの定義が終了しました。
いよいよ、学習を実行していきましょう。

今回の学習仕様は次の通りとします。

  • 学習回数は 200 回とする。
  • 一度の学習で使用するデータは、全データから無作為に抽出した 100 件とする。
  • 学習率(一度の学習でパラメータを更新する割合)は 0.1 とする。

つまり今回は、パラメータを200回更新することでモデルを最適化するという過程をとります。

では、学習処理を実装していきましょう。

予め述べておくと、ここでの学習は失敗しました。

先ほど定義したモデルを呼び出し、指定回数の学習を行なっています。
順調に行けば学習のたびに損失関数が減少していくはずなのですが、今回はここで問題が発生しました。

下の図が、実行時の損失の推移です。損失が思うように減少していないことがわかります。

 

問題の発生

ここではおきた問題をまとめると、つぎのようになります。

 

  1. 損失の減少が緩やかすぎる。
  2. 学習に時間がかかりすぎる。
  3. 損失を減少させるのに十分な学習数になっていない

まず 2 ですが、今回はテスト用として学習数 200 を設定しています。が、この実行だけでも私のPCでは30分程度を要しました。これで結果が出るならば良いのですが、それにしてもあまりに時間がかかっています。

そして1です。損失は少しずつ減少しているのですが、あまりに緩やかで、モデルを最適化できているとは言い難いものです。恐らくこれは、層の数に対して学習数が不足していることに起因するものと思われます。(上記プログラムをベースに2層のネットワークも構築してみましたが、そちらはもう少しまともな結果が出ました)

 

問題の原因

今回は3層のネットワークですが、それでも学習数 200 というのは不足であり、学習数をもっと増やさなければいけないということが判明しました。

ですが、私のPCのスペック的にはこれ以上学習数を増やすと、結果を出すまでに数日かかってしまいます。従って、方法を変えるしかありません。

では、今回の処理に時間を要している原因は、勾配を計算する処理にあります。
勾配を求めるに当たって、対象の変数の極限の変化率を求めているわけですが、その処理を全パラメータに対して行なっているために非常に時間がかかるということになっています。

問題の解決

上記のように勾配を一つ一つ計算すると時間がかかってしまうことがわかりました。

それを解決する方法が、誤差逆伝播という勾配計算方法です。
誤差逆伝播と言う技術を用いると、一つ一つの勾配計算にかかる時間が大幅に短縮されます。処理に時間がかからなければ学習数を増やすこともできるので、結果的にモデルを最適化することができるわけです。

この方法の詳細についてはいずれ記事にまとめることとして、まずはこの技術を使用してモデルを作り直してみたいと思います。

が今回の記事はすでに長くなってしまいましたので、次回の記事でモデルの再定義を行なっていきたいと思います。

 

今回のまとめ

  1. 学習を行うためには、画像データ、使用する関数、ベースになるネットワークの定義が必要
  2. 層の大きさに応じて、パラメータの計算には時間がかかるようになる
  3. 勾配を一つ一つ計算すると、モデルを最適化するのに非常に時間がかかる

 

最後に

今回の失敗の原因は学習数不足にあると断定しましたが、他の原因にお気づきになられた方がいましたら、教えていただけると嬉しいです。

 

 

以上

MachineLearningカテゴリの最新記事