# 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}


求$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)
```







問題:沒有問題