###前提・実現したいこと
現在ゼロから学ぶDeepLearningを使用して機械学習について勉強しています。
その中で、第四章の二層のネットワーク作成で躓いてしまったことがありました。
作成自体は理解できたのですが、なぜうまく動作しているのか理解ができませんでした。
###二層のネットワークのコード
Python
1import sys, os 2sys.path.append(os.pardir) 3from common.functions import * 4from common.gradient import numerical_gradient 5 6class TwoLayerNet: 7 8 def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01): 9 """ 10 input_size・・入力層の数 11 hidden_size・・中間層の数 12 output_size・・出力層の数 13 weight_init_std 14 """ 15 16 #重みの初期化 17 self.params = {} 18 self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) 19 self.params['b1'] = np.zeros(hidden_size) 20 self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) 21 self.params['b2'] = np.zeros(output_size) 22 23 24 def predict(self, x): 25 """ 26 入力値をもとに予測をする 27 """ 28 29 W1, W2 = self.params['W1'], self.params['W2'] 30 b1, b2 = self.params['b1'], self.params['b2'] 31 32 a1 = np.dot(x, W1) + b1 33 z1 = sigmoid(a1) 34 a2 = np.dot(z1, W2) + b2 35 y = softmax(a2) 36 return y 37 38 39 def loss(self, x, t): 40 """ 41 損失関数・・どれぐらい教師データと値が違うかを求める 返り値が大きいほど合っていない 42 x・・入力データ 43 t・・教師データ 44 """ 45 y = self.predict(x) 46 return cross_entropy_error(y, t) 47 48 49 def accuracy(self, x, t): 50 """ 51 返り値・・0から1の値 大きいほど入力データからの予測値と、教師データの値が一致している 52 """ 53 y = self.predict(x) 54 y = np.argmax(y, axis=1) 55 t = np.argmax(t, axis=1) 56 57 accuracy = np.sum(y == t) / float(x.shape[0]) 58 return accuracy 59 60 61 def numerical_gradient(self, x, t): 62 """ 63 重みパラメータに対する勾配を求める 64 x・・入力データ 65 t・・教師データ 66 grads・・勾配を保持するディクショナリ変数 67 """ 68 loss_W = lambda W: self.loss(x, t) #loss_Wはloss関数と等しい 69 grads = {} 70 grads['W1'] = numerical_gradient(loss_W, self.params['W1']) 71 grads['b1'] = numerical_gradient(loss_W, self.params['b1']) 72 grads['W2'] = numerical_gradient(loss_W, self.params['W2']) 73 grads['b2'] = numerical_gradient(loss_W, self.params['b2']) 74 return grads 75 76
###上記の二層ネットワーククラス内で使用しているnumerical_gradientのコード(本に付属しているコード)
Python
1def numerical_gradient(f, x): 2 h = 1e-4 # 0.0001 3 grad = np.zeros_like(x) 4 5 it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite']) 6 while not it.finished: 7 idx = it.multi_index 8 tmp_val = x[idx] 9 x[idx] = float(tmp_val) + h 10 fxh1 = f(x) # f(x+h) 11 12 x[idx] = tmp_val - h 13 fxh2 = f(x) # f(x-h) 14 grad[idx] = (fxh1 - fxh2) / (2*h) 15 16 x[idx] = tmp_val # 値を元に戻す 17 it.iternext() 18 19 return grad
###上記2つのコードに対しての入力コード
Python
1net = TwoLayerNet(input_size=784, hidden_size=100, output_size=10) 2x = np.random.rand(100, 784) #ダミーの入力データ 100枚 3y = net.predict(x) 4print(y.shape) #(100,10) 5 6t = np.random.rand(100, 10) #ダミーの正解ラベル(100枚分) 7grads = net.numerical_gradient(x, t)
###理解できない点
1.TwoLayerNetクラスのnumerical_gradient関数内で使用されているnumerical_gradient関数は,selfがついていないため、クラスの外側にあるcommon.numerical_gradient関数を使用しているという認識で正しいでしょうか?
2.TwoLayerNetクラスのnumerical_gradient関数を使用した勾配がどうして合っているのかわかりません。
numerical_gradient関数内のラムダ式「loss_W=lamda W:self.loss(x, t)」の引数(x,t)は、TwoLayerNetクラスのnumerical_gradient関数の引数である(self, x,t)の(x,t)から使用しているのでしょうか?
3.TwoLayerNetクラスのnumerical_gradient関数内で使用されている
「grads['W1'] = numerical_gradient(loss_W, self.params['W1'])」についてわからないことがあります。
common.numerical_gradient関数では引数に(f,x)(f・・関数,x・・重み'W1'など)を取っています。
common.numerical_gradient関数の「fxh1 = f(x)」で、self.params['W1']をf関数に入れていますが、このf関数は ラムダ式である「lamda W: self.loss(x, t)」であるため、self.params['W1']と引数に渡しても、self.params['W2']を引数に渡しても結果が変わらないだろうと思いました。
しかし、色々とデータを代入してみると、['W1']の場合と['W2']の場合で結果が異なってしまいました。どうして違う結果になるのでしょうか。
よろしくお願いいたします。
###補足情報(言語/FW/ツール等のバージョンなど)
使用環境:Mac OS High Sierra
使用ツール:Jupyter Notebook
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。