156 Views
June 23, 24
スライド概要
AI・機械学習を勉強したい学生たちが集まる、京都大学の自主ゼミサークルです。私たちのサークルに興味のある方はX(Twitter)をご覧ください!
2024年度前期輪読会#8「ゼロから作る Deep Learning」 5章 誤差逆伝播法 5.5~5.6 京都大学経済学部二回生 大澤衡正 0
誤差逆伝播法 目次 1. ReLUレイヤの逆伝播 2. Sigmoidレイヤの逆伝播 3. Affineレイヤの逆伝播 4. Softmax-with-Lossレイヤの逆伝播 5. まとめ 1
1. ReLUレイヤの逆伝播 2
1 . ReLUレイヤの逆伝播 計算グラフ ● ReLUの微分は 𝜕𝑥 = 1(x > 0) 𝜕𝑦 𝜕𝑥 = 0(x ≤ 0) 𝜕𝑦 よって、逆伝播時の入力xが0より大きければそれを そのまま流し、それ以外の場合は下流への信号はスト ップする。 3
2. ReLUレイヤの逆伝播 実装 class Relu: def __init__(self) -> None: # 準伝播時の入力値が0以下の要素をTrueとする配列 self.mask: npt.NDArray[np.bool] = np.zeros(0) def forward(self, x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: self.mask = x <= 0 out = x.copy() out[self.mask] = 0 return out def backward( self, dout: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: # 逆伝播時に0以下の要素を0にする dout[self.mask] = 0 dx = dout return dx 4
2. Sigmoidレイヤの逆伝播 5
2. Sigmoidレイヤの逆伝播 計算グラフ Sigmoid関数の計算グラフは上に示した通り これはさらに簡略化できて 𝜕𝐿 y(1 − y) 𝜕𝑦 よってSigmoid関数の逆伝播は順伝播の出力だけで書く ことができる 6
2. . Sigmoidレイヤの逆伝播 実装 class Sigmoid: def __init__(self) -> None: self.out: npt.NDArray[np.float64] = np.zeros(0) def forward(self, x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: out = 1.0 / (1.0 + np.exp(-x)) self.out = out return out def backward( self, dout: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: dx = dout * (1.0 - self.out) * self.out return dx 7
3. Affineレイヤの逆伝播 8
2. Affineレイヤの逆伝播 計算グラフ ←Affineレイヤの計算グラフ これまでの計算グラフではノー ドを流れるのはスカラ値だった が、今回は行列が流れる ※Nはbatchサイズを意味する 式1.2の導出は以下が参考になる 行列積の勾配を誤差逆伝播法により求める (zenn.dev) 9
2. Affineレイヤの逆伝播 実装 class Affine: def __init__( self, W: npt.NDArray[np.float64], b: npt.NDArray[np.float64] ) -> None: self.W: npt.NDArray[np.float64] = W self.b: npt.NDArray[np.float64] = b self.x: npt.NDArray[np.float64] = np.zeros(0) self.dW: npt.NDArray[np.float64] = np.zeros(0) self.db: npt.NDArray[np.float64] = np.zeros(0) def forward(self, x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: self.x = x out = np.dot(x, self.W) + self.b return out def backward( self, dout: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: dx = np.dot(dout, self.W.T) # x方向以外の微分も求める self.dW = np.dot(self.x.T, dout) self.db = np.sum(dout, axis=0) return dx 10
4. Softmax-with-Lossレイヤの逆伝播 11
2. Softmax-with-Lossレイヤの逆伝播 計算グラフ ● Softmax関数の損失関数として交差エント ロピー誤差を用いると逆伝播は (y1 − t1, y2 − t2, y3 − t3) という綺麗な値になる。これは偶然ではなく、 交差エントロピー誤差が望ましい性質を持つよ うに設計されているから また、単に綺麗なだけでなく、教師ラベルとNN の予測の差が出力されていることも重要 ※ここでは3クラス分類を行う場合を想定 12
2. Softmax-with-Lossレイヤの逆伝播 計算グラフの詳細 softmax関数の計算グラフ クロスエントロピー誤差 の計算グラフ 13
2. ReLUレイヤの逆伝播 実装 class SoftmaxWithLoss: def __init__(self) -> None: self.loss: float = 0.0 self.y: npt.NDArray[np.float64] = np.zeros(0) self.t: npt.NDArray[np.float64] = np.zeros(0) def forward( self, x: npt.NDArray[np.float64], t: npt.NDArray[np.float64] ) -> float: self.t = t self.y = softmax(x) self.loss = float(cross_entropy_error(self.y, self.t)) return self.loss def backward(self, dout: float = 1) -> npt.NDArray[np.float64]: batch_size = self.t.shape[0] # バッチサイズで割ることで、1サンプルあたりの誤差を求める dx = (self.y - self.t) / batch_size return dx 14
誤差逆伝播法 4.まとめ まとめ1 まとめ2 まとめ3 NNを構成するレイヤーを一つのノードとみなして誤差逆伝播を実装できる クロスエントロピー誤差はSoftmax関数と組み合わせたときに逆伝播の値 が正確にモデルの予測誤差を反映した簡潔な値となるように設計されている 各層の準伝播と逆伝播を一つのクラスとして実装することで、実際 のコーディングを簡潔に行うことができる 15
16