『Neural Networks and Deep Learning』読書ノート:最も簡単なMNISTを識別するニューラルネットワークプログラム(2)


転載は出典を明記してください.https://www.codelast.com/
本文は前の文章の続きです.「Neural Networks and Deep Learning」という本の中国語訳名は「ニューラルネットワークと深い学習」で、本はその名の通り、説明する必要もなく何を言っているのか、これは入門級の良い本です.第1章では,著者らは,MNISTデータを識別するための簡単なPythonニューラルネットワークプログラムをどのように記述するかを示した.本文は次に前の文章でプログラムコードを解析した.SGD()メソッドの実装を見てみましょう.まず、その完全なコードを貼り付けます.
def SGD(self, training_data, epochs, mini_batch_size, eta,
test_data=None):
"""Train the neural network using mini-batch stochastic
gradient descent.  The ``training_data`` is a list of tuples
``(x, y)`` representing the training inputs and the desired
outputs.  The other non-optional parameters are
self-explanatory.  If ``test_data`` is provided then the
network will be evaluated against the test data after each
epoch, and partial progress printed out.  This is useful for
tracking progress, but slows things down substantially."""
if test_data: n_test = len(test_data)
n = len(training_data)
for j in xrange(epochs):
random.shuffle(training_data)
mini_batches = [
training_data[k:k + mini_batch_size]
for k in xrange(0, n, mini_batch_size)]
for mini_batch in mini_batches:
self.update_mini_batch(mini_batch, eta)
if test_data:
print "Epoch {0}: {1} / {2}".format(
j, self.evaluate(test_data), n_test)
else:
print "Epoch {0} complete".format(j)

コードには詳細なコメントが付いていて、分かりやすいです.記事の出典:https://www.codelast.com/forj in xrange(epochs)というコードは、訓練がepochホイールを行うようにする.xrang()はPythonが持つ関数で、勝手に試してみるとその役割がわかります.例えば:
for j in xrange(4):
print(j)

このコード出力の結果は、次のとおりです.
0
1
2
3
したがって,epochを4と定義すると,サイクルは4回,すなわち訓練は4ラウンドで行われる.記事の出典:https://www.codelast.com/明らかに、for j in xrange(epochs)の下の循環体のコードは、訓練ごとに実行されるコードである.まずrandomshuffle(training_data)という文の役割は何ですか?答え:ランダムにtrainingを乱すdataというリスト.それを説明するために、ipythonを開いて、かなり簡単な実験をしました.
import numpy as np
import random
a = [(1, 2), (3, 4), (5, 6), (7, 8), (0, 9)]
random.shuffle(a)
print(a)
random.shuffle(a)
print(a)
random.shuffle(a)
print(a)

上記のコードでは、aの内容を3回印刷しましたが、私のPCでは、3回printの出力はそれぞれ以下の通りです.
[(7, 8), (0, 9), (1, 2), (3, 4), (5, 6)] [(3, 4), (5, 6), (0, 9), (7, 8), (1, 2)] [(1, 2), (0, 9), (5, 6), (3, 4), (7, 8)]
見えますrandomshuffle()はリストの要素をランダムに乱した.ランダムなので、あなたのテスト結果は私とは違うかもしれません.ランダム乱れデータは、いくつかのpattern類似の入力データが1つのbatchに集中することを防止し、訓練結果に悪影響を及ぼすことを防止するためである.SGDは「ランダム勾配降下」ではないか.記事の出典:https://www.codelast.com/データを乱すと、プログラムはすべての入力データをいくつかのロット(mini batch)に分割し、各batchのサイズはmini_batch_size定義:
mini_batches = [
training_data[k:k+mini_batch_size]
for k in xrange(0, n, mini_batch_size)]

ここでのxrangeの使い方は、上記のxrangeとは少し異なり、その役割を示す例を示します.
for k in xrange(0, 10, 3):
print(k)

このコードはmini_batch_sizeは3に設定され、その出力結果は:
0
3
6
9
kを0からminiを押すと表示されます.batch_sizeのサイズはステップサイズで増加しますが、最大値は2番目のパラメータを超えません.
だから、training_dataもこのやり方で分割を実現した.
記事の出典:
https://www.codelast.com/
training_data分割でいくつかのmini batchが得られた後,以下では各mini batchをそれぞれ訓練し,パラメータベクトルを求める
w和
bの値.しかし、ここではシリアル計算です.つまり、最初のmini batchの計算が終わってから、2番目のmini batchの計算の番になります.
各mini batchに対してパラメータベクトルを解くのは,実はこのコード呼び出し(eta,すなわち
η,学習率,これは1人がその値を設定するためのスーパーパラメータである):
self.update_mini_batch(mini_batch, eta)

これは求められるパラメータベクトルwとbとは関係ないと言う人もいるかもしれません.前回の記事では、wとbがNetworkクラスのメンバー変数として定義されていることを示しました.update_mini_batch()は実は関数内で計算し、更新した値なので、表面的には「大丈夫」に見えるだけで、実際には完全に関係しています.
すべてのmini batchをループ反復した後、wとbの値も更新され、すなわち「学習」の過程も終了する.従って,反復が進むにつれてwとbの値はますます理想値に近づき,すべての反復が終了すると,wとbの値が理想値に達したと考えられる.記事の出典:https://www.codelast.com/各反復の最後に、次のコードがあります.
if test_data:
print "Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)
else:
print "Epoch {0} complete".format(j)

各ラウンドの反復がwとbの値を更新した後、test_dataが空でなければevaluate()法で本輪の計算結果を評価します.理論的には,反復が1回1回行われるにつれて,評価結果はますます良くなるべきである.記事の出典:https://www.codelast.com/だから、今最も重要なコードはupdateにカプセル化されています.mini_batch()メソッドで.この方法はどのようにwとbを計算したのですか?次回の分解を聞いてください.