Skip to content

DNET_NeuralNetworkInference

nishi_74322014 edited this page Sep 11, 2026 · 1 revision

ニューラルネットワーク(推論)

概要

推論フェーズでは、信号は順方向に伝播する。

行列の積による実装

簡単なニューラルネットワークの実装

対象(簡単なニューラルネットワーク)

バイアスと活性化関数を省略し重みだけとする。

X行列 * W行列=Y行列

┌      ┐ ┌          ┐   ┌                               ┐
│a1  b1│ │a2  b2  c2│ = │a1a2+b1d2  a1b2+b1e2  a1c2+b1f2│
└      ┘ │d2  e2  f2│   └                               ┘
         └          ┘
  X行列       W行列                   Y行列
  1行2列       2行3列                   1行3列
     ─        ─
     └────┘

簡単なニューラルネットワークの実装

┌    ┐ ┌       ┐   ┌                   ┐
│a  b│ │1  3  5│ = │1a+2b  3a+4b  5a+6b│
└    ┘ │2  4  6│   └                   ┘
       └       ┘
  X行列   W行列            Y行列
  1行2列   2行3列            1行3列
     ─    ─
     └──┘

実装(簡単なニューラルネットワーク)

>>> x=np.array([1,2])
>>> x
array([1, 2])
>>> w=np.array([[1,3,5],[2,4,6]])
>>> w
array([[1, 3, 5],
       [2, 4, 6]])
>>> y=np.dot(x,w)
>>> y
array([ 5, 11, 17])

3層のニューラルネットワークの実装

対象(3層のニューラルネットワーク)

前述の「簡単なニューラルネットワーク」を3層化する。

3層のニューラルネットワークの実装

  • 第一層目の計算の例
    入力が1行2列、出力が1行3列

    • 重み付き信号とバイアスの和

      • a(1)1 = w(1)11 x1 + w(1)12 x2 + b(1)1
      • a(1)2 = w(1)21 x1 + w(1)22 x2 + b(1)2
      • a(1)3 = w(1)31 x1 + w(1)32 x2 + b(1)3
    • これを行列で表すと、
      入力が1行2列、出力が1行3列だから、

      A(1) = X(1) W(1) + B(1)
      
      • X(1) = [x1 x2]

      • A(1) = [a(1)1 a(1)2 a(1)3]

      • W(1) = W(1)は、2行3列

        ┌                    ┐
        │w(1)11 w(1)21 w(1)31│
        │w(1)12 w(1)22 w(1)32│
        └                    ┘
        
      • B(1) = 出力が1行3列だから、

        [b(1)1 b(1)2 b(1)3]
        
      • 活性化関数
        Sigmoid関数(ニューラルネットワークの該当節を参照)を使用する。

        h(A(1)) = Z(1)
        
  • 第二層目の計算の例
    入力が1行3列、出力が1行2列だから、

    • 第一層目と大方、同じ。

      • X(2) = 1行3列
      • A(2) = 1行2列
      • W(2) = 入力が1行3列、出力が1行2列だから、W(2)は、3行2列
      • b(2) = 出力と同じ、1行2列
  • 第三層目の計算の例
    入力が1行2列、出力が1行2列だから、

    • 第一層目と大方、同じ。

      • X(3) = 1行2列
      • A(3) = 1行2列
      • W(3) = 入力が1行2列、出力が1行2列だから、W(3)は、2行2列
      • b(3) = 出力と同じ、1行2列
    • 活性化関数だけ異なる。

実装(3層のニューラルネットワーク)

そのまんま実装した。

"""This is a test program."""

import numpy as np

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

def identity_function(y_1):
    """出力層の活性化関数"""
    return y_1

# 第一層
X1 = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

print("第一層")
A1 = np.dot(X1, W1) + B1
print("A1:" + str(A1))
Z1 = sigmoid(A1)
print("Z1:" + str(Z1))

# 第二層
X2 = Z1
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])

print("第二層")
A2 = np.dot(X2, W2) + B2
print("A2:" + str(A2))
Z2 = sigmoid(A2)
print("Z2:" + str(Z2))

# 第三層
X3 = Z2
W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])

print("第三層")
A3 = np.dot(X3, W3) + B3
print("A3:" + str(A3))
Z3 = identity_function(A3)
print("Z3:" + str(Z3))

慣例的実装

  • init_networkで、ニューラルネットワークを定義/初期化し、
  • forwardで入力から出力方向への伝達処理を行う。
"""This is a test program."""

import numpy as np

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

def identity_function(y_1):
    """出力層の活性化関数"""
    return y_1

