373 Views
June 23, 24
スライド概要
AI・機械学習を勉強したい学生たちが集まる、京都大学の自主ゼミサークルです。私たちのサークルに興味のある方はX(Twitter)をご覧ください!
2024 前期輪読会 # 8 ゼロから作るDeep Learning 5.7~5.8 工学部 4回生 河田賢斗 0
5.7.1 ニューラルネットワークの学習の全体図 [前提] ニューラルネットワーク(以下NN)は、適応可能な重みとバイアス を有する。訓練データに適応するように調整すること = 「学習」 [学習の手順] Step1(ミニバッチ) : 訓練データの中からランダムに一部のデータを抽出 Step2(勾配の算出) : 各重みパラメータに関する損失関数の勾配を算出 Step3(パラメータの更新) : 重みパラメータを勾配方向に微小量だけ更新 Step4(繰り返し) : Step1 ~Step3を繰り返す 1
5.7.2 誤差逆伝播法に対応したNNの実装 ポイント : レイヤを使用することでpredict()やgradient()の処理がレイヤ の伝播だけで達成可能 2層 NN の場合 → class TwoLayerNet を参考にレイヤを追加 # レイヤの生成 self.layers = OrderedDict() self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1']) self.layers['Relu1'] = Relu() self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2']) self.lastLayer = SoftmaxWithLoss() →次のページへ続く 2
5.7.2 誤差逆伝播法に対応したNNの実装 self.layers = OrderDict()として、NNのレイヤを保存する(順番つきのdictionary) →ディクショナリに追加した要素の順番を記憶可能 順伝播では、追加した順にレイヤのforward()メソッドを呼び出せばよい 逆伝播では、逆の順番でレイヤを呼び出せばよい ここでは、Affine1、Relu1、Affine2、SoftmaxwithLossレイヤが各々の内部で順 伝播・逆伝播を正しく処理してくれるため、これらのレイヤを正しい順番で連結し、 順番にレイヤを呼び出せばよい def predict(self, x): for layer in self.layers.values(): 認識(推論)を行う。 順伝播によって出力xを得る。 x = layer.forward(x) return x 3
5.7.2 誤差逆伝播法に対応したNNの実装 def gradient(self, x, t): # forward 順伝播によって損失関 数の値を求める self.loss(x, t) # backward dout = 1 ! dout = self.lastLayer.backward(dout) 初期値を1と設定し、逆伝播 によって差分誤差を求める layers = list(self.layers.values()) layers.reverse() ! reverseメソッドの定義 for layer in layers: dout = layer.backward(dout) 上で求まったdout(差分誤差)が前レイに伝わる。 すなわち、AffineレイヤやReluレイヤにて逆伝播さ れる。Backwardに記載の事柄が実行される。 4
5.7.2 誤差逆伝播法に対応したNNの実装 ・上でみたコードは、誤差逆伝播法にて用いられるものである ・その他は、2層の NN を実現するためのコード ( class TwoLayerNet に記載のコード)を利用している NN の構成要素をレイヤとして実装したことで、NN を簡単に構築 することが出来る →各レイヤ内で実装された順伝播・逆伝播によって学習に必要な勾 配が求まる 5
勾配を算出する2つの手法 数値微分 解析的手法 欠点) ・計算に時間を要する 利点) ・実装が容易→ミスが少ない 欠点) 微小な差分により、微分を求 める ・計算が高速かつ効率的 ex.) def numerical_diff(f, x) : h = 1e-4 return (f(x + h) – f(x-h)) /(2*h) ・実装がやや複雑→ミスが多い 利点) 数式から解析的に微分を求めるため、 誤差が含まれない「真の微分」 誤差逆伝播法で使用される 数値微分の結果と誤差伝播法の結 果を比較して、誤差伝播法の実装 の正しさを実証する→「勾配確認」 6
5.7.3 誤差逆伝播法の勾配確認 以下に、勾配確認の実装を示す # coding: utf-8 import sys, os sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定 import numpy as np from dataset.mnist import load_mnist from two_layer_net import TwoLayerNet # データの読み込み (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) 7
5.7.3 誤差逆伝播法の勾配確認 network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) x_batch = x_train[:3] t_batch = t_train[:3] grad_numerical = network.numerical_gradient(x_batch, t_batch) grad_backprop = network.gradient(x_batch, t_batch) for key in grad_numerical.keys(): diff = np.average( np.abs(grad_backprop[key] - grad_numerical[key]) ) print(key + ":" + str(diff)) 参照 : https://github.com/oreilly-japan/deep-learning-fromscratch/blob/master/ch05/gradient_check.py 8
5.7.3 誤差逆伝播法の勾配確認 データの読み込みでは、MNISTデータセットを読み込む X_batch、t_batchを定義し、訓練データの一部を抽出する grad_numerical(数値微分の値)及びgrad_backprop(逆誤差伝 播法での微分の値)を定義し、誤差を確認する (各重みパラメータにおいて差の絶対値を求め、平均を算出) 算出した値が0になることは稀であるが、十分に小さな値をとる とき(1.0*e-12など)、誤差逆伝播法の実装に誤りが無いことの 信憑性が増す 9
5.7.4 誤差逆伝播法を使った学習 以下に、誤差逆伝播法を用いた NN の学習の実装を示す # coding: utf-8 import sys, os sys.path.append(os.pardir) import numpy as np from dataset.mnist import load_mnist from two_layer_net import TwoLayerNet # データの読み込み (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) 10
5.7.4 誤差逆伝播法を使った学習 network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) iters_num = 10000 train_size = x_train.shape[0] batch_size = 100 learning_rate = 0.1 train_loss_list = [] train_acc_list = [] test_acc_list = [] iter_per_epoch = max(train_size / batch_size, 1) 11
5.7.4 誤差逆伝播法を使った学習 for i in range(iters_num): batch_mask = np.random.choice(train_size, batch_size) x_batch = x_train[batch_mask] t_batch = t_train[batch_mask] # 勾配 #grad = network.numerical_gradient(x_batch, t_batch) grad = network.gradient(x_batch, t_batch) ! 誤差逆伝播法によって勾配を求める # 更新 for key in ('W1', 'b1', 'W2', 'b2'): network.params[key] -= learning_rate * grad[key] 12
5.7.4 誤差逆伝播法を使った学習 loss = network.loss(x_batch, t_batch) train_loss_list.append(loss) if i % iter_per_epoch == 0: train_acc = network.accuracy(x_train, t_train) test_acc = network.accuracy(x_test, t_test) train_acc_list.append(train_acc) test_acc_list.append(test_acc) print(train_acc, test_acc) 参照 : https://github.com/oreilly-japan/deep-learning-fromscratch/blob/master/ch05/train_neuralnet.py 13
5.8 まとめ 本章では、視覚的に計算過程を表す計算グラフを学んだ 計算グラフを描く 局所的な微分(NNでの誤差逆伝播法) NNの処理をレイヤで実装する→ Softmaxレイヤ、Affineレイヤ、Softmax-with-Lossレイヤ ReLUレイヤ 各レイヤには、backward・forwardのメソッドが実装されており、 データを逆方向・順方向に伝播させることが出来る 重みパラメータの勾配を効率的に求めることが可能 さらに、レイヤの重ね合わせで任意のNNを構築することも可能 14
15
16
17