2017年07月26日

学習本の3章のサンプルプログラムneuralnet_mnist.prをも少し詳しく解説してみます(2)

storage.mantan-web.jp_images_2017_05_21_20170521dog00m200017000c_001_size8.jpg

deeplearning1.jpg

この本を学習しています。

この本の構成は次の通りです。

1章 Python入門
2章 パーセプトロン
3章 ニューラルネットワーク
4章 ニューラルネットワークの学習
5章 誤差逆伝播法
6章 学習に関するテクニック
7章 畳み込みニューラルネットワーク
8章 ディープラーニング
付録A Softmax-with-Loss レイヤの計算グラフ
参考文献

前回、この3章ニューラルネットワークのサンプルプログラムとして次のプログラムを紹介しました。

ファイル名:neuralnet_mnist.py
----------------------------------------------------------------------
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
return x_test, t_test


def init_network():
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f)
return network


def predict(network, x):
W1, W2, W3 = network['W1'], network['W2'], network['W3']
b1, b2, b3 = network['b1'], network['b2'], network['b3']

a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = softmax(a3)

return y


x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
y = predict(network, x[i])
p= np.argmax(y) # 最も確率の高い要素のインデックスを取得
if p == t[i]:
accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
----------------------------------------------------------------------

このプログラムを私流に少し掘り下げています。

前回はこのプログラムが入力された手書き数字の画像データからどうやって数字を判別しているのかを実際の値で追ってみました。

今回はプログラムが数字の判定を誤る場合を調べてみました。

このプログラムを実行すると次のような結果が表示されます。

(親ディレクトリ)\ch03>python neuralnet_mnist.py
Accuracy:0.9352

これは10000個のテスト用の画像データのうち9352個数字の識別に成功したということです。

では、数字の識別に失敗する場合はどういう場合か少し詳しく調べてみます。

次の画像はプログラムが数字の識別に失敗した画像です。

数字5-2err.jpg

さて、皆さんはこの画像を見て数字の何だと思いますか?

とてもクセのある字なので少し悩みますね。5のようにも見えますが、自信は持てないと思います。

ちなみに正解は5です。プログラムは6と判定しました。

以下が一番最後の出力データyの値です(縦に表示します)。

hyo2.jpg

95%の確率でプログラムは6だと思ったようです。5の確率は0.7%しかありません。

再度入力画像を見て見ましょう。

数字5-2err.jpg

これを6と判定したのも分からないでもないですね。

もう一例紹介します。

数字4-1.jpg

これが数字なのかと言いたくなりますが、該当しそうなのは4だろうなと思います。
でも、正直とても数字とは思えません。

以下がプログラムが計算した各数字の確率です。

hyo3.jpg

正解は4です。プログラムは6と判断しましたが、その確率は64.2%です。プログラムもあまり自信がなかったことが分かります。(笑)
正解の4の確率は4.5%で0の22.0%よりも低い確率です。

この2例から分かるようにプログラムが数字の判定に失敗する場合は、人間でも判定に悩む場合なのです。書く人の方に問題がある場合です。クセがあり過ぎてどの数字かよくわからないのです。

仮に学校の入学試験や企業の就職時の筆記試験で上記のような数字を書いたらはたして採点者が5や4と思ってくれるでしょうか。

少なくとも4は4と思ってくれないでしょう。

今回はこれで終わりです。







posted by tsurutsuru at 15:02| Comment(0) | 日常茶飯事

学習本の3章のサンプルプログラムneuralnet_mnist.prをも少し詳しく解説してみます(1)

storage.mantan-web.jp_images_2017_05_21_20170521dog00m200017000c_001_size8.jpg

deeplearning1.jpg

この本を学習しています。

この本の構成は次の通りです。

1章 Python入門
2章 パーセプトロン
3章 ニューラルネットワーク
4章 ニューラルネットワークの学習
5章 誤差逆伝播法
6章 学習に関するテクニック
7章 畳み込みニューラルネットワーク
8章 ディープラーニング
付録A Softmax-with-Loss レイヤの計算グラフ
参考文献

前回、この3章ニューラルネットワークのサンプルプログラムとして次のプログラムを紹介しました。

ファイル名:neuralnet_mnist.py
----------------------------------------------------------------------
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
return x_test, t_test


def init_network():
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f)
return network


def predict(network, x):
W1, W2, W3 = network['W1'], network['W2'], network['W3']
b1, b2, b3 = network['b1'], network['b2'], network['b3']

a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = softmax(a3)

return y


x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
y = predict(network, x[i])
p= np.argmax(y) # 最も確率の高い要素のインデックスを取得
if p == t[i]:
accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
----------------------------------------------------------------------

このプログラムを私流に少し掘り下げてみます。

a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3
y = softmax(a3)

この部分を実際の画像データを使って数値の変化を追ってみます。

手書き画像は次の7の画像とします。

数字7-1.jpg

この手書き画像のデータは以下の通りです。

gazou7data1.jpg
(画像をクリックすると拡大して見れます)

元データは(784,)ですが、(28,28)にしてあります。

このデータが入力されると、次のように値が変わっていきます。x[0]には正規化された入力画像データが入っています。正規化とは元データを255で除算してデータが0〜1の範囲になるようにすることです。ですから、0〜255の値が0〜1になっています。

hyo1.jpg
(画像をクリックすると拡大して見れます)

小さくて見づらいので左側だけ取り出してみます。

hyo11.jpg

yの値の行だけ取り出すと次のようになります。

hyo12.jpg

見やすくするため2段にしてあります。

yの値をすべて足すと1になります。ですから、yの値は確率と同等の意味になります。

これをみると7が99.7%だと分かります。

それでプログラムは入力された手書きの画像データを7と判別します。正解です。

こんな風にプログラムは手書きの画像データの数字を判別しています。

面白いですね。

最後にプログラムに出てくる sigmoid関数のグラフを描いてみます。

sigmoid()

Figure_32.png

このグラフを描くプログラムは以下の通りです。 sigmoid関数の定義もこれを見ると分かります。

ファイル名: sigmoid.py
-----------------------------------------------------------------
# coding: utf-8
import numpy as np
import matplotlib.pylab as plt


def sigmoid(x):
return 1 / (1 + np.exp(-x))

X = np.arange(-5.0, 5.0, 0.1)
Y = sigmoid(X)
plt.plot(X, Y)
plt.ylim(-0.1, 1.1)
plt.show()
-----------------------------------------------------------------

今回はここまでです。

posted by tsurutsuru at 11:28| Comment(0) | 日常茶飯事