【动手学深度学习】视频课程笔记与重点总结 19-29,卷积神经网络大全

目录

上期回顾

卷积神经网络

从全连接到卷积

图像卷积

填充和步幅

多输入多输出通道

池化层

LeNet

现代卷积神经网络

深度卷积神经网络(AlexNet)

使用块的网络(VGG)

网络中的网络(NiN)

含并行连接的网络(GoogLeNet)

批量归一化(BN)

残差网络(ResNet)

密集连接网络(DenseNet)

下期预告


上期回顾

【李沐 动手学深度学习】视频课程笔记与重点总结 01-18-优快云博客icon-default.png?t=N7T8https://blog.youkuaiyun.com/qq_52589927/article/details/141156454?spm=1001.2014.3001.5502还是提醒一下,文章中代码仅作展示。使用的是pytorch框架,在运行代码的时候,不要忘了先导包

import torch
from torch import nn
from d2l import torch as d2l
from torch.nn import functional as F

卷积神经网络

相信大家对卷积都稍微有些了解,就是一个卷积核(权重矩阵)在图片上不断扫描求值,如下动图就是一个3*3的卷积核在5*5的图片上做卷积。

下面会从底层逻辑开始讲起,卷积是怎么出现的

从全连接到卷积

对全连接层(输入和输出为一维向量)使用如下两种性质就会变成卷积层(输入和输出为二维矩阵)

通俗来讲就是:

平移不变性

  • 确定卷积核的个数唯一
  • 要识别图片上的猫,不管猫在图片的哪个位置,只需要同一个卷积核(权重矩阵)来扫描即可,即卷积核的参数不变,从图中提取到的特征就不变

局限性

  • 确定卷积核的大小适当
  • 无需整张图一起看,只需要看某一个位置点附近的地方

通过改变卷积核中的参数,可以实现不同目的,如边缘检测,锐化,模糊........

也可以使用一维,三维的数据来做卷积。要注意,输入输出变化的同时,卷积核也会改变维度哦

一维:文本,语言,时序序列

三维:视频,医学图像

卷积的简单公式:

  • 输入 X 和 权重矩阵 W(卷积核)交叉相乘,再加上偏移 b,得到输出 Y
  • 可学习的参数:W 和 b
  • 超参数:W 的大小

图像卷积

实现二维卷积层

class Conv2D(nn.Module): # 继承nn.Module
    def __init__(self, kernel_size): # W 的大小
        super().__init__()
        self.weight = nn.Parameter(torch.rand(kernel_size)) # W 可学习参数
        self.bias = nn.Parameter(torch.zeros(1)) # b 可学习参数

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias # Y = X * W + b

学习卷积核

学习由 X输入 生成 Y输出 的卷积核,无需自己设计卷积核的参数,而是让网络来学习

# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)

# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2  # 学习率

# 手搓训练逻辑
for i in range(10):
    Y_hat = conv2d(X)
    l = (Y_hat - Y) ** 2 # 均方误差作为loss
    conv2d.zero_grad() # conv2d的梯度设为0
    l.sum().backward()
    # 迭代卷积核,梯度下降的方式
    conv2d.weight.data[:] -= lr * conv2d.weight.grad
    if (i + 1) % 2 == 0:
        print(f'epoch {i+1}, loss {l.sum():.3f}')

# 查看这个卷积核的权重tensor
conv2d.weight.data.reshape((1, 2))

填充和步幅

卷积的超参数:填充padding、步幅stride

先讲填充,假设如下情况:

形状减小到 ( 32 - 5 + 1 ) * ( 32 - 5 + 1 ),即第一层输出大小 28 * 28

如此往复,输出结果越来越小,为了防止这一现象的出现,可以采取如下措施:

在输入的周围添加额外的行列,这也就是为什么文章开头的动图中,蓝色方框外还有一圈虚线,那个就是额外添加的padding

如果添加 ph 行填充和 pw 列填充,则输出形状将为:

p:填充padding 、k:卷积核kernel 、n:输入

h:高 、 w:宽

这样选取的话,在经过不断卷积后,输出的形状不会发生变化,和输入时大小一样(Pw同理)

代码实现:

在所有侧边填充 1 个像素(填一圈)

# 为了方便起见,我们定义了一个计算卷积层的函数。
# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数
def comp_conv2d(conv2d, X):
    # 这里的(1,1)表示批量大小和通道数都是1
    X = X.reshape((1, 1) + X.shape)
    Y = conv2d(X)
    # 省略前两个维度:批量大小和通道
    return Y.reshape(Y.shape[2:])

# 请注意,这里每边都填充了1行或1列,因此总共添加了2行或2列,左边一行,右边一行
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1)
X = torch.rand(size=(8, 8)) # 输入为 8*8
comp_conv2d(conv2d, X).shape

放入之前的公式就是:

Ph=(3-1)=2,Pw=(3-1)=2,因为Kh为奇数,故在上下两侧都填充Ph/2=1行,即共填充2行

Pw同理,填充左右两侧。所以说,其实就是填充了一圈

填充不同的高度和宽度

conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3), padding=(2, 1))
comp_conv2d(conv2d, X).shape

接下来讲步幅,假设希望 输出的大小 比 输入小

那么就需要很多层的计算才能得到较小输出,为解决这一问题,采取如下措施:

高度3,宽度2 的步幅(行/列的滑动步长)

如果给定 高度Sh 和 宽度Sw 的步幅,则输出形状将为:

代码实现:

高度和宽度的步幅设置为 2

conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
comp_conv2d(conv2d, X).shape

此时输入为 8*8,输出为 4*4

多输入多输出通道

卷积的超参数:输出的通道数

例如,彩色图像都有RGB三个通道,红绿蓝,这时就是多输入

多个输入通道

每个通道都有一个独立的二维卷积核 (长宽) ,所有通道卷积结果相加 得到一个输出结果

多个输出通道

可以有多个3维卷积核 (长 宽 通道) ,每个核对应生成一个输出通道

此时,核变成4维,输出变成3维

其实这里也就是说,我们可以用不同的3维卷积核,实现不同的目标,对应不同的通道

多输出的特定:每个输出可以识别特定模式

多输入的特定:识别并组合

1 * 1卷积

作用:通道融合

输入通道为3,长宽为3,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值