图像分类学习笔记(六)——ResNeXt

一、要点

ResNeXt是ResNet的小幅升级,更新了block

 左边(ResNet的block/50/101/152层):

对于输入通道为256的特征矩阵,首先使用64个1×1的卷积核进行降维,再通过64个3×3的卷积核处理,再通过256个1×1的卷积核升维输出,将输出与输入进行相加,得到最终的输出。

使用右边的结构替代左边的结构:下面解释。

(一)论文中的性能参数指标

 (二)关于ResNet和ResNeXt在ImageNet上top-1 的错误率(计算量相同)

(三)组卷积 (Group Convolution)

当分组的个数与输入特征矩阵的channel是一致的,并且输入特征矩阵的channel也和输出特征矩阵的channel一致的话,就相当于对我们输入特征矩阵的每一个channel分配了一个channel为1的卷积核进行卷积。即DW卷积。

(四)ResNeXt的block结构

(c)(最简形式):输入通道为256维,首先通过128个1×1的卷积核降维处理,再通过group卷积(卷积核3×3,group数为32),得到的特征矩阵的通道是128维,再通过256个1×1的卷积核升维得到输出。再将输出和输入的特征矩阵进行相加得到最终的输出。

(b)和(c)等价

 (a)和(b)等价

 举例:假设path为2,对每个path采用1×1的卷积核来进行卷积

(五) 网络结构

二、使用pytorch搭建

代码是包括ResNet和ResNeXt的

import torch.nn as nn
import torch# 18层/34层 对应的残差结构(既要有实线残差结构的功能,又要有虚线残差结构的功能)
class BasicBlock(nn.Module):expansion = 1  #残差结构的主分支卷积核的个数有无发生变化def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs): # downsample对应残差结构的虚线(shortcut分支)super(BasicBlock, self).__init__()# stride=1,对应着实线的残差结构,因为并没有改变输入特征矩阵的高和宽# output = (input -3 + 2 * 1) / 1 + 1 = input# stride=2,对应着虚线的残差结构,在第一个卷积层需要将特征矩阵的高和宽缩减为原来的一半# output = (input -3 + 2 * 1) / 2 + 1 = input / 2 + 0.5 = input / 2 (向下取整)self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,kernel_size=3, stride=stride, padding=1, bias=False)  # bias=False,不使用偏置项,因为下面用到BatchNormalizationself.bn1 = nn.BatchNorm2d(out_channel)self.relu = nn.ReLU()self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,kernel_size=3, stride=1, padding=1, bias=False)self.bn2 = nn.BatchNorm2d(out_channel)self.downsample = downsampledef forward(self, x):identity = x # shorcut上的输出值if self.downsample is not None:identity = self.downsample(x)out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out += identityout = self.relu(out)return out# 50层/101层/152层 对应的残差结构
class Bottleneck(nn.Module):"""注意:原论文中,在虚线残差结构的主分支上,第一个1x1卷积层的步距是2,第二个3x3卷积层步距是1。但在pytorch官方实现过程中是第一个1x1卷积层的步距是1,第二个3x3卷积层步距是2,这么做的好处是能够在top1上提升大概0.5%的准确率。可参考Resnet v1.5 https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch"""expansion = 4  #每个残差结构的最后一层卷积核的个数都是前两层的4倍def __init__(self, in_channel, out_channel, stride=1, downsample=None,groups=1, width_per_group=64):super(Bottleneck, self).__init__()width = int(out_channel * (width_per_group / 64.)) * groupsself.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=width,kernel_size=1, stride=1, bias=False)  # squeeze channelsself.bn1 = nn.BatchNorm2d(width)# -----------------------------------------self.conv2 = nn.Conv2d(in_channels=width, out_channels=width, groups=groups,kernel_size=3, stride=stride, bias=False, padding=1)self.bn2 = nn.BatchNorm2d(width)# -----------------------------------------self.conv3 = nn.Conv2d(in_channels=width, out_channels=out_channel*self.expansion,kernel_size=1, stride=1, bias=False)  # unsqueeze channelsself.bn3 = nn.BatchNorm2d(out_channel*self.expansion)self.relu = nn.ReLU(inplace=True)self.downsample = downsampledef forward(self, x):identity = xif self.downsample is not None:identity = self.downsample(x)out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out = self.relu(out)out = self.conv3(out)out = self.bn3(out)out += identityout = self.relu(out)return outclass ResNet(nn.Module):def __init__(self,block, # 对应18/34层或者50/101/152层的残差结构blocks_num, # 残差结构的个数,是个列表,以34层为例,就是[3,4,6,3]num_classes=1000, # 训练集的分类个数include_top=True, # 方便以后在ResNet网络上去搭建更复杂的网络groups=1,width_per_group=64):super(ResNet, self).__init__()self.include_top = include_topself.in_channel = 64self.groups = groupsself.width_per_group = width_per_groupself.conv1 = nn.Conv2d(3, self.in_channel, kernel_size=7, stride=2,padding=3, bias=False)# 为了让特征矩阵的宽和高缩减为原来的一半,所以这里padding=3self.bn1 = nn.BatchNorm2d(self.in_channel)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)# 为了让特征矩阵的宽和高缩减为原来的一半,所以这里padding=1self.layer1 = self._make_layer(block, 64, blocks_num[0]) # conv2_x 对于50/101/152层来说,第一个残差结构的第一层只改变特征矩阵的深度,没有改变宽高,所以没有传入stride,默认为1self.layer2 = self._make_layer(block, 128, blocks_num[1], stride=2) # conv3_xself.layer3 = self._make_layer(block, 256, blocks_num[2], stride=2) # conv4_xself.layer4 = self._make_layer(block, 512, blocks_num[3], stride=2) # conv5_xif self.include_top:self.avgpool = nn.AdaptiveAvgPool2d((1, 1))  # output size = (1, 1)self.fc = nn.Linear(512 * block.expansion, num_classes)for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')def _make_layer(self, block, channel, block_num, stride=1):downsample = None# 对于18/34层第一个残差结构,跳过这句if stride != 1 or self.in_channel != channel * block.expansion:downsample = nn.Sequential(nn.Conv2d(self.in_channel, channel * block.expansion, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(channel * block.expansion))layers = []# 残差结构的第一层(虚线残差结构)layers.append(block(self.in_channel,channel,downsample=downsample,stride=stride,groups=self.groups,width_per_group=self.width_per_group))self.in_channel = channel * block.expansionfor _ in range(1, block_num):layers.append(block(self.in_channel,channel,groups=self.groups,width_per_group=self.width_per_group))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)if self.include_top:x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return xdef resnet34(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet34-333f7ec4.pthreturn ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet50(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet50-19c8e357.pthreturn ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet101(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet101-5d3b4d8f.pthreturn ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, include_top=include_top)def resnext50_32x4d(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pthgroups = 32width_per_group = 4return ResNet(Bottleneck, [3, 4, 6, 3],num_classes=num_classes,include_top=include_top,groups=groups,width_per_group=width_per_group)def resnext101_32x8d(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pthgroups = 32width_per_group = 8return ResNet(Bottleneck, [3, 4, 23, 3],num_classes=num_classes,include_top=include_top,groups=groups,width_per_group=width_per_group)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/88499.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flink on yarn with kerberos 边缘提交

