Yabu.log

ITなどの雑記

ニューラルネットワークでの手書き画像分類の処理イメージ

ゼロから作るディープラーニング第3章の後半の整理です。本書で最初のニューラルネットワークの動くサンプルはMNISTと言われる定番の手書き数字画像を判別するものについて書かれています。これの処理イメージを整理したいと思います。

MNISTデータセット

28×28pxの手書き画像(数字1~9)のセット。グレースケールであり黒色の濃淡を0~255で表現されています。

f:id:yuyubu:20180427223349p:plain プログラム上では28×28の2次元配列、もしくは784要素*1の1次元配列で、値は0~255までの値をとります。

https://en.wikipedia.org/wiki/MNIST_database

学習データの一つをエディタで整形して表示してみたけどこんな感じ。 f:id:yuyubu:20180427211409p:plain

もちろんこのデータのラベルは「5」

元画像はこんな感じ

f:id:yuyubu:20180427211935p:plain

MNISTを数値(0-9)に分類するニューラルネットワーク

  • 入力は画像を正規化*2したものをとる(28×28=784要素の配列)
  • 出力は分類結果を取る(要素が10の配列)

になります。出力層の活性関数はsoftmax関数になっており、最終的に入力の画像はどの数字になるか?を0〜9の数字ごとに確率を表す要素を10個持つ配列になります

イメージとしてはこんな感じです

5の画像=>ニューラルネットワーク=>[1の確率:1%, 2の確率:0%,...5の確率:90%,...]

上記のデータ(手書き数字の5)をニューラルネットワークぶち込んで検証してみます。

>>> predict(network, x_train[0])

するとこんな配列が帰ってきました。

array([1.0667706e-02, 1.5830112e-04, 4.3034455e-04, 2.1552832e-01,
       5.6906956e-06, 7.6759964e-01, 3.0164907e-05, 3.1157802e-03,
       1.6654776e-03, 7.9853699e-04], dtype=float32)

指数表記は分かりにくいのでゴニョゴニョして変換します

>>> def convert(f):
...     return "%.2f" % f
>>> r2 = [convert(f) for f in result]
>>> r2
['0.01', '0.00', '0.00', '0.22', '0.00', '0.77', '0.00', '0.00', '0.00', '0.00']

最終的に出力結果は['0.01', '0.00', '0.00', '0.22', '0.00', '0.77', '0.00', '0.00', '0.00', '0.00']

となりました。0の確率が1パーセント,3の確率は22%,5の確率は77%,そのほかの数字はとても低い確率,という結果になりました。

ただしこれは学習データなので分類できて当然です。正しく学習できたかは訓練データとして使っていないテストデータを利用する必要があります。

*1:28*28=784

*2:0~255で表していたものを0~1.0で表すよう正規化