barus's diary

とても真面目なblogですにゃ

VC++でニューラルネットワークによる手書き文字認識その⑤(オリジナル訓練データの追加)for VS2017

本ソフトウェアは、ニューラルネットワークと深層学習(著:Michael Nielsen )で

紹介されていたPythonで書かれたコードnetwork.pyを元にVC++でアレンジをしたもの。

今回は、まとめとなる。 ソースコードここからダウンロードできるようにした。

ソースコードの解説は以下①~④記事参照。

但し、①~④で紹介したものとはソースコードは全く同じではなく、多少いじっております。( ゚Д゚)

 

C++でニューラルネットワーク その① ・・PythonのコードをVC++に書き換え

C++でニューラルネットワーク その② ・・PythonのコードをVC++に書き換え

C++でニューラルネットワーク その③ ・・重みとバイアスを外部に記録

C++でニューラルネットワーク その④ ・・オリジナル訓練データの追加 

C++でニューラルネットワーク その⑤ ・・まとめ、文字認識アプリ

 

 アプリケーションはここからダウンロードできます。

f:id:hatakeka:20171020112252p:plain

NNmodelGUI_sourceフォルダには、GUI本体のフォルダ内に、コンソールとDLLのソースが以下のように配置しています。

.
├── NNmodelDLL.dll    ←DLL
├── NNmodelGUI.exe   ←プログラム本体
├── NNmodelGUI_source
│   ├── NNmodelGUI   ←本体のソースコード
│   │   ├── NNmodelConsole ←コンソールのソースコード
│   │   ├── NNmodelDLL  ←DLLのソースコード
├── Readme.txt
├── train-file   ←作業フォルダ
│   ├── train-images.idx3-ubyte  ←ここからダウンロードして配置
│   └── train-labels.idx1-ubyte    ←ここからダウンロードして配置
└── 使用例
├── 例1_mnistデモ.gif
├── 例2_オリジナルデモ.gif
├── 例3_オリジナルひらがなデモ.gif
└── 例4_オリジナル14マス出力層3デモ.gif

 

MNISTデータ(文字データ)は、ここからダウンロードする必要があります。

今回は、オリジナル訓練データを追加できるようにしてみた。

なので、MNIST データに頼らずとも オリジナル訓練データを作成することが出来ます。

※但し、オリジナル訓練データを作成するのは手作業で地道にやるしかないので、かなりしんどいです(;'∀')。

  

 例① ネットワーク[784 100 10]の数字判定(入力層28x28、出力10)

 例② ネットワーク[784 120 70 35 15 10]の数字判定(入力層28x28、出力10)

 例③ ネットワーク[1764 120 70 35 15 10]のひらがな判定(入力層42x42、出力10)

 例④ ネットワーク[196 81 3]の出力が3の場合の(/ + o)判定(入力層14x14、出力3)

 

このように、入力層と出力層と中間層を変更できるようし、

オリジナル訓練データを作成し学習できるようにした。

 

以下に例を示す。

 

 

MNIST訓練データの利用

例① ネットワーク[784 100 10]の数字判定

入力層28x28、出力10

グリッドの設定

28x28(784)size10」を指定して「セット」ボタンを押す。

 

「訓練data」の設定

訓練データ

train-images.idx3-ubyte

train-labels.idx1-ubyte

のファイルはここからダウンロードしてtrain-fileフォルダ(作業フォルダ)に配置する。

作業フォルダはデフォルトでは「train-file」となっている。

ダウンロードしたMNIST データセットの読み込みの確認方法

アプリケーションと同じフォルダに「setting.txt」ファイルがあればこれを削除、もしくは名称変更すれば初期起動と同じとなる。初期起動の状態で、コマンドはそのままで、「MNIST read」ボタンを押してMNIST 訓練データ(train-images.idx3-ubyte、train-labels.idx1-ubyte)を読み込み成功するとreading.tradingdata reading..と表示される。次に「Index」に0~5万9999の範囲の数字を入力し「MNIST view」ボタンを押した際に、グリッドに数字が表示されれば、正常にMNIST データセットが読み込まれた。(以下のgif画像参照)

