Python DeepLearningに再挑戦 5 手書き数字認識
概要
Python DeepLearningに再挑戦 5 手書き数字認識
参考書籍
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
- 作者: 斎藤康毅
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/09/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (6件) を見る
MNIST データセット
学習済みのパラメータを使って、推論処理だけを実装する。 mnistのデータを取得する。
import sys, os sys.path.append(os.pardir) from dataset.mnist import load_mnist # (訓練画像, 訓練ラベル), (テスト画像、テストラベル)という形式で、mnistデータを読み込む (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False) # normalize : 入力画像を0.0~1.0の値に正規化するかどうかの設定。Falseの場合は、ピクセルは元の0~255のまま。 # flatten : 入力画像を平らにする(1次元配列にする)かどうかを設定する。Falseに設定すると、1x28x28の3次元配列、Trueにすると784個の要素からなる1次元配列として格納される。 # one_hot_label : [0,0,1,0,0,0...] などのように正解となるラベルだけが1、それ以外が0の配列として表記される。
データの確認がてら、MNIST画像を表示させてみる。
from PIL import Image import numpy as np def img_show(img): pil_img = Image.fromarray(np.uint8(img)) # 配列からimageを生成する?復元する? pil_img.show() (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False) img = x_train[0] # x_trainの0番目のデータを取り出す。(画像情報) label = t_train[0] # t_trainの0番目のデータを取り出す(ラベル情報) print(label) # 5が表示されるはず。 img = img.reshape(28,28) # イメージは1次元配列になっているので、元の画像サイズに変形する。 img_show(img) # 手書きの5の文字が表示されるはず。
無事データセットが読み込まれていることが確認できた。
ニューラルネットワークの推論処理
入力層を784個、出力層を10個のニューロンで構成するらしい。 784というのは、画像サイズの28x28=784かららしい。なるほど、そいうことか!! 1つ1つのピクセル?から確率を割り振って、推論していくのか〜!
イメージ図は以下のような感じかなぁ。
入力層784, 出力層10, 第1層 50, 第2層 100 のニューロン
# はじめに3つの関数を定義する。 # データセットをゲットする。 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 # 重みのパラメータをsample_weight.pkl(重みの学習済みデータ)から読み込む def init_network(): with open("sample_weight.pkl", 'rb') as f: network = pickle.load(f) return network # シグモイド関数と出力層にsoftmaxを使った推論処理 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
学習済みデータがあるとかなりシンプルに定義できるな(^^) この関数を使って、認識精度の評価を行うコードを記載する。
def sigmoid(x): return 1 / (1 + np.exp(-x)) def softmax(a): c = np.max(a) exp_a = np.exp(a-c) sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y import pickle x, t = get_data() # x_testテスト画像, t_testテストラベルを読み込む network=init_network() # sample_weight.pkl を読み込んで、networkに代入する。 accuracy_cnt = 0 # accuracy_cntを初期化する。数字があっていたら、+1にする。 for i in range(len(x)): # テスト画像のすべてのデータを1枚1枚取り出して処理する。 y = predict(network, x[i]) # predict p = np.argmax(y) # argmaxで、一番大きい数値のラベルを取り出す。 if p == t[i]: # 正解のラベル名と、pがあっているかを確認する。 accuracy_cnt += 1 print("Accuracy:" + str(float(accuracy_cnt) /len(x))) #確率を計算する。 >>> Accuracy:0.9352
なるほど〜〜!!これは学習済みデータが圧倒的に重要なことがわかった。 画像の場合は、ピクセル値255(最大値)で徐算・割り算して、データの値を0〜1の間に収まるように変換する。 決まった範囲に変換する処理を、正規化する。 正規化も含めて、色々決まった変換をすることを、pre-processing前処理という。
今回は、画像の場合は、255で割るだけの正規化だったけど、色々テクニックがあるようで、その辺りもゆくゆくは調べてみたい。
いや〜〜、機械学習すごい!