卷积神经网络 前向传播 反向传播 计算公式
时间: 2024-12-30 13:28:24 浏览: 20
### 卷积神经网络(CNN)前向传播与反向传播详细计算公式
#### 前向传播公式
对于卷积层,在输入图像 \(X\) 和滤波器(或称为权重矩阵)\(W\) 的情况下,输出特征图 \(Y\) 可通过如下方式获得:
\[ Y(i, j)=\sigma \left( b+\sum_{k=0}^{K-1}\sum_{l=0}^{L-1} X(i+k,j+l)\cdot W(k,l) \right)[^2] \]
这里,
- \(i\) 和 \(j\) 是输出特征图的位置坐标;
- \(b\) 表示偏置项;
- \(K\) 和 \(L\) 分别代表滤波器的高度和宽度;
- \(\sigma\) 为激活函数。
当涉及多通道数据时,则需考虑多个这样的操作并最终叠加起来形成单个输出单元的结果。设输入有 \(C_i\) 个通道而输出有 \(C_o\) 个通道,则上述表达变为:
\[ Y(c_o,i,j)=\sigma \left(b_{c_o} + \sum_{c_i=0}^{C_i-1}\sum_{k=0}^{K-1}\sum_{l=0}^{L-1} X(c_i,i+k,j+l)\cdot W(c_o,c_i,k,l)\right) \]
其中下标 \(c_o\) 指定当前处理的是哪一个输出通道上的位置 (i,j),即第几个过滤器产生的响应;同样地,\(c_i\) 则遍历所有可能的输入通道组合来完成一次完整的卷积运算。
#### 反向传播公式
在反向传播过程中,目标是从损失函数出发逐步调整模型中的各个参数以最小化预测误差。具体来说,
##### 对于卷积层而言:
假设已知某一层输出相对于总成本的变化率 \(\frac{\partial L}{\partial y}\),则该层对应的权值更新规则可表示为:
\[ \Delta w=\eta \times (\text{input feature map}) * (\delta \text{ of output feature map})[^5] \]
这里的星号(*)表示互相关而非标准意义上的卷积操作——即将原始输入作为固定模板滑动匹配由链式法则传递下来的梯度信号δ,并取其内积得到相应维度下的累积贡献量Δw用于后续修正原有参数设置。
更精确地说,针对每个单独的权重系数 \(W(c_o,c_i,h,w)\),其梯度估计应满足下面的关系:
\[ \frac{\partial E}{\partial W(c_o,c_i,h,w)} = \sum_{m,n} \delta(m,n) \times I(c_i,m+h,n+w) \]
此处 \(I(c_i,\cdots)\) 记作特定输入通道内的局部区域采样值序列;同时注意到求和符号覆盖了整个感受野范围内的有效配对情况。
另外值得注意的一点是在实际应用当中为了提高效率通常会采用批量处理机制(Batch Processing),此时上面提到的各种变量都将扩展成三维张量形式以便一次性完成更大规模的数据交换任务。
```python
import numpy as np
def conv_backward(dZ, cache):
"""
实现卷积层的反向传播
参数:
dZ -- 成本关于线性输出 Z 的梯度.
形状为(n_H_prev, n_W_prev, n_C_prev).
cache -- 来自conv_forward()的一个Python字典,
包含"A_prev", "W", "b", "hparameters".
返回:
dA_prev -- 关于 A_prev 的成本梯度,
形状同 A_prev.
dW -- 关于 W 的成本梯度,
形状同 W.
db -- 关于 b 的成本梯度,
形状同 b.
"""
# 获取缓存信息
(A_prev, W, b, hparameters) = cache
# 提取形状参数
(m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
(f, f, n_C_prev, n_C) = W.shape
# 初始化输出梯度
dA_prev = np.zeros_like(A_prev)
dW = np.zeros_like(W)
db = np.zeros((1, 1, 1, n_C))
# 遍历批次样本
for i in range(m):
a_slice_prev = A_prev[i,:,:,:]
for c in range(n_C): # 迭代输出通道
for h in range(n_H_prev): # 迭代高度方向索引
for w in range(n_W_prev): # 迭代宽度方向索引
vert_start = ...
horiz_start = ...
slice_a = ... # 定义切片窗口
da = ... # 更新dA_prev
dw = ... # 积累dW
db[:,:,:,c] += ...# 累加db
return dA_prev, dW, db
```
阅读全文