f:id:hatakeka:20171020112339p:plain

 MNIST訓練データは28x28で固定なので入力層を変更できない。 

※このMNISTの訓練データは、オリジナル訓練データの学習では必要ではない。

学習した内容を記録するファイル名を「weightとbiases」に指定する。

以下の形式で保存されていく。

8 ←学習回数
network=[array([784,50,10])]    ←ネットワーク
biases=[array([-0.828435051648776]・・・,[-1.896426398453763])] ←バイアスの値

weights=[array(-0.924953936537927,0.02・・・,-3.377555057371262)] ←重みの値

MNIST データでは「訓練data」のファイル名は関係ない 

 

 「weightとbiases」の設定

 学習した内容を記録するファイル名を「weightとbiases」に指定する。

  

コマンド

network=784 500 10,epochs=10,mini_batch_size=10,eta=3.0,testdata_n=700,n_test=100,roopcnt=100,outputlist=0 1 2 3 4 5 6 7 8 9 

 

以下コマンドの説明

コマンドは param1=aaaa,param2=bb,param3=cccc,param4=dddd,のようにパラメータ=値と紐付けされて、カンマで区切られている。

 

network=784 500 10

ネットワークを記述するMNIST データの「入力層」=784、「出力層」=10で固定。隠れ層は任意、それぞれを半角スペースで区切る。

outputlist=0 1 2 3 4 5 6 7 8 9

outputlistに正答を記述し、紐付けする。これもデフォルトのまま変更しないものとし、それぞれは半角スペースで区切る。

testdata_n=700,n_test=100

testdata_nは、MNIST データの6万からランダムで切り出すデータ要素数なので、6万より小さい値を設定する。n_testはテストデータに相当するのでオリジナル訓練データ数、testdata_nより小さい値でないといけない。(オリジナル訓練データ数≧testdata_n>n_test)

epochs=3,mini_batch_size=10,eta=2.1

はそれぞれ、学習回数、バッチ数、学習率

roopcnt=100

roopcnt=1でもよい。データ要素から、testdata_n, n_testで

指定数のランダムで選び学習するのをroopcnt回繰り返す。

 

以上の、コマンドやファイル名等、決めたら一旦「設定保存」ボタンを押すと

アプリケーションと同じフォルダに「setting.txt」が作成される。

再起動時に、環境を復元するのでエラーで落ちた際に復帰しやすい。

 

学習させる

以上、コマンドを設定したら「MNISTを使った学習」ボタンを押すと「weightとbiases」に指定したファイルに学習した重みとバイアスが記録される。中断させる場合は「MNISTを使った学習」ボタンとなりの「 || 」ボタンを押す。重みと、バイアスを記録するファイル名を「BW_MNIST.txt」とした場合、正答率が「BW_MNIST.txt_正答率.log」としてファイルに記録される。

 

文字解析

「表示をリセット」ボタンを押す。グリッドにマウスで数字「0123456789」の1つを描画し「MNIST使った解析」ボタンを押すと、「weightとbiases」に指定したファイルを利用し機械判定されて結果が表示される。

 

使用している様子のgif画像

コマンド

network=784 100 10,epochs=10,mini_batch_size=10,eta=3.0,testdata_n=700,n_test=100,roopcnt=100,outputlist=0 1 2 3 4 5 6 7 8 9

f:id:hatakeka:20171019201456g:plain

 

 

 

オリジナル訓練データの作成

例② ネットワーク[784 120 70 35 15 10]の数字判定

入力層28x28、出力10.

オリジナル訓練データを作成し学習させるので、学習させるまえに

100以上の手書きデータを事前に入力する必要があるのでしんどい。

 入力層はMNIST データと同じ28x28とし変更しないものとする。

 

グリッドの設定

28x28(784)size10」を指定して「セット」ボタンを押す。

 

