资料下载
链接:https://pan.baidu.com/s/1mTqblxzWcYIRF7_kk8MQQA
提取码:7x6w
资料的下载真的很感谢(14条消息) 【中文】【吴恩达课后编程作业】Course 4 - 卷积神经网络 - 第二周作业_何宽的博客-CSDN博客
【博主使用的python版本:3.6.8】
对于此作业,您将使用 Keras。
在进入问题之前,请运行下面的单元格以加载所需的包。
import tensorflow as tf import numpy as np import scipy.misc from tensorflow.keras.applications.resnet_v2 import ResNet50V2 from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.resnet_v2 import preprocess_input, decode_predictions from tensorflow.keras import layers from tensorflow.keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D from tensorflow.keras.models import Model, load_model from resnets_utils import * from tensorflow.keras.initializers import random_uniform, glorot_uniform, constant, identity from tensorflow.python.framework.ops import EagerTensor from matplotlib.pyplot import imshow from test_utils import summary, comparator import public_tests
- 非常深的神经网络的问题
- 非常深度网络的主要好处是它可以表示非常复杂的功能。它还可以学习许多不同抽象级别的特征,从边缘(在较浅的层,更接近输入)到非常复杂的特征(在更深的层,更接近输出)。
- 但是,使用更深的网络并不总是有帮助。训练梯度的一个巨大障碍是梯度消失:非常深的网络通常有一个梯度信号,很快就会归零,从而使梯度下降变得非常慢。
- 更具体地说,在梯度下降期间,当您从最后一层反向传播回第一层时,您将乘以每一步的权重矩阵,因此梯度可以呈指数级迅速减小到零(或者在极少数情况下,指数级快速增长并“爆炸”,因为获得非常大的值)。
- 因此,在训练过程中,您可能会看到随着训练的进行,较浅层的梯度的大小(或范数)会非常迅速地减小到零,如下所示:
构建一个残差网络
- 左图显示了通过网络的“主要路径”。右侧的图像将快捷方式添加到主路径。通过将这些 ResNet 块堆叠在一起,您可以形成一个非常深的网络。
- 讲座提到,使用带有快捷方式的 ResNet 块也使其中一个块学习恒等函数变得非常容易。这意味着您可以堆叠额外的 ResNet 块,而几乎没有损害训练集性能的风险。
- 在这一点上,还有一些证据表明,学习恒等函数的便利性解释了ResNets的卓越性能,甚至超过了跳过连接对梯度消失的帮助。
- ResNet 中使用两种主要类型的块,主要取决于输入/输出尺寸是相同还是不同。您将实现它们:“标识块”和“卷积块”。
恒等块(Identity block)
恒等块是 ResNet 中使用的标准块,对应于输入激活(例如a[L])与输出激活(例如a[L+!])具有相同维度的情况。为了充实 ResNet 身份块中发生的不同步骤,下面是一个显示各个步骤的替代图表:
上面的路径是“捷径”。较低的路径是“主要路径”。在此图中,请注意每层中的 CONV2D 和 ReLU 步骤。为了加快训练速度,添加了 BatchNorm 步骤。不要担心这很难实现 - 你会看到BatchNorm只是Keras中的一行代码!
在本练习中,您将实际实现此标识块的一个功能稍微强大的版本,其中跳过连接“跳过”3 个隐藏层而不是 2 个层。它看起来像这样:
主路径的第一部分:
- 第一个 CONV2D 具有F1形状为 (1,1) 和步幅为 (1,1) 的过滤器。它的填充是“有效的”。使用 0 作为随机统一初始化的种子:
kernel_initializer = initializer(seed=0)
. - 第一个 BatchNorm 是规范化“channel”轴。
- 然后应用 ReLU 激活函数。这没有超参数。
主路径的第二部分:
- 第二个 CONV2D 具有F2形状(f,f)和步幅为 (1,1) 的过滤器。它的填充是“相同的”。使用 0 作为随机统一初始化的种子:kernel_initializer = initializer(seed=0)
- 第二个 BatchNorm 是规范化“channel”轴。
- 然后应用 ReLU 激活函数。这没有超参数。
主路径的第三部分:
- 第三个 CONV2D 具有F3形状 (1,1) 和步幅为 (1,1) 的过滤器。它的填充是“相同的”。使用 0 作为随机统一初始化的种子:kernel_initializer = initializer(seed=0)
- 第三个 BatchNorm 是规范化“channel”轴。
- 然后应用 ReLU 激活函数。这没有超参数。
主路径的最后一部分:
- 第 3 层 X 的X_shortcut和输出相加。
- 提示:语法看起来像 Add()([var1,var2])
- 然后应用 ReLU 激活函数。这没有超参数。
接下来我们就要实现残差网络的恒等块了
我们已将初始值设定项参数添加到函数中。此参数接收一个初始值设定项函数,类似于包 tensorflow.keras.initializers 或任何其他自定义初始值设定项中包含的函数。默认情况下,它将设置为random_uniform
请记住,这些函数接受种子参数,该参数可以是所需的任何值,但在此笔记本中必须将其设置为 0 才能进行评分。
下面是实际使用函数式 API 的强大功能来创建快捷方式路径的地方:
def identity_block(X, f, filters, training=True, initializer=random_uniform): """ 实现图 4 中定义的恒等块 Arguments: X -- 形状的输入张量(m、n_H_prev、n_W_prev、n_C_prev) f -- 整数,指定主路径中间 CONV 窗口的形状 filters -- python 整数列表,定义主路径的 CONV 层中的过滤器数量 训练 -- True:在训练模式下行为 错误:在推理模式下行为 初始值设定项 -- 设置图层的初始权重。等于随机统一初始值设定项 Returns: X -- output of the identity block, tensor of shape (n_H, n_W, n_C) """ # Retrieve Filters F1, F2, F3 = filters # Save the input value. You'll need this later to add back to the main path. X_shortcut = X cache = [] # 主路径的第一个组成部分 X = Conv2D(filters = F1, kernel_size = 1, strides = (1,1), padding = 'valid', kernel_initializer = initializer(seed=0))(X) X = BatchNormalization(axis = 3)(X, training = training) # Default axis X = Activation('relu')(X) ### START CODE HERE ## Second component of main path (≈3 lines) X = Conv2D(filters = F2, kernel_size = f,strides = (1, 1),padding='same',kernel_initializer = initializer(seed=0))(X) X = BatchNormalization(axis = 3)(X, training=training) X = Activation('relu')(X) ## Third component of main path (≈2 lines) X = Conv2D(filters = F3, kernel_size = 1, strides = (1, 1), padding='valid', kernel_initializer = initializer(seed=0))(X) X = BatchNormalization(axis = 3)(X, training=training) ## Final step: Add shortcut value to main path, and pass it through a RELU activation (≈2 lines) X = Add()([X_shortcut,X]) X = Activation('relu')(X) ### END CODE HERE return X
我们来测试一下:
np.random.seed(1) X1 = np.ones((1, 4, 4, 3)) * -1 X2 = np.ones((1, 4, 4, 3)) * 1 X3 = np.ones((1, 4, 4, 3)) * 3 #按着X1,X2,X3的顺序排序 X = np.concatenate((X1, X2, X3), axis = 0).astype(np.float32) A3 = identity_block(X, f=2, filters=[4, 4, 3], initializer=lambda seed=0:constant(value=1), training=False) print('