NNDL 作业7:第五章课后题(1×1 卷积核 | CNN BP)

习题5-2 证明宽卷积具有交换性,即公式(5.13)

现有在这里插入图片描述
根据宽卷积定义在这里插入图片描述
为了让x的下标形式和w的进行对换,进行变量替换,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
已知在这里插入图片描述
因此对于在这里插入图片描述
由于宽卷积的条件,s和t的变动范围是可行的。

习题5-3 分析卷积神经网络中用1×1的卷积核的作用

1×1的卷积核在实际应用中类似于一根截面积为1个像素的正方形管道,用来贯穿整个输入特征。每个1×1的卷积核都试图提取基于相同像素位置的特征的融合表达。可以实现特征升维和降维的目的。并且增加了网络的非线性,提高拟合能力。

习题5-4 对于一个输入为100×100×256的特征映射组,使用3×3的卷积核,输出为100×100×256的特征映射组的卷积层,求其时间和空间复杂度。如果引入一个1×1的卷积核,先得到100×100×64的特征映射,再进行3×3的卷积,得到100×100×256的特征映射组,求其时间和空间复杂度。

时间复杂度:时间复杂度即模型的运行次数。
空间复杂度:空间复杂度即模型的参数数量。

时间复杂度一:256×100×100×256×3×3 = 5,898,240,000
空间复杂度一:256×100×100 = 2,560,000
时间复杂度二:64×100×100×256 + 256×100×100×64×3×3 = 1,638,400,000
空间复杂度二:64×100×100 + 256×100×100 = 3,200,000

习题5-7 忽略激活函数,分析卷积网络中卷积层的前向计算和反向传播是一种转置关系。

在这里插入图片描述

推导CNN反向传播

先回顾一下卷积运算:在卷积神经网络中,所谓的卷积运算,其实并不是严格的数学意义上的卷积。深度学习中的卷积实际上是信号处理和图像处理中的互相关运算,它们二者之间有细微的差别。深度学习中的卷积(严格来说是互相关)是卷积核在原始图像上遍历,对应元素相乘再求和,得到的新图像在尺寸上会有减小。可以通过下图直观的去理解。假设输入图像的有m行,n列,卷积核的尺寸为filter_size×filter_size,输出图像的尺寸即为(m-filter_size+1)×(n-filter_size+1)
在这里插入图片描述
在全连接神经网络,图像数据以及特征是以列向量的形式进行存储。而在卷积神经网络中,数据的格式主要是以张量(可以理解为多维数组)的形式存储。图片的格式为一个三维张量,行×列×通道数。卷积核的格式为一个四维张量,卷积核数×行×列×通道数。

卷积操作是每次取出卷积核中的一个,一个卷积核的格式为三维,为行×列×通道数。对应通道序号的图片与卷积核经过二维卷积操作后(即上图所示操作),得到该通道对应的卷积结果,将所有通道的结果相加,得到输出图像的一个通道。每个卷积核对应输出图像的一个通道,即输出图像的通道数等于卷积核的个数。

误差传播:
参数更新规则:梯度下降法,公式如下:
在这里插入图片描述
定义误差项δ,如下:
在这里插入图片描述
在这里插入图片描述
l代表卷积神经网络第l层, j、k表示其特征向量第j行,第k列。w表示权重,i对应下一层神经元特征向量个数,s代表上一层特征向量个数,m、n表示一个卷积核第(m,n)个的值,b为偏置,z为该层神经元输入,a为该层神经元输出。
由链式求导法则,得误差传播过程为:
在这里插入图片描述
得误差传递公式:在这里插入图片描述

设计简易CNN模型,分别用Numpy、Pytorch实现卷积层和池化层的反向传播算子,并代入数值测试.

import numpy as np
def padding(X, pad):
    X_pad = np.pad(X, (
        (0, 0),
        (pad, pad),
        (pad, pad),
        (0, 0)),
         mode='constant', constant_values=(0, 0))
    return X_pad
def conv_single_step(a_slice_prev, W, b):
    s = np.multiply(a_slice_prev, W)
    Z = np.sum(s)
    Z = Z + float(b)
    return Z
def conv_forward(A_prev, W, b, hparameters):
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
    (f, f, n_C_prev, n_C) = W.shape
    stride = hparameters['stride']
    pad = hparameters['pad']
    n_H = int((n_H_prev + 2 * pad - f) / stride) + 1
    n_W = int((n_W_prev + 2 * pad - f) / stride) + 1
    Z = np.zeros((m, n_H, n_W, n_C))
    A_prev_pad = padding(A_prev, pad)
 
    for i in range(m):  # 依次遍历每个样本
        a_prev_pad = A_prev_pad[i]  # 获取当前样本
        for h in range(n_H):  # 在输出结果的垂直方向上循环
            for w in range(n_W):  # 在输出结果的水平方向上循环
                # 确定分片边界
                vert_start = h * stride
                vert_end = vert_start + f
                horiz_start = w * stride
                horiz_end = horiz_start + f
 
                for c in range(n_C):
                    a_slice_prev = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]
                    weights = W[:, :, :, c]
                    biases = b[:, :, :, c]
                    Z[i, h, w, c] = conv_single_step(a_slice_prev, weights, biases)
 
    assert (Z.shape == (m, n_H, n_W, n_C))
    mask = (A_prev, W, b, hparameters)
 
    return Z, mask
 
def backward(theta, mask):
    (A_prev, W, b, hparameters) = mask
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
    (f, f, n_C_prev,
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值