flink on yarn 带kerberos 远程提交 实现 flink kerberos 配置 先使用ugi进行一次认证正常提交 import com.google.common.io.Files; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.flink.client.cli.CliFrontend; import o…

无涯教程-Python机器学习 - Stochastic Gradient Boosting函数

它也称为梯度提升机。在下面的Python食谱中,我们将通过使用pima Indians糖尿病数据集上的 sklearn 的 GradientBoostingClassifier 类来创建随机梯度Boostingensemble模型进行分类。 首先,导入所需的软件包,如下所示: from pandas import read_csv from sklearn.model_select…

【数据结构】排序(插入、选择、交换、归并) -- 详解

一、排序的概念及其运用 1、排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记…

HUT23级训练赛

目录 A - tmn学长的字符串1 B - 帮帮神君先生 C - z学长的猫 D - 这题用来防ak E - 这题考察FFT卷积 F - 这题考察二进制 G - 这题考察高精度 H - 这题考察签到 I - 爱派克斯,启动! J - tmn学长的字符串2 K - 秋奕来买瓜 A - tmn学长的字符串1 思路&#x…

Goland 配置go modules 环境变量

我的配置,仅供参考: GOPROXYhttps://goproxy.cn,direct;GO111MODULEon;GOSUMDBoff;GONOSUMDB*

网络基础知识socket编程

目录 网络通信概述网络互连模型:OSI 七层模型TCP/IP 四层/五层模型数据的封装与拆封 IP 地址IP 地址的编址方式IP 地址的分类特殊的IP 地址如何判断2 个IP 地址是否在同一个网段内 TCP/IP 协议TCP 协议TCP 协议的特性TCP 报文格式建立TCP 连接:三次握手关…

网工内推 | IT网工,华为、华三认证优先,15k*13薪

01 广东善能科技发展股份有限公司 招聘岗位:IT网络工程师 职责描述: 1、负责公司项目售后技术支持工作; 2、负责项目交付实施,配置调试、运维等; 3、参加合作厂商产品技术知识培训; 4、参加合作厂商工程师…

顺序表链表OJ题(3)——【数据结构】

W...Y的主页 😊 代码仓库分享 💕 前言: 今天是链表顺序表OJ练习题最后一次分享,每一次的分享题目的难度也再有所提高,但是我相信大家都是非常机智的,希望看到博主文章能学到东西的可以一键三连关注一下博主…

Windows 桌面运维及安全管理

什么是桌面运维 桌面运维是IT管理的重要部分,是一种系统管理的技术,它的主要目的是通过管理用户、计算机和其他设备来提高组织的效率。它不仅能够降低维护成本,而且还能够提高系统的可用性。 如今随着企业设备越来越丰富,桌面运…

Zabbix 5.0 媒体介质 邮箱配置例子

QQ企业邮箱 参考:zabbix 腾讯企业邮箱配置图_harveymomo的博客-CSDN博客

内网 里面安装 vue

1.先在内网电脑上安装node,跟自己电脑一样的版本 2.把自己电脑 node里面 node-cache, node_global,node_modules 三个文件 拷贝到内网电脑 的node 里面 3.内网在配置 node_cache的环境变量环境变量如何配置连接

4.19 20

服务端没有 listen,客户端发起连接建立,会发生什么? 服务端如果只 bind 了 IP 地址和端口,而没有调用 listen 的话,然后客户端对服务端发起了连接建立,服务端会回 RST 报文。 没有 listen&#x…