「訓練data」の設定

オリジナル訓練データを保存するファイル名を「訓練data」に指定する。

train-fileフォルダの「NewDataset_28x28.txt」に私が、マウス入力した数字「0123456789」のオリジナル訓練データが937個登録しているので、「訓練data」にNewDataset_28x28.txtファイルを指定する。「28x28(784)size10」をリストから選択し「セット」ボタンを押す。次に「MYDATAを読み込む」ボタンを押す。「Index」に0~937の数字を入力し「MYDATA View」ボタンを押してグリッドに表示されれば正常に読み込まれた。(以下gif画像参照)

 

「weightとbiases」の設定

学習した内容を記録するファイル名を「weightとbiases」に指定する。前述と、同じファイル名だとMNIST データで学習したファイルが上書きされるので、適当な名称にしておくとよいかと思う。

 

コマンド

network=784 120 70 35 15 10,epochs=15,mini_batch_size=10,eta=1.5,testdata_n=1000,n_test=100,roopcnt=100,outputlist=0 1 2 3 4 5 6 7 8 9

 

以下コマンドの説明

コマンドは param1=aaaa,param2=bb,param3=cccc,param4=dddd,のようにパラメータ=値と紐付けされて、カンマで区切られている。

 

network=784 120 70 35 15

ネットワークを記述するMNIST データの「入力層」=784、「出力層」=10。隠れ層は任意、それぞれを半角スペースで区切る。

outputlistに正答を記述する

outputlist=0 1 2 3 4 5 6 7 8 9

これもデフォルトのまま変更しないものとする。(半角スペースで区切る。)

testdata_nは、オリジナル訓練データからランダムで切り出すデータ要素数なので、オリジナル訓練データ数より小さい値を設定する。

testdata_n=1000

もしオリジナル訓練データ数より大きい値を設定していれば最大値が自動的に指定される。

次に、n_testにテスト数を記述する

n_test=100

これはオリジナル訓練データ数、testdata_nよりも小さい値でないといけない。もし、訓練データ数が100であれば、n_test=50くらいが無難である。

(オリジナル訓練データ数≧testdata_n>n_test)

epochs=15,mini_batch_size=10,eta=1.5

はそれぞれ、学習回数、バッチ数、学習率

roopcnt=100

roopcnt=1でもよい。データ要素から、testdata_n, n_testで

指定数のランダムで選び学習するのをroopcnt回繰り返す。

 

コマンドやファイル名、入力層決めたら一旦「設定保存」で状態を記録し再起動時に、環境を再現出来るようにしておくとエラーで落ちた際に復帰しやすい。

 

オリジナル訓練データの追加

コマンドで、outputlistを記述したらグリッドに「0 1 2 3 4 5 6 7 8 9」のいずれかを記述し解答に正解を記述する。グリッドに「0」を記述したら解答には「0」を記述する。この順番はどちらでもよい。「訓練データ追加」ボタン押すとグリッドはクリアされて、オリジナル訓練データが「訓練data」に記載されたファイル(NewDataset_42x42.txt)に追記される。この作業を繰り返す。

 

学習させる

 以上、オリジナル訓練データを十分に作成し、コマンドを設定したら「MYDATAを使った学習」ボタンを押すと「weightとbiases」に指定したファイルに学習した重みとバイアスが記録される。中断させる場合は「MYDATAを使った学習」ボタンとなりの「 || 」ボタンを押す。重みと、バイアスを記録するファイル名を「BW_オリジナル.txt」とした場合、正答率が「BW_オリジナル.txt_正答率.log」としてファイルに記録される。

 

文字解析

「表示をリセット」ボタンを押す。グリッドにマウスで数字「0123456789」の1つを描画し「MYDATA使った解析」ボタンを押すと、「weightとbiases」に指定したファイルを利用し機械判定されて結果が表示される。

 

使用している様子のgif画像

コマンド

