SIGMA-SE Tech Blog

SIGMA-SE Tech Blog


当サイトは、過去に運営していた別ドメイン(unisia-se.com)から sigma-se.com へ移行した技術ブログです。
旧サイトの記事をもとに、内容の精査・加筆・最新化を行い再構成しています。
正確で実用的な情報提供を目的としています。

Python - ニューラルネットワーク:6/14 MNIST推論処理の実装

概要

MNISTデータを使い、学習済みの重みパラメータによるニューラルネットワークの推論処理を整理する。

推論とは、入力データをネットワークに通し、最終的な出力から予測結果を得る処理となる。

ここでは、入力層、中間層、出力層の計算を関数化し、手書き数字画像に対する予測の流れを確認する。

この記事で扱うこと

  • 推論処理の全体像。
  • 入力層、中間層、出力層の値の流れ。
  • 重み、バイアス、活性化関数を使った計算手順。
  • 予測結果を正解ラベルと比較する考え方。

作業前に確認すること

確認項目 内容
MNISTMNISTデータを読み込める状態にしておく。
NumPy行列積、配列shape、argmaxの基本を確認しておく。
前提知識活性化関数とソフトマックス関数の役割を確認しておく。

概念の説明と実装サンプル

推論処理の実行準備

参考文献の『ゼロから作るDeep Learning』から提供されている推論処理のサンプルコード(ch03/neuralnet_mnist.py)をダウンロードする。

Git(deep-learning-from-scratch): https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/dataset/mnist.py

MNISTのダウンロードについては、前の記事 > Python - ニューラルネットワーク: MNISTのダウンロード方法(手書き数字画像セットを取込む)> MNISTのダウンロードを参照

推論処理のニューロン構成と関数定義

  • ニューロン構成について
    入力層:784個(画像データ28 x 28 = 784(px))
    隠れ層1:50(任意の値)
    隠れ層2:100(任意の値)
    出力層:10(数字0~9の10クラス)

  • 実装サンプル(関数定義)
    以下、ch03/neuralnet_mnist.py内の3つの関数定義。

    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
    

    init_network()では、pickleファイルとなるsample_weight.pklを読み込んでいる。

    ※ pickleファイルには、重みとバイアスのパラメータがdictionary型で保存されている。
    ※ predict(network, x)のsigmoid, softmaxについては、下記を参考。
    Python - ニューラルネットワーク: ニューラルネットワークの活性化関数と実装サンプル
    Python - ニューラルネットワーク: 活性化関数の実装サンプルまとめ(ステップ、シグモイド、ReLU、恒等関数、ソフトマックス関数)

推論処理の実行

  • ch03/neuralnet_mnist.py内の実行処理

    x, t = get_data()    # … 1.
    network = init_network()    # … 2.
    
    accuracy_cnt = 0
    for i in range(len(x)):    # … 3.
        y = predict(network, x[i])    # … 4.
        p= np.argmax(y)    # … 5.
        if p == t[i]:    # … 6.
            accuracy_cnt += 1    # … 7.
    
    print("Accuracy:" + str(float(accuracy_cnt) / len(x)))    # … 8.
    
  • 実行処理の解説

    1. get_data()でMNISTデータセットを取得。
    2. init_network()でpickleファイルを読み込む。
    3. \(x\)の画像データ60000枚をfor文でループ。
    4. 1枚の画像データに対してpredict(network, x[i])を実行し、下記のNumPy配列のように数字0~9それぞれの確立を出力。
      ※ 0である確率:20%、1である確率:10%、2である確率:4%、… 9である確率:5%
      [ 0.2, 0.1, 0.04 , … , 0.05  ]    # 0 ~ 9 それぞれの確率 (20%, 10%, 4%,  … , 5%)
      
    5. 「4.」の結果であるNumPy配列\(y\)に対して、最も確率が高い要素のインデックスを取得。
    6. 推論処理出した「5.」の予測結果が正解ラベル\(t\)と一致しているかチェック。
    7. 一致していれば、認識制度を加算。
    8. 最後に正解率を出力。
  • 実行結果
    実際に上記を対話モードで実行するとAccuracy:0.9352が出力される。

    $ cd gitlocalrep
    $ cd deep-learning-from-scratch/ch03
    $ source /var/www/vops/bin/activate
    $ python neuralnet_mnist.py
    Accuracy:0.9352
    

    上記実装サンプルでは、93%程度の精度だったが、実際のニューラルネットワークでは、さらにニューラルネットワークの構造や「4.」の関数predict内の処理にあたる学習方法を工夫し、99%以上の精度を出していく。

違いを整理する

比較する項目 整理するポイント
学習と推論の違い推論では重みを更新せず、入力から出力を計算する。
shape不一致入力、重み、バイアスの形が合わないと行列計算でエラーになる。
argmaxの意味出力の中で最も大きい値の位置を予測クラスとして扱う。

実務とのつながり

  • モデル利用の基本
    学習済みモデルをアプリケーションに組み込むときは、まず推論処理の流れを理解する必要がある。
  • 精度確認
    正解ラベルと比較することで、モデルがどれくらい正しく分類できているかを確認できる。

まとめ

  • 推論は、学習済みの重みを使って入力から予測を得る処理。
  • 各層では、行列積、バイアス加算、活性化関数の適用を行う。
  • shapeを確認しながら実装すると、計算の流れを追いやすい。

参考文献

  • 斎藤 康毅(\(2018\))『ゼロから作るDeep Learning - Pythonで学ぶディープラーニングの理論と実装』株式会社オライリー・ジャパン


Copyright SIGMA-SE All Rights Reserved.
s-hama@sigma-se.jp