# 6.2.3 卷積層和池化層的反向求導及程式實現 ## 1. 卷積層的反向求導 下面以一維卷積來說明 設$x = (x_0, x_1, \cdot\cdot\cdot, x_{n-1})$,$w = (w_0, w_1, \cdot\cdot\cdot, w_{k-1})$,$b$ 為偏置,卷積結果為$z = x\cdot w + b = (z_0, z_1, \cdot\cdot\cdot, z_{n-k})$ 。如果已知某個損失函數關於 $z$ 的梯度$dz = \frac{\partial{L}}{\partial{z}} = (dz_0, \cdot\cdot\cdot, dz_{n-k})$,那根據連鎖律求解該損失函數關於 $w$ 的梯度,如下: \begin{aligned} dw &= \frac{\partial{L}}{\partial{w}} \\&= (\frac{\partial{L}}{\partial{w_0}}, \frac{\partial{L}}{\partial{w_1}}, \cdot\cdot\cdot, \frac{\partial{L}}{\partial{w_{k-1}}}) \\&= (\sum_i \frac{\partial{L}}{\partial{z_i}} \frac{\partial{z_i}}{\partial{w_0}}, \cdot\cdot\cdot, \sum_i \frac{\partial{L}}{\partial{z _i}} \frac{\partial{z_i}}{\partial{w_j}}, \cdot\cdot\cdot, \sum_i \frac{\partial{L}}{\partial{z_i}} \frac{\partial{z_i}}{\partial{w_{k-1}}}) \\&= \sum_i \frac{\partial{L}}{\partial{z_i}}(\frac{\partial{z_i}}{\partial{w_0}}, \cdot\cdot\cdot, \frac{\partial{z_i}}{\partial{w_j}}, \cdot\cdot\cdot, \frac{\partial{z_i}}{\partial{w_{k-1}}}) \\&= \sum_i \frac{\partial{L}}{\partial{z_i}} \frac{\partial{z_i}}{\partial{w}} \end{aligned} \begin{equation} \because z_i = x_iw_0 + x_{i+1}w_1 + \cdot\cdot\cdot + x_{i+k-1}w_{k-1} \\ \therefore \frac{\partial{z_i}}{\partial{w}} = (x_i, x_{i+1}, \cdot\cdot\cdot, x_{i+k-1}) \\ \therefore dw = \frac{\partial{L}}{\partial{w}} = \sum_i \frac{\partial{L}}{\partial{z_i}} \frac{\partial{z_i}}{\partial{w}} = \sum_i \frac{\partial{L}}{\partial{z_i}}(x_i, x_{i+1}, \cdot\cdot\cdot, x_{i+k-1}) \end{equation} ![](https://hackmd.io/_uploads/r1hG8gubp.jpg) ![](https://hackmd.io/_uploads/SkmESeuZa.jpg) 求$L$關於輸出$x$的梯度 $dx = \frac{\partial{L}}{\partial{x}}$ \begin{equation} \because z_i 只和 x_i, x_{i+1}, \cdot\cdot\cdot, x_{i+k-1}有關\\ \therefore \frac{\partial{z_i}}{\partial{x_j}} = 0 \quad (j \not = i,\cdot\cdot\cdot, i+k-1) \end{equation} \begin{aligned} \frac{\partial{z_i}}{\partial{x}} &= (\frac{\partial{z_i}}{\partial{x_{0}}}, \cdot\cdot\cdot, \frac{\partial{z_i}}{\partial{x_{i-1}}}, \frac{\partial{z_i}}{\partial{x_i}}, \cdot\cdot\cdot, \frac{\partial{z_i}}{\partial{x_{i+k-1}}}, \frac{\partial{z_i}}{\partial{x_{i+k}}}, \cdot\cdot\cdot)\\ &= (0, \cdot\cdot\cdot, 0, \frac{\partial{z_i}}{\partial{x_j}}, \cdot\cdot\cdot, \frac{\partial{z_i}}{\partial{x_{i+k-1}}}, 0, \cdot\cdot\cdot) \\&= (0, \cdot\cdot\cdot, w_0, \cdot\cdot\cdot, w_{k-1}, 0, \cdot\cdot\cdot) \end{aligned} 根據連鎖律得 \begin{equation} \frac{\partial{L}}{\partial{x}} = \sum^{n-k+1}_{i=1} \frac{\partial{L}}{\partial{z_i}} \frac{\partial{z_i}}{\partial{x}} = \sum^{n-k+1}_{i=1} \frac{\partial{L}}{\partial{z_i}}(0, \cdot\cdot\cdot, w_0, w_1, \cdot\cdot\cdot, w_{k-1}, \cdot\cdot\cdot, 0) \end{equation} ```python= # 對一維資料的反向求導 import numpy as np def conv_backward(dz, x, w, p = 0, s = 1): n, k = len(x), len(w) o_n = 1 + (n + 2 * p - k) // s assert(o_n == len(dz)) dx = np.zeros_like(x) dw = np.zeros_like(w) db = dz[:].sum() x_pad = np.pad(x, [(pad, pad)], 'constant') dx_pad = np.zeros_like(x_pad) for i in range(o_n): start = i * s dw += x_pad[start: start+k] * dz[i] dx_pad[start: start+k] += w * dz[i] dx = dx[pad: -pad] return dx, dw, db np.random.seed(231) x = np.random.randn(5) w = np.random.randn(3) stride = 2 pad = 1 dz = np.random.randn(5) print(dz) dx, dw, db = conv_backward(dz, x, w, 1) print(dx) print(dw) print(db) ``` ![](https://hackmd.io/_uploads/SkGDXzuW6.jpg) ![](https://hackmd.io/_uploads/S12P7GOWa.jpg) ![](https://hackmd.io/_uploads/HkS_mz_bp.jpg) ![](https://hackmd.io/_uploads/Sk3OXMdW6.jpg) ![](https://hackmd.io/_uploads/SkitmG_ZT.jpg) ![](https://hackmd.io/_uploads/HyQY7G_W6.jpg) ![](https://hackmd.io/_uploads/Hyl5XfubT.jpg) 問題:沒有問題