network=784 120 70 35 15 10,epochs=15,mini_batch_size=10,eta=1.5,testdata_n=1000,n_test=100,roopcnt=100,outputlist=0 1 2 3 4 5 6 7 8 9f:id:hatakeka:20171019205426g:plain

 

 

 

例③ ネットワーク[1764 120 70 35 15 10]のひらがな判定

入力層42x42、出力10.

 グリッドの設定

42x42(1764)size7.5」を指定して「セット」ボタンを押す。

 

「訓練data」の設定

オリジナル訓練データを保存するファイル名を「訓練data」に指定する。

 train-fileフォルダの「NewDataset_42x42_ひらがな.txt」に私が、マウス入力したひらがな「あいうえおかきくこ」のオリジナル訓練データが284個登録しているので、「訓練data」にNewDataset_42x42_ひらがな.txtファイルを指定する。「42x42(1764)size7.5」をリストから選択し「セット」ボタンを押す。次に「MYDATAを読み込む」ボタンを押す。「Index」に0~284の数字を入力し「MYDATA View」ボタンを押してグリッドに表示されれば正常に読み込まれた。(以下gif画像参照)

 

「weightとbiases」の設定

 学習した内容を記録するファイル名を「weightとbiases」に指定する。

 

コマンド

network=1764 120 70 35 15 10,epochs=30,mini_batch_size=10,eta=1.5,testdata_n=1000,n_test=100,roopcnt=100,outputlist=あ い う え お か き く け こ

 

以下コマンドの説明

コマンドは param1=aaaa,param2=bb,param3=cccc,param4=dddd,のようにパラメータ=値と紐付けされて、カンマで区切られている。

 

 

network=1764 120 70 35 15 10

ネットワークを記述するMNIST データの「入力層」=1764、「出力層」=10。隠れ層は任意、それぞれを半角スペースで区切る。

outputlist=あ い う え お か き く け こ

入力層を決定したら次に出力層を決定する。outputlistに出力の0~9番目の解答を紐付けする。outputlist=あ い う え お か き く け こ」(半角スペースで区切る。)だと

0=あ  5=か

1=い  6=き

2=う  7=く

3=え  8=け

4=お  9=こ

それぞれの出力と解答が紐付けさせる。

 

testdata_nは、オリジナル訓練データからランダムで切り出すデータ要素数なので、オリジナル訓練データ数より小さい値を設定する。

testdata_n=1000

もしオリジナル訓練データ数より大きい値を設定していれば最大値が自動的に指定される。

次に、n_testにテスト数を記述する

n_test=100

これはオリジナル訓練データ数、testdata_nよりも小さい値でないといけない。 

(オリジナル訓練データ数≧testdata_n>n_test)

epochs=30,mini_batch_size=10,eta=1.5

はそれぞれ、学習回数、バッチ数、学習率

roopcnt=100

roopcnt=1でもよい。データ要素から、testdata_n, n_testで

指定数のランダムで選び学習するのをroopcnt回繰り返す。

 

コマンドやファイル名、入力層決めたら一旦「設定保存」で状態を記録し再起動時に、環境を再現出来るようにしておくとエラーで落ちた際に復帰しやすい。

 

オリジナル訓練データの追加

コマンドで、outputlistを記述したらグリッドに「あ い う え お か き く け こ」のいずれかを記述し解答に正解を記述する。グリッドに「あ」を記述したら解答には「あ」を記述する。この順番はどちらでもよい。「訓練データ追加」ボタン押すとグリッドはクリアされて、オリジナル訓練データが「訓練data」に記載されたファイル(NewDataset_42x42_ひらがな.txt)に追記される。この作業を繰り返す。

 

 

 学習させる

以上、オリジナル訓練データを十分に作成し、コマンドを設定したら「MYDATAを使った学習」ボタンを押すと「weightとbiases」に指定したファイルに学習した重みとバイアスが記録される。中断させる場合は「MYDATAを使った学習」ボタンとなりの「 || 」ボタンを押す。重みと、バイアスを記録するファイル名を「BW_オリジナル.txt」とした場合、正答率が「BW_オリジナル.txt_正答率.log」としてファイルに記録される。

 

