-Deep Learning- 推論を行うニューラルネットワーク

前回の投稿で読み込んだMINSTデータセットに対して推論処理を行うニューラルネットワークを実装する例を以下に示します.

ネットワークは,入力層を784個,出力層を10個のニューロンで構成します.入力層の784個は,画像サイズの28 x 28 = 784からきています.出力層の10個は10クラス分類(0 - 9 の10クラス)からきています.
隠れ層は2層で,一つ目の隠れ層は50個,2つ目の隠れ層は100個のニューロンを持つものとします.この50と100は任意に設定できます.

def sigmoid(x):
    return 1 / (1 + np.exp(-x))
 
def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T
 
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  = sigmoid(a3)
 
 
    return y
 

sigmoid(x)は,シグモイド関数softmax(x)は,ソフトマックス関数です.
init_network()では,pickleファイルのsample_weight.pklに保存された学習済みの重みパラメータを読み込みます.このファイルには,重みとバイアスのパラメータを読み込みます.このファイルには,重みとバイアスのパラメータがディクショナリ型の変数として保存されています.
これらの3つの関数を使って,ニューラルネットワークによる推論処理を行い,認識精度を評価するコード例を以下に示します.

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) # Get the index of the most probable element
    if p == t[i]:
 
        accuracy_cnt += 1
 
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
 
 

最初にMINISTデータセットを取得して,ネットワークを生成します.そして,に格納された画像データを1枚ずつfor文で取り出し,predict()関数によって分類を行います.predict()関数の結果は各ラベルの確率がNumPy配列として出力されます.この確率リストからnp.argmax(x)関数によって最大値のインデックスを取得して,それを予測結果とします.np.argmax(x)関数は,引数xに与えられた配列で最大の値を持つ要素のインデックスを取得する関数です.
そして,最後にニューラルネットワークが予測した答えと正解ラベルを比較して,正解した割合を認識精度accuracy_cntとします.

コード全体は以下のようになります.

 
# Import Module
import sys, os
sys.path.append(os.pardir)  # Setting of import from Parent Directory
import numpy as np
import pickle
from dataset.mnist import load_mnist
 
# Definition of Function
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
 
def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T
 
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  = sigmoid(a3)
 
    return y
 
# Execution part
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) # Get the index of the most probable element
    if p == t[i]:
        accuracy_cnt += 1
 
# Display results
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
 
 

上記のコードを実行すると,以下のようになります.

Accuracy:0.9352
 

この結果は93.52%の確率で正しい分類が可能という結果を表します.この認識精度は,ニューラルネットワークの構造や学習方法を工夫することで,精度を向上させることが可能です.

また,上記の例では,load_mnist関数の引数であるnormalizeにはTrueを設定しています.normalizeTrueに設定すると,その関数内部では画像の各ピクセルの値を255で除算し,データの値が0.0 - 0.1の範囲に収まるように正規化(normalization)された値に変換されます.このように,入力データに対して何らかの決まった変換を行うことを前処理(pre-processing)といいます.