MNISTデータセットを学習させてみよう|Excel VBAでMNIST機械学習
本ページではこれまでに実装したコードを使ってMNISTデータセットでの学習を行なっていきます。
このページで行った学習の結果をもとに次回以降で自身の描いた手描き文字の識別を行うため、ここでしっかりとした精度の高い学習済みデータを作成しておきましょう。
まだレイヤやクラス等の実装ができていない方はメインページの「ニューラルネットワーク作成編」をもとにニューラルネットワークを構築してから本ページに臨んで下さい。
事前準備
学習を始める前にまずはニューラルネットワークの学習教材となる「MNISTデータセット」をブック内に用意しておく必要があります。
「MNISTデータセットのダウンロード」でダウンロードしたCSVファイルの「mnist_train」と「mnist_test」のシートをそのままマクロと同じブックにコピペ(or移動)します。(下画像では「mnist_test」だけになっていますが「mnist_train」も忘れず同じようにコピペして下さい)
コピペができたらVBE上でそれぞれのシートのオブジェクト名を「ws_mnist_train」と「ws_mnist_test」に変更します。
最終的には以下のような構成になっていればOKです。
ここで、標準モジュールやクラスモジュールの構成も併せて確認しておきましょう。
(「Sheet1」は予測時に使うので、そのまま残しておいて下さい)
以上で事前準備は完了です。
※VBE上にイミディエイトウィンドウが表示されていない場合は、[表示]>[イミディエイトウィンドウ](ショートカット[Ctrl]+[G])から表示状態にしておいて下さい。学習時に必要になります。
ハイパーパラメータ設定
学習設定としてハイパーパラメータを変更します。
(標準モジュール[Main]のコード内でハイパーパラメータの数値を変更するということ)
変更可能なハイパーパラメータは以下のとおりです。
hidden_size:隠れ層のニューロン数
batch_size:バッチサイズ(まとめて何個のデータを学習するかを決める)
LearningRate:学習率(この値が小さいほど学習時間は長くなるが精度の高い学習ができる)
train_size:学習用データのデータ数
test_size:テスト用データのデータ数
MinLoss:最少Loss値(学習終了条件)
MaxEpoc:最大エポック数(学習終了条件)
はじめはデフォルトのままにしておけば問題ありません。
学習結果を見て精度を上げたいと感じたら変更してください。
学習量やニューロン数を増やせば精度が上がるという単純なものではないため、学習結果を確認しながら上げ下げして微調整していく必要があります。
MNIST学習
ハイパーパラメータの設定が完了したらあとはメインモジュールの「Sun train」を実行するだけで学習を始めることができます。通常のマクロのようにユーザーフォームやコマンドボタンから実行するわけではなく、VBE上で実行することを前提としているので注意してください。
学習精度の確認
学習を開始すると、イミディエイトウィンドウに以下のように学習精度が表示されていきます。
これはMNISTデータをbatch_size回(デフォルト:100)学習する毎の学習精度を表します。
つまり初めの1行目は100(batch_size)個のMNISTデータをもとに学習したニューラルネットワークの精度を表し、2行目はさらに100個のMNISTデータを追加して学習した精度を表しています。この1行(100回の学習)のことを「1エポック」といいます。(実際の意味は少し違いますが)
出力される精度は左から順に
[エポック回数][Loss値][学習用データでの正解率][テスト用データでの正解率]となっています。
エポック回数:batch_size回の学習をまとめて1エポックとした時の現在のエポック数を表す
Loss値:値が0に近づくほど適切なパラメータに近づくことを表す
学習用データでの正解率:学習用データでの現在のニューラルネットワークの正解率を表す
テスト用データでの正解率:テスト用データでの現在のニューラルネットワークの正解率を表す
この中で1番注目すべき項目は1番右の「テスト用データでの正解率」です。
テスト用データとは学習には使用していないデータで、言い換えればニューラルネットワークがまだ見たことのないデータであり、この未学習データでの精度確認が非常に重要になってきます。
というのも、ニューラルネットワークは学習をすればするほど学習用データに”特化”していきます。特化というと精度が良くなるようにきこえますが、特化させすぎてしまうと、学習用データと少しでも違う場合に正解を全く導き出せなくなってしまいます。
つまり極端な話、学習データの60000個の画像データは確実に当てることができるが、それ以外の手描き数字画像データを入力しても全く当たらないという状態になります。
これは、いわゆるところの「汎化性」がなくなってしまった状態です。
ニューラルネットワークにはこの汎化性が必要で、これがないと全く融通の効かないニューラルネットワークになってしまいます。(イメージとしては受験勉強でやった問題集は全て解けるのに、実際のテストでは全く解けないという状態です)
このようにニューラルネットワークが学習用データに特化しすぎ、汎化性を失ってしまった学習状態のことを「過学習」といい、機械学習をやるうえでは避けなければならない問題です。
「テスト用データでの正解率」に注目するのは「過学習」が起きていないかを確認するためです。
「学習用データでの正解率」が高いのに、「テスト用データでの正解率」が異様に低い場合は、過学習が起きていると判断することができます。
正常な動きとしては「学習用データでの正解率」の方が「テスト用データでの正解率」より少し精度が高い状態を維持しながら、同じくらいの比率で精度が上がっていくイメージです。(多少の上がり下がりは気にしなくて大丈夫です)
最終的にニューラルネットワークに推論させる我々の手描き画像のデータは、もちろん学習用データと全く同じなわけがありません。そのため未学習である「テスト用データでの正解率」がニューラルネットワークの本来の精度を表しているというわけです。
学習の終了
「テスト用データでの正解率」があまり伸びなくなってきた、もしくは過学習になりかけていると感じたら学習を終了させましょう。
学習はハイパーパラメータで設定した「MinLoss」「MaxEpoc」を満たすか、[F7]キーを押した場合に終了します。箇条書きでまとめておくと、以下の3つが学習終了の条件です。
① Loss値が「MinLoss」を下回ったとき
② エポック回数が「MaxEpoc」を上回ったとき
③ [F7]キーが押されたとき
精度を見ながらいい感じになったら[F7]キーで終了させることもできますし、「MinLoss」「MaxEpoc」をうまく指定しておき、昼寝の間に過学習が起きない程度に学習させることもできます。
※コピペしたままのコードの場合、時間はかかりますが300回~500回ほどは学習させましょう。
学習を終了すると「Parameters」というシートが作成され、学習結果がそこに出力されます。
一見意味不明な数字が羅列されているように見えますが、これらは「Affineレイヤ」の全ての重みパラメータとバイアスパラメータを表しています。
この学習結果(シート)を使うことで、ニューラルネットワークの推論を行ったり、2回目以降の学習に再利用することができます。
2回目以降の学習
2回目以降の学習(厳密にいうと「Parameters」という名前のシートが存在する場合)では以下のようなメッセージが表示されます。ここでは学習済みのデータをどうするかを指定することができます。
上記のメッセージの各ボタンの内容は以下の通りです。
[はい]:現在の学習済みデータを利用し続きから学習を始めます
[いいえ]:現在の学習済みデータを残しつつ、新規で学習を始めます
[キャンセル]:キャンセルします
[いいえ]を押すと以下のようなウィンドウが立ち上がります。
現在の学習済みデータは「Parameters」からここで入力した名称へ変更され、最新の学習結果は新たに作成される「Parameters」シートに出力されます。
新たに名前をつけた学習済みデータも、再度「Parameters」という名前に変更することで続きから学習を行うことができます。
いらなくなった学習済みデータ(シート)は随時、手動で消しても問題ありません。
まとめ
今回はこれまでに実装したモジュールを使いMNIST学習を行いました。
学習の手順を簡単にまとめると以下のとおりです。
① MNISTデータセット(CSVファイル)の取り込み
② ハイパーパラメータの設定
③ [Main]モジュールの[Sub train]をVBE上で実行
④ 学習の精度を確認しながら学習を終了する(or 終了まで待つ)
⑤「Parameters」シートに学習結果が出力される
2回目以降の学習では前回の学習結果を引き継ぐことも、新規作成することもできるのでうまく使い分けましょう。
いろいろやってきましたが、一番欲しかったのは「Parameters」シートに出力された学習結果(「Affineレイヤ」の重みパラメータとバイアスパラメータ)です。
あとはこの学習済みのパラメータをニューラルネットワークに取り込むことで、自身の描いた手描き数字が何かを推論させることができます。
初めのうちはあまり深く考えず、「テスト用データでの正解率」の値が毎回90〜95%を超えるようになったら学習を終了しておきましょう。(この90〜95%は自身の描いた手描き数字を当てる確率とイコールといえます)
次回は自身の描いた手描き数字をニューラルネットワークに取り込むための前処理を行なっていきます。一番の難所である「学習」のフェーズが終わったのであとはあまり気負わずにいきましょう。
参考書籍