文字解析

「表示をリセット」ボタンを押す。グリッドにマウスでひらがな「あいうえおかきくけこ」の1つを描画し「MYDATA使った解析」ボタンを押すと、「weightとbiases」に指定したファイルを利用し機械判定されて結果が表示される。

 

 

使用している様子のgif画像

コマンド

network=1764 120 70 35 15 10,epochs=30,mini_batch_size=10,eta=1.5,testdata_n=1000,n_test=100,roopcnt=100,outputlist=あ い う え お か き く け こ

f:id:hatakeka:20171019202634g:plain

 

 

 例④ ネットワーク[196 81 3]の出力が3の場合の(/ + o)判定

入力層14x14、出力3.

グリッドの設定

14x14(196)size20」を指定して「セット」ボタンを押す。

 

「訓練data」の設定

オリジナル訓練データを保存するファイル名を「訓練data」に指定する。

train-fileフォルダの「NewDataset_14x14_出力3.txt」に私が、マウス入力した「/ + o」のオリジナル訓練データが132個登録しているので、「訓練data」にNewDataset_14x14_出力3.txtファイルを指定する。「14x14(196)size20」をリストから選択し「セット」ボタンを押す。次に「MYDATAを読み込む」ボタンを押す。「Index」に0~132の数字を入力し「MYDATA View」ボタンを押してグリッドに表示されれば正常に読み込まれた。(以下gif画像参照)

  

「weightとbiases」の設定

 学習した内容を記録するファイル名を「weightとbiases」に指定する。

 

コマンド

network=196 81 3,epochs=3,mini_batch_size=10,eta=2.1,testdata_n=1000,n_test=10,roopcnt=100,outputlist=/ + o

 

以下コマンドの説明

コマンドは param1=aaaa,param2=bb,param3=cccc,param4=dddd,のようにパラメータ=値と紐付けされて、カンマで区切られている。

 

network=196 81 3

ネットワークを記述するMNIST データの「入力層」=196、「出力層」=。隠れ層は任意、それぞれを半角スペースで区切る。

outputlist=/ + o

入力層を決定したら次に出力層を決定する。

outputlistに出力の0~2番目の解答を紐付けする。outputlist=/ + o」だと

0=/  

1=+  

2=o  

それぞれの出力と解答が紐付けさせる。

入力層と出力層を決定したら、オリジナル訓練データを作成していく

 

testdata_nは、オリジナル訓練データからランダムで切り出すデータ要素数なので、オリジナル訓練データ数より小さい値を設定する。

testdata_n=1000

もしオリジナル訓練データ数より大きい値を設定していれば最大値が自動的に指定される。

次に、n_testにテスト数を記述する

n_test=10

これはオリジナル訓練データ数、testdata_nよりも小さい値でないといけない。

(オリジナル訓練データ数≧testdata_n>n_test)

epochs=3,mini_batch_size=10,eta=2.1

はそれぞれ、学習回数、バッチ数、学習率

roopcnt=100

roopcnt=1でもよい。データ要素から、testdata_n, n_testで

指定数のランダムで選び学習するのをroopcnt回繰り返す。

 

コマンドやファイル名、入力層決めたら一旦「設定保存」で状態を記録し再起動時に、環境を再現出来るようにしておくとエラーで落ちた際に復帰しやすい。

 

オリジナル訓練データの追加

コマンドで、outputlistを記述したらグリッドに「/ + o」のいずれかを記述し解答に正解を記述する。グリッドに「/」を記述したら解答には「/」を記述する。この順番はどちらでもよい。「訓練データ追加」ボタン押すとグリッドはクリアされて、オリジナル訓練データが「訓練data」に記載されたファイル(NewDataset_14x14_出力3.txt)に追記される。この作業を繰り返す。

 

 

 学習させる

