pytorch深度学习基础(十一)——常用结构化CNN模型构建

news/2024/11/16 20:41:57/

结构化CNN模型构建与测试

  • 前言
  • GoogLeNet
    • 结构
    • Inception块
    • 模型构建
  • resNet18
    • 模型结构
    • 残差块
    • 模型构建
  • denseNet
    • 模型结构
    • DenseBlock
    • transition_block
    • 模型构建
  • 结尾

前言

在本专栏的上一篇博客中我们介绍了常用的线性模型,在本文中我们将介绍GoogleNet、resNet、denseNet这类结构化的模型的构建方式。

GoogLeNet

结构

整体的结构似乎有些吓人,但其实他也是用了块的思维,仔细观察可以发现,他中间一段很多层的结构都是相似的
在这里插入图片描述

Inception块

这个块就是其中重复的块,这个块分成了四个分支:1x1卷积、1x1卷积+3x3卷积、1x1卷积+5x5卷积、3x3卷积+1x1卷积,最后将这四个分支通道合并

class Inception(nn.Module):def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):super(Inception, self).__init__(**kwargs)self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)def forward(self, x):p1 = F.relu(self.p1_1(x))p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))p4 = F.relu(self.p4_2(self.p4_1(x)))return torch.cat((p1, p2, p3, p4), dim=1)

模型构建

b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),nn.ReLU(),nn.Conv2d(64, 192, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),Inception(256, 128, (128, 192), (32, 96), 64),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),Inception(512, 160, (112, 224), (24, 64), 64),Inception(512, 128, (128, 256), (24, 64), 64),Inception(512, 112, (144, 288), (32, 64), 64),Inception(528, 256, (160, 320), (32, 128), 128),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),Inception(832, 384, (192, 384), (48, 128), 128),nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten())net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10))

resNet18

模型结构

这个模型似乎要更加简洁一些,因为这里只有两个分支,但是他有两种分支方式,一种是卷积+残差,另外一种是卷积+经过1x1卷积处理过的残差
在这里插入图片描述

残差块

class Residual(nn.Module):def __init__(self, input_channels, num_channels, use_1x1conv=False, strides=1):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 = Noneself.bn1 = nn.BatchNorm2d(num_channels)self.bn2 = nn.BatchNorm2d(num_channels)def forward(self, X):Y = F.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.conv3:X = self.conv3(X)Y += Xreturn F.relu(Y)

构建时依次使用两种分支方式

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

模型构建

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))
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))net = nn.Sequential(b1, b2, b3, b4, b5, nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(512, 10))

denseNet

模型结构

这个模型的主要思路就是把每一次的输出和输入合并起来,同时作为下一层的输入,具体的细节还要结合代码解释
在这里插入图片描述

DenseBlock

我们看下面的代码,注意init中的循环以及forward时对于X的处理。我们可以发现,每经过一个conv_block都会将conv_block的输出并入到输入,以此作为下一层的输入

def conv_block(input_channels, num_channels):return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1))class DenseBlock(nn.Module):def __init__(self, num_convs, input_channels, num_channels):super(DenseBlock, self).__init__()layer = []for i in range(num_convs):layer.append(conv_block(num_channels * i + input_channels, num_channels))self.net = nn.Sequential(*layer)def forward(self, X):for blk in self.net:Y = blk(X)X = torch.cat((X, Y), dim=1)return X

transition_block

这个块的主要作用是减少通道,因为在前面的块中,通道数会持续的增长,考虑到计算量,需要在中间加入减少通道的块

def transition_block(input_channels, num_channels):return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=1),nn.AvgPool2d(kernel_size=2, stride=2))

模型构建

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))num_channels, growth_rate = 64, 32
num_convs_in_dense_blocks = [4, 4, 4, 4]
blks = []
for i, num_convs in enumerate(num_convs_in_dense_blocks):blks.append(DenseBlock(num_convs, num_channels, growth_rate))num_channels += num_convs * growth_rateif i != len(num_convs_in_dense_blocks) - 1:blks.append(transition_block(num_channels, num_channels // 2))num_channels = num_channels // 2net = nn.Sequential(b1, *blks,nn.BatchNorm2d(num_channels), nn.ReLU(),nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(num_channels, 10))

结尾

我们到现在模型就已经构建好了,测试的过程可以参照本专栏的上一篇博客
pytorch深度学习基础(十)——常用线性CNN模型的结构与训练


http://www.ppmy.cn/news/19646.html

相关文章

【MySQL进阶】MySQL视图详解

序号系列文章6【MySQL基础】MySQL单表操作详解7【MySQL基础】运算符及相关函数详解8【MySQL基础】MySQL多表操作详解9【MySQL进阶】MySQL事务详解文章目录前言1,视图1.1,视图概述1.2,视图使用环境1.3,视图创建格式1.4,…

常见DEM数据汇总

常见DEM数据汇总ALOS-2 PALSAR DEM数据 [12.5m]Shuttle Radar Topography Mission (SRTM) [30m, 90m]Advanced Spaceborne Thermal Emission and Reflection Radiometer (ASTER) [30m]USGS 30 ARC-second Global Elevation Data, GTOPO30 [1km]火星轨道器激光高度计&#xff08…

恶意代码分析实战 16 Shellcode分析

16.1 Lab19-01 将程序载入IDA。 一堆ecx自增的操作。到200是正常的代码段。 shellcode的解码器也是从这里开始的,一开始的xor用于清空ecx,之后将18dh赋给cx,jmp来到loc_21f,而在下图可以看到loc_21调用sub_208,在call指令执行后&#xff0…

【数据结构】7.2 线性表的查找

文章目录7.2.1 顺序查找(线性查找)顺序查找算法设置监视哨的顺序查找顺序查找算法分析7.2.2 折半查找(二分或对分查找)折半查找算法折半查找性能分析 - 判定树7.2.3 分块查找分快查找算法分块查找算法分析及比较查找方法比较7.2.1…

【进击的算法】基础算法——怎么优雅地控制边界范围

学习范围 : ✔️数组 ✔️边界控制本文作者 : 蓝色学者i 边界控制的艺术前言一、为什么需要控制边界?二、怎么优雅地控制边界?三、令人抓狂的二分查找3.1 题目概述3.2解题思路3.3 解决方案方案一:边界都有效方案二&…

Docker 基础 - 3

Web 服务器与应用 Nginx 我的Nginx Docker镜像 ## 设置继承自己创建的 sshd 镜像 FROM caseycui/ubuntu-sshd## 维护者 LABEL maintainer"CaseyCui cuikaidongfoxmail.com"## 安装 nginx RUN apt-get update \&& DEBIAN_FRONTENDnoninteractive apt-get ins…

[Python]调用pytdx的代码示例

安装pytdxpip install pytdx简单示范from pytdx.hq import TdxHq_API api TdxHq_API() # 数据获取接口一般返回list结构, with api.connect(119.147.212.81, 7709): # 返回普通listdata api.get_security_bars(9, 0, 000001, 0, 10) print(data)输出结果[Ordered…

什么是YOLOR?

简述YOLOR 是一种用于对象检测的最先进的机器学习算法,与 YOLOv1-YOLOv5 不同,原因在于作者身份、架构和模型基础设施的差异。YOLOR 代表“你只学习一种表示”,不要与 YOLO 版本 1 到 4 混淆,其中 YOLO 代表“你只看一次”。 YOLO…