IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 《动手学深度学习》--- ResNet实现 -> 正文阅读

[人工智能]《动手学深度学习》--- ResNet实现

参考沐神

7.6. 残差网络(ResNet) — 动手学深度学习 2.0.0-beta0 documentationhttps://zh-v2.d2l.ai/chapter_convolutional-modern/resnet.html

ResNet结构

????????这次就浅记一下,不深入讲解了。

?????????创新点是引入残差块,残差块有很好的性质。先看下面内容再展开残差块。

????????简单说一下上图,对于输入X和标签y,我们希望学习一个好的函数F来尽可能正确预测给定输入X对应的y。可能我们最开始的函数为F1,效果狠辣鸡。我们一顿操作改成F2,效果也不好,又改了好几次,变成了F6,可能效果反而更差了,在上图左半边我们可以很清楚的看到,F1模型的规模很小,但其实它比复杂的F6离最优点f'更接近。上面说的这种调整策略就是非嵌套函数类的调整,显然通过这种非嵌套函数类调整策略并不合适。

? ? ? ? 所以有大聪明提出了右边的嵌套函数类,它可以使我们在原来简单模型F1基础上不偏移的一点点向外扩张变复杂。在上图右边可以明显看出这种策略稳定性更高,可以很好的稳定的逼近最优点。

? ? ? ? 实现嵌套函数类的方式就是使用残差块!来浅看一下残差块和原来的普通块的区别吧~

?????????ResNet残差块有两种形式,具体用哪种形式根据use_1x1conv设置。use_1x1conv的作用就是调整通道数,因为1x1的卷积核不改变输入张量的形状,所以我们多搞几个1x1的卷积核就可以控制输出通道。

代码实现

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :深度学习入门
@File :ResNet.py
@Author :little_spice
@Date :2022/5/8 21:19
"""
import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l

# 定义残差块
"""
    残差块??先有2个有相同输出通道数的3 × 3卷积层。每个卷积
    层后接?个批量规范化层和ReLU激活函数。然后我们通过跨层数据通路,跳过这2个卷积运算,将输?直接
    加在最后的ReLU激活函数前。这样的设计要求2个卷积层的输出与输?形状?样,从?使它们可以相加。如
    果想改变通道数,就需要引??个额外的1 × 1卷积层来将输?变换成需要的形状后再做相加运算。
"""
class Residual(nn.Module):
    # 构造函数
    def __init__(self,input_channels,num_channels,use_1x1conv=False,strides=1):
        # 调用父类也就是nn.Moudle的构造函数
        super().__init__()
        self.conv1 = nn.Conv2d(input_channels,num_channels,kernel_size=3,padding=1,stride=strides)
        self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1)

        if use_1x1conv:
            self.conv3 = nn.Conv2d(input_channels,num_channels,kernel_size=1,stride=strides)
        else:
            self.conv3 = None
        self.bn1 = nn.BatchNorm2d(num_channels)
        self.bn2 = nn.BatchNorm2d(num_channels)

    # 前向传播过程
    def forward(self,X):
        # F.relu()一般在forward中用,nn.ReLU()在定义网络结构的时候用。前者是函数调用,后者是模块调用。
        Y = F.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        Y += X
        return F.relu(Y)

# 不使用1x1卷积层
blk = Residual(3,3)
X = torch.rand(4,3,6,6)
Y = blk(X)
# print(Y)

# 使用1x1卷积层,同时可以在增加输出通道数的同时,减半输出的?和宽。
blk = Residual(3,6,use_1x1conv=True,strides=2)
# print(blk(X).shape)

# 定义ResNet模型
b1 = nn.Sequential(nn.Conv2d(1,64,kernel_size=7,stride=2,padding=3),
                   nn.BatchNorm2d(64),nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3,stride=2,padding=1))

"""
    定义ResNet的模块
    ResNet使?4个由残差块组成的模块,每个模块使?若?个同样输出通道数的残差块。第?个模块的通道数同输?通道数?致。
    由于之前已经使?了步幅为2的最?汇聚层,所以?须减??和宽。之后的每个模块在第?个残差块?将上?个模块的通道数翻倍,
    并将?和宽减半。
    对一个模块做了特殊处理。
"""
def resnet_block(input_channels,num_channels,num_residuals,first_block=False):
    blk = []
    for i in range(num_residuals):
        if i==0 and not first_block:
            blk.append(Residual(input_channels,num_channels,use_1x1conv=True,strides=2))
        else:
            blk.append(Residual(num_channels,num_channels))
    return blk

# 接着在ResNet加?所有残差块,这?每个模块使?2个残差块。
b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))

# 最后,与GoogLeNet?样,在ResNet中加?全局平均汇聚层,以及全连接层输出。
net = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1,1)),nn.Flatten(), nn.Linear(512, 10))

"""
在训练ResNet之前,让我们观察?下ResNet中不同模块的输?形状是如何变化的。在之前所有架构中,分辨
率降低,通道数量增加,直到全局平均汇聚层聚集所有特征。
"""
X = torch.rand(size=(1,1,224,224))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape:\t', X.shape)

# 在Fashion-MNIST数据集上训练模型
lr, num_epochs, batch_size = 0.05, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

?结果我就不展示了,感觉一跑我电脑巨卡,gtx1050确实顶不住了QAQ!

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:27:02  更:2022-05-11 16:29:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:52:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码