def init_network():
    """ニューラルネットワーク"""
    network = {}
    networkw = {}
    networkw[0] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    networkw[1] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    networkw[2] = np.array([[0.1, 0.3], [0.2, 0.4]])
    networkb = {}
    networkb[0] = np.array([0.1, 0.2, 0.3])
    networkb[1] = np.array([0.1, 0.2])
    networkb[2] = np.array([0.1, 0.2])
    network["W"] = networkw
    network["b"] = networkb
    return network

def forward(network, zzz):
    """ニューラルネットワークの実行"""
    tier = len(network["W"])

    for num in range(tier - 1):
        print("第" + str(num + 1) + "層")
        xxx = zzz
        aaa = np.dot(xxx, network["W"][num]) + network["b"][num]
        print("A" + str(num + 1) + ":" + str(aaa))
        zzz = sigmoid(aaa)
        print("Z" + str(num + 1) + ":" + str(zzz))

    print("第" + str(tier) + "層")
    xxx = zzz
    aaa = np.dot(xxx, network["W"][tier -1]) + network["b"][tier -1]
    print("A" + str(tier) + ":" + str(aaa))
    zzz = identity_function(aaa) # 出力層の活性化関数
    print("Z" + str(tier) + ":" + str(zzz))

    return zzz

print(forward(init_network(), np.array([1.0, 0.5])))

出力層の設計

活性化関数

  • ニューラルネットワークは

    • 分類問題と

      • 入力データがどのクラスに属するか?
      • 例:写真から男性・女性を識別する。
    • 回帰問題に

      • 入力データから連続的な数値を予測する。
      • 例:写真からその人の体重を予測する。

用いることができる。

を利用する。

恒等関数

  • f(x) = x
    
  • 特徴

    • 回帰問題で使用。
    • 入力をそのまま返す。
  • グラフ

恒等関数

Sigmoid関数

  • 2クラス分類の機械学習で使用される。
  • xで条件付けされたyのベルヌーイ分布(統計解析の該当節を参照)を推定。
  • オッズの対数を取ったロジット関数の逆関数
    統計解析のロジスティック回帰分析の節を参照)らしい。
  • 中間層の活性化関数として既出なので、実装など詳細については
    ニューラルネットワークの該当節を参照。

Softmax関数

  • 多クラス分類の機械学習で使用される。

  • xで条件付けされたyのマルチヌーイ分布(統計解析の該当節を参照)を推定。

  • Sigmoid関数を多クラスに拡張、一般化したもの。

  • Softmax関数の結果は

    • 0 - 1 の実数になり、その総和は 1.0 になる。
    • 従って、Softmax関数の結果は「確率」として解釈できる。
    • これは多クラス分類問題で使用できる。
    • 分類では、一番大きい値のみを使用する。
    • Softmax関数を使用しても値の大小関係は変わらないので
      順方向の推論フェーズにおいては、Softmax関数は省略可能である。

対象(Softmax関数)

            exp(Ak)
Yk = ───────────
            n
           Σexp(Ai)
           i=1

Sigmoid関数(ニューラルネットワークの該当節を参照)の項で説明した通り、

  • exp(x)とは、eのx乗を意味する。
  • eは ネイピア数(2.7182)の実数を表す。

Softmax関数

実装(Softmax関数)

  • そのまま実装
>>> a=np.array([0.3, 2.9, 4.0])
>>> a
array([ 0.3,  2.9,  4. ])
>>> exp_a = np.exp(a)
>>> exp_a
array([  1.34985881,  18.17414537,  54.59815003])
>>> sum_exp_a = np.sum(exp_a)
>>> sum_exp_a
74.122154210163302
>>> y = exp_a / sum_exp_a
>>> y
array([ 0.01821127,  0.24519181,  0.73659691])
>>>
  • 関数化
"""This is a test program."""

import numpy as np

def softmax(aaa):
    """Softmax関数"""
    exp_a = np.exp(aaa)
    sum_exp_a = np.sum(exp_a)
    return exp_a / sum_exp_a

print(softmax(np.array([0.3, 2.9, 4.0])))

オーバーフロー対策の実装

Softmax関数は指数関数を使用するため、オーバーフローし易い。
従って、ここでは、オーバーフロー対策について考える。

  • 以下のように変形できる。
            exp(Ak)