以上、オリジナル訓練データを十分に作成し、コマンドを設定したら「MYDATAを使った学習」ボタンを押すと「weightとbiases」に指定したファイルに学習した重みとバイアスが記録される。中断させる場合は「MYDATAを使った学習」ボタンとなりの「 || 」ボタンを押す。重みと、バイアスを記録するファイル名を「BW_オリジナル.txt」とした場合、正答率が「BW_オリジナル.txt_正答率.log」としてファイルに記録される。

 

 

文字解析

「表示をリセット」ボタンを押す。グリッドに記号「/  +  o」の1つを描画し「MYDATA使った解析」ボタンを押すと、「weightとbiases」に指定したファイルを利用し機械判定されて結果が表示される。

 

 

使用している様子のgif画像

コマンド

network=196 81 3,epochs=3,mini_batch_size=10,eta=2.1,testdata_n=1000,n_test=10,roopcnt=100,outputlist=/ + o

 

f:id:hatakeka:20171020061105g:plain

 

 

ざっくりな説明

入力層と出力層と中間層を変更できるようし、オリジナル訓練データを作成し

学習できるようにした。

 

コマンド

コマンドは param1=aaaa,param2=bb,param3=cccc,param4=dddd, のようにパラメータ=値と紐付けされて、カンマで区切られている。

network //ネットワーク構造 examp network=784 30 10のように半角スペースで区切る。行列が6の場合入力は36となり、行列が42の場合入力は1764となる。

epochs, //世代(学習回数) examp 30

mini_batch_size, //ミニバッチサイズ examp 10

eta //学習率 examp 3.0

testdata_n  //訓練データ数。もし訓練データよりも大きい値を指定した場合、最大値が入る。

n_test      //訓練データからのテストする要素数。全体のtestdata_nから、ランダムでn_test選ばれ、残りが教師データとなる。オリジナル訓練データ数、testdata_nよりも小さい値でないといけない。(オリジナル訓練データ数≧testdata_n>n_test)

roopcnt  //「ランダムでテストを選び、学習回数学習する。」を、roopcnt繰り返す。

outputlist   //正答(出力)となるリスト、数値だけでなくひらがなや英数字も選択できるようにした。出力は2以上の任意数で、半角スペースで区切る。

 作業フォルダ

ここに訓練データ等のファイルを置く。デフォルトでは解凍したアプリケーションと同じフォルダの「train-file」フォルダが作業フォルダとなっている。

変更する場合、ボタン押すとコモンダイアログが開くので参照したいフォルダにある適当なファイルを選択して、開く(選択したファイルが開かれるわけではない)を押すとパスが指定される。

WeightとBiases

重みと、バイアスを記録するファイル名

コマンドで記載されたnetwork=784 50 10と、ファイルに記述された

ネットワークが異なる場合、再利用出来ない。

8 ←学習回数
network=[array([784,50,10])]    ←ネットワーク
biases=[array([-0.828435051648776]・・・,[-1.896426398453763])] ←バイアスの値

weights=[array(-0.924953936537927,0.02・・・,-3.377555057371262)] ←重みの値

f:id:hatakeka:20171020153013p:plain

訓練data

オリジナル訓練データのファイル名

ヘッダー部分とデータ要素として、以下の形式で保存される。

count=要素数,row=入力行数,col=入力列数

d=要素のグリッド部分を0と1で記録,anser=解答

f:id:hatakeka:20171020152453p:plain

設定保存

設定をアプリケーションと同じフォルダの「setting.txt」ファイルに記録する。これは再起動時に読み込まれ復元される。

f:id:hatakeka:20171020155815p:plain

 正答率のログ

重みと、バイアスを記録するファイル名を「BW_オリジナル.txt」とした場合、正答率を「BW_オリジナル.txt_正答率.log」ファイルに記録する

roopcnt回数

Epoch {学習回数}  : {正解数} / {テスト数}

f:id:hatakeka:20171020153245p:plain

 

 

 

 

今回は、PythonのNetwork2の畳み込みの機能は入れていない。

 

 

 

 以上