使用numpy搭建卷积神经网络
主要内容来自DeepLearning.AI的卷积神经网络
本文使用numpy实现卷积层和池化层,包括前向传播和反向传播过程。
在具体描述之前,先对使用符号做定义。
- 上标[I]表示神经网络的第Ith层。
- a [ 4 ] a^{[4]} a[4]表示第4层神经网络的激活值; W [ 5 ] W^{[5]} W[5]和 b [ 5 ] b^{[5]} b[5]表示神经网络第5层的参数;
- 上标(i)表示第i个数据样本
- x ( i ) x^{(i)} x(i)表示第i个输入样本
- 下标i表示向量的第i个元素
- a i [ l ] a_i^{[l]} ai[l]表示神经网络第l层的激活向量的第i个元素。
- n H , n W , n C n_H,n_W,n_C nH,nW,nC表示当前层神经网络的高度、宽度和通道数。
- n H p r e v , n W p r e v , n C p r e v n_{H_{prev}},n_{W_{prev}},n_{C_{prev}} nHprev,nWprev,nCprev表示上一层神经网络的高度、宽度和通道数。
1. 导入包
首先,导入需要使用的工具包。
import numpy as np
import h5py
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (5.0, 4.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
%load_ext autoreload
%autoreload 2
np.random.seed(1) # 指定随机数种子
2. 大纲
本文要实现的卷积神经网络的几个网络块,每个网络包含的功能模块如下。
-
卷积函数Convolution
- 0填充边界
- 卷积窗口
- 卷积运算前向传播
- 卷积运算反向传播
-
池化函数Pooling
- 池化函数前向传播
- 掩码创建
- 值分配
- 池化的反向传播
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WdueA44q-1589298710418)(https://dijvuftadtswhbvbrhckte.coursera-apps.org/notebooks/week1/images/model.png)]
在每个前向传播的函数中,在参数更新时会有一个反向传播过程;此外,在前向传播过程会缓存一个参数,用于在反向传播过程中计算梯度。
3. 卷积神经网络
尽管当下存在很多深度学习框架使得卷积网络使用更为便捷,但是卷积网络在深度学习中仍然是一个难以理解的运算。卷积层能将输入转换为具有不同维度的输出,如下图所示。
接下来,我们自己实现卷积运算。首先,实现两个辅助函数:0填充边界和计算卷积。
3.1 0值边界填充
0值边界填充顾名思义,使用0填充在图片的边界周围。
使用边界填充的优点:
- 可以保证使用上一层的输出结果经过卷积运算后,其高度和宽度不会发生变化。这个特性对于构建深层网络非常重要,否则随着网络深度的增加,计算结果会逐步缩水,直至降为1。一种特殊的的“Same”卷积,可以保证计算结果的宽度和高度不发生变化
- 可以在图像边界保留更多的信息。不适用填充的情况下,图像的边缘像素对下一层结果的影响小(图像的中间像素使用滑动窗口时会遍历多次,而边界元素则比较少,有可能只使用1次)。
# GRADED FUNCTION: zero_pad
def zero_pad(X, pad):
"""
把数据集X的图像边界用0值填充。填充情况发生在每张图像的宽度和高度上。
参数:
X -- 图像数据集 (m, n_H, n_W, n_C),分别表示样本数、图像高度、图像宽度、通道数
pad -- 整数,每个图像在垂直和水平方向上的填充量
返回:
X_pad -- 填充后的图像数据集 (m, n_H + 2*pad, n_W + 2*pad, n_C)
"""
# X数据集有4个维度,填充发生在第2个维度和第三个维度上;填充方式为0值填充
X_pad = np.pad(X, (
(0, 0),# 样本数维度,不填充
(pad, pad), #n_H维度,上下各填充pad个像素
(pad, pad), #n_W维度,上下各填充pad个像素
(0, 0))