Yk = ───────────
            n
           Σexp(Ai)
           i=1

          C exp(Ak)
   = ───────────
            n
         C Σexp(Ai)
           i=1

            exp(Ak + logeC)
   = ───────────
            n
           Σexp(Ai + logeC)
           i=1
  • 例えば、

    • 10の3乗は、10の1乗*10の2乗 = 1,000

    • 10の4乗は、10の2乗*10の2乗 = 10,000

    • なので、下のような変形ができるということになる。

       (a+b)    a    b
      X      = X  * X
      
  • X の b 乗 = C は、b = logxC であるから、下のようになる。

       a    a    logxC     (a+logxC)
    C X  = X  * X       = X
    
              exp(Ak + C')
     = ───────────
              n
             Σexp(Ai + C')
             i=1
    
  • Cは、入力信号中の最大値を使用する。
    これによって、オーバーフローが発生し難くなる。以下に実装を示す。

"""This is a test program."""

import numpy as np

def softmax(aaa):
    """Softmax関数"""
    exp_a = np.exp(aaa - np.max(aaa))
    sum_exp_a = np.sum(exp_a)
    return exp_a / sum_exp_a

# print(softmax(np.array([0.3, 2.9, 4.0])))
print(softmax(np.array([1010, 1000, 990])))

ニューロンの数

出力層のニューロンの数は、問題に合わせて決定する。

  • 分類問題 : 分類する数に合わせる。
  • 回帰問題 : 多分、1つにする。

手書き数字画像の認識

  • 実践的な手書き数字画像の認識を行う。
  • ここでは、学習済みのパラメタを使用して実装をする。

MNISTデータセット

機械学習分野で最も有名なデータセット

概要(MNISTデータセット)

  • 手書き数字の画像セット

    • 数字の0-9で構成され、以下の画像を使用して学習/推論を行う。

      • 学習用の訓練画像 :60,000枚
      • 推論用のテスト画像:10,000枚
  • 28*28の単一チャンネル、グレー画像

    • 画像の1つのピクセルは、0-255の8ビット
    • 画像には、正解を意味するラベルが与えられている。
    • 白黒画像は行列で表現でき、
      カラー画像は テンソル(行列 * RGB)で表現できる。

データの取得

c:\deep-learning-from-scratch-master\ch03>python mnist_show.py
Downloading train-images-idx3-ubyte.gz ...
Done
Downloading train-labels-idx1-ubyte.gz ...
Done
Downloading t10k-images-idx3-ubyte.gz ...
Done
Downloading t10k-labels-idx1-ubyte.gz ...
Done
Converting train-images-idx3-ubyte.gz to NumPy Array ...
Done
Converting train-labels-idx1-ubyte.gz to NumPy Array ...
Done
Converting t10k-images-idx3-ubyte.gz to NumPy Array ...
Done
Converting t10k-labels-idx1-ubyte.gz to NumPy Array ...
Done
Creating pickle file ...
Done!
5
(784,)
(28, 28)

c:\deep-learning-from-scratch-master\ch03>python mnist_show.py
5
(784,)
(28, 28)
  • 一回目はWebからのダウンロードは成功したが、画像表示ができなかった。
    二回目以降は、ローカル保存した*.pklからデータを読み込むようで、画像表示できた。
    なお、*.pklファイルは、pythonのbinaryserialize的なpickleによって生成されている。

    • \dataset\mnist.pkl は、MNISTデータ
    • \ch03\sample_weight.pkl は、重みパラメタ

推論処理

ニューロン構成(推論処理)

  • 入力層が784個、出力層が10個とする。

    • 入力層が784個 = 28 * 28 のピクセル数
    • 出力層が10個 = 分類問題なので、0 - 9 のクラス
  • 中間層(隠れ層)の数は任意だが、ココでは以下の値に設定。

    • 第一層:50個
    • 第二層:100個

実行(推論処理)

以下のように
neuralnet_mnist.py
実行すると、

>python neuralnet_mnist.py
  • 推論用のテスト画像:10,000枚の分類結果の正解率が表示される。
  • なお、ここでは、画像データに正規化(normalize)の前処理(preprocessing)を行っている。

バッチ化

バッチについてはニューラルネットワーク(学習)の該当節を参照。

ニューロン構成(バッチ化)

  • 上記の
    neuralnet_mnist.py
    処理中の重みパラメタを確認すると、
    この、ニューラルネットワークが以下の様なものであることを確認できる。

batch1

  • バッチ化は、X行列、Y行列の行を増やして
    データを纏めて投入できるようにするだけで良い。
    ソレに合わせてW行列も変わるがbに変更はない(1行n列)。

batch2

実行(バッチ化)

以下のように
neuralnet_mnist_batch.py
実行すると、

>python neuralnet_mnist_batch.py
  • neuralnet_mnistと比べ、100枚づつのバッチ処理が行われ、高速化される。
  • 正解の判定処理は、true値をsumするという方法を使用している。
  • なお、np.argmaxの引数、axis=1は行方向の最大値となる要素のインデックスを求める。

移行メモ:本ページの図の元となる PowerPoint ファイルが添付されていたため、
DNET_NeuralNetworkInference_temp.pptx として併置した。


Tags: 移行, 人工知能, 深層学習, ニューラルネットワーク, 推論, Softmax, MNIST, Python

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally