ResNet网络结构详解,网络搭建,迁移学习

article/2025/9/16 5:45:01

前言:

参考内容来自up:6.1 ResNet网络结构,BN以及迁移学习详解_哔哩哔哩_bilibili

up的代码和ppt:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing

一、简介

ResNet 网络是在 2015年 由微软实验室提出,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得COCO数据集中目标检测第一名,图像分割第一名。

  • 原论文地址:[1512.03385] Deep Residual Learning for Image Recognition (arxiv.org)

  • 在ResNet网络的创新点:

  • 搭建超深的网络结构(可突破1000层)

  • 提出 Residual 结构(残差结构 )

  • 使用 Batch Normalization 加速训练(丢弃dropout)

下图是ResNet34层模型和VGG模型的对比结构简图:

二、详解

1 . 为什么使用残差模块 ?

在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与池化层进行堆叠得到的。

一般我们会觉得网络越深,特征信息越丰富,模型效果应该越好。但是实验证明,当网络堆叠到一定深度时,会出现两个问题:

  • 梯度消失或梯度爆炸

关于梯度消失和梯度爆炸,其实看名字理解最好:
若每一层的误差梯度小于1,反向传播时,网络越深,梯度越趋近于0
反之,若每一层的误差梯度大于1,反向传播时,网路越深,梯度越来越大

这个问题通常通过对数据进行标准化处理,权重初始化,BN处理等方法。

  • 退化问题(degradation problem):在解决了梯度消失、爆炸问题后,仍然存在深层网络的效果可能比浅层网络差的现象

这个问题通过残差结构解决

总结就是,当网络堆叠到一定深度时,反而会出现深层网络比浅层网络效果差的情况

如下图所示,20层网络比56层网络的误差更小:

在原论文中:

  • 提出通过数据的预处理以及在网络中使用 BNBatch Normalization)层来解决梯度消失或梯度爆炸问题。

  • 提出了 residual结构残差结构)来减轻退化问题,下图是使用residual结构的卷积网络,可以看到随着网络的不断加深,效果并没有变差,而是变的更好了。(虚线是train error,实线是test error)

2 . 什么是残差网络 ?

为了解决深层网络中的退化问题,可以人为地让神经网络某些层跳过下一层神经元的连接,隔层相连,弱化每层之间的强联系。这种神经网络被称为 残差网络 (ResNets)。

残差块

假设 F(x) 代表某个只包含有两层的映射函数, x 是输入, F(x)是输出。假设他们具有相同的维度。在训练的过程中我们希望能够通过修改网络中的 w和b去拟合一个理想的 H(x)(从输入到输出的一个理想的映射函数)。也就是我们的目标是修改F(x) 中的 w和b逼近 H(x) 。如果我们改变思路,用F(x) 来逼近 H(x)-x ,那么我们最终得到的输出就变为 F(x)+x(这里的加指的是对应位置上的元素相加,也就是element-wise addition),这里将直接从输入连接到输出的结构也称为shortcut,那整个结构就是残差块,ResNet的基础模块。

ResNet沿用了VGG全3x3卷积层的设计。残差块里首先有2个有相同输出通道数的3x3卷积层。每个卷积层后接BN层和ReLU激活函数,然后将输入直接加在最后的ReLU激活函数前,这种结构用于层数较少的神经网络中,比如ResNet34。若输入通道数比较多,就需要引入1x1卷积层来调整输入的通道数,这种结构也叫作瓶颈模块,通常用于网络层数较多的结构中。如下图所示:

注意:主分支与shortcut的输出特征矩阵shape必须相同

可以计算一下,假设两个残差结构的输入特征和输出特征矩阵的深度都是256维,如下图:(注意左侧结构的改动)

那么两个残差结构所需的参数为:
左侧:3 × 3 × 256 × 256 + 3 × 3 × 256 × 256 = 1 , 179 , 648
右侧:1 × 1 × 256 × 64 + 3 × 3 × 64 × 64 + 1 × 1 × 64 × 256 = 69 , 632
注:CNN参数个数 = 卷积核尺寸×卷积核深度 × 卷积核组数 = 卷积核尺寸 × 输入特征矩阵深度 × 输出特征矩阵深度
明显搭建深层网络时,使用右侧的残差结构更合适。

3 . 网路结构

观察下图34层网络,可以发现有些残差块的 short cut 是实线的,而有些则是虚线的。

这些虚线的 short cut 上通过1×1的卷积核进行了维度处理(特征矩阵在长宽方向降采样,深度方向调整成下一层残差结构所需要的channel)。

下图是原论文给出的不同深度的ResNet网络结构配置,注意表中的残差结构给出了主分支上卷积核的大小与卷积核个数,表中 残差块×N 表示将该残差结构重复N次。

原文的表注中已说明,conv3_x, conv4_x, conv5_x所对应的一系列残差结构的第一层残差结构都是虚线残差结构。因为这一系列残差结构的第一层都有调整输入特征矩阵shape的作用(将特征矩阵的高和宽缩减为原来的一半,将深度channel调整成下一层残差结构所需要的channel)

需要注意的是,对于ResNet50/101/152,其实conv2_x所对应的一系列残差结构的第一层也是虚线残差结构,因为它需要调整输入特征矩阵的channel。根据表格可知通过3x3的max pool之后输出的特征矩阵shape应该是[56, 56, 64],但conv2_x所对应的一系列残差结构中的实线残差结构它们期望的输入特征矩阵shape是[56, 56, 256](因为这样才能保证输入输出特征矩阵shape相同,才能将捷径分支的输出与主分支的输出进行相加)。所以第一层残差结构需要将shape从[56, 56, 64] --> [56, 56, 256]。注意,这里只调整channel维度,高和宽不变(而conv3_x, conv4_x, conv5_x所对应的一系列残差结构的第一层虚线残差结构不仅要调整channel还要将高和宽缩减为原来的一半)。

ResNet

残差结构

浅层网络

ResNet18/34

BasicBlock

深层网络

ResNet50/101/152

Bottleneck

ResNet 18/34 具体的残差结构图:

ResNet 50/101/152 具体的残差结构图:

4 . Batch Normalization原理

我们在图像预处理过程中通常会对图像进行标准化处理,这样能够加速网络的收敛,如下图所示,对于Conv1来说输入的就是满足某一分布的特征矩阵,但对于Conv2而言输入的feature map就不一定满足某一分布规律了注意这里所说满足某一分布规律并不是指某一个feature map的数据要满足分布规律,理论上是指整个训练样本集所对应feature map的数据要满足分布规律)。而我们Batch Normalization的目的就是使我们的feature map满足均值为0,方差为1的分布规律

使用BN时需要注意的问题

(1)训练时要将traning参数设置为True,在验证时将trainning参数设置为False。在pytorch中可通过创建模型的model.train()和model.eval()方法控制。

(2)batch size尽可能设置大点,设置小后表现可能很糟糕,设置的越大求的均值和方差越接近整个训练集的均值和方差。

(3)建议将bn层放在卷积层(Conv)和激活层(例如Relu)之间,且卷积层不要使用偏置bias,因为没有用

三、迁移学习

迁移学习(Transfer Learning)是一种机器学习方法,是把一个领域(源领域)的知识,迁移到另外一个领域(目标领域),使得目标领域能够取得更好的学习效果。

在迁移学习中,我们希望利用源任务(Source Task)学到的知识帮助学习目标任务 (Target Task)。例如,一个训练好的图像分类网络能够被用于另一个图像相关的任务。再比如,一个网络在仿真环境学习的知识可以被迁移到真实环境的网络。迁移学习一个典型的例子就是载入训练好VGG网络,这个大规模分类网络能将图像分到1000个类别,然后把这个网络用于另一个任务,如医学图像分类。

如下图所示,神经网络逐层提取图像的深层信息,这样,预训练网络就相当于一个特征提取器。

  • 使用迁移学习的优势

  1. 能够快速的训练出一个理想的结果

  1. 当数据集较小时也能训练出理想的效果

   注意:使用别人预训练好的模型参数时,要注意别人的预处理方式。

  • 常见的迁移学习方式

  1. 载入权重后训练所有参数

  1. 载入权重后只训练最后几层参数

  1. 载入权重后在原网络基础上再添加一层全连接层,仅训练最后一个全连接层

四、网络搭建

1 model.py

import torch.nn as nn
import torch# ResNet18/34的残差结构,用的是2个3x3的卷积
class BasicBlock(nn.Module):expansion = 1  # 残差结构中,主分支的卷积核个数是否发生变化,不变则为1#初始化层结构,downsample使得既有实现的功能又有虚线的功能,conv3_x, conv4_x, conv5_x所对应的一系列残差结构的第一层都有调整输入特征矩阵shape的作用def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs):  # downsample对应虚线残差结构super(BasicBlock, self).__init__()self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,kernel_size=3, stride=stride, padding=1, bias=False)     #stride为传入进来的,1为视线,不需要改变大小,2为虚线结构,使用BN时不使用偏置#stride=1,output=(input-3+2*1)/ 1 + 1 = input   输入和输出的高和宽时一样的#stride=2,output=(input-3+2*1)/ 2 + 1 = input = input/2 + 0.5 = input/2(向下取整)self.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 = xif self.downsample is not None:   # 虚线残差结构,需要下采样identity = self.downsample(x)  # 捷径分支 short cutout = 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# ResNet50/101/152的残差结构,用的是1x1+3x3+1x1的卷积
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)#stride=stride根据传入的进行调整,因为实线中的第二层是1,虚线中是2self.bn2 = nn.BatchNorm2d(width)# -----------------------------------------self.conv3 = nn.Conv2d(in_channels=width, out_channels=out_channel*self.expansion,      #卷积核个数变为4倍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)  # 捷径分支 short cutout = 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 out#整个网络的框架部分
class ResNet(nn.Module):# block = BasicBlock or Bottleneck# block_num为残差结构中conv2_x~conv5_x中残差块个数,是一个列表,如34层中的是3,4,6,3def __init__(self,block,     blocks_num,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)self.bn1 = nn.BatchNorm2d(self.in_channel)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, 64, blocks_num[0])        #对应conv2所有的一切残差结构,通过_make_layer函数生成self.layer2 = self._make_layer(block, 128, blocks_num[1], stride=2)self.layer3 = self._make_layer(block, 256, blocks_num[2], stride=2)self.layer4 = self._make_layer(block, 512, blocks_num[3], stride=2)if 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')# channel为残差结构中第一层卷积核个数,block_num表示该层一共包含多少个残差结构,如34层中的是3,4,6,3def _make_layer(self, block, channel, block_num, stride=1):downsample = None# ResNet50/101/152的残差结构,block.expansion=4if stride != 1 or self.in_channel != channel * block.expansion:     #layer2,3,4都会经过这个结构downsample = nn.Sequential(     #生成下采样函数,这里只需要调整conv2的特征矩阵的深度nn.Conv2d(self.in_channel, channel * block.expansion, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(channel * block.expansion))layers = []         #空列表     #首先将第一层残差结构添加进去,block = BasicBlock or Bottlenecklayers.append(block(self.in_channel,        #输入特征矩阵的深度64channel,                #残差结构对应主分支上的第一个卷积层的卷积核个数downsample=downsample,  #50/101/152对应的是高宽不变,深度4倍,对应的虚线残差结构stride=stride,          #对于layer1,stride=1,是高宽不变,深度4倍groups=self.groups,width_per_group=self.width_per_group))self.in_channel = channel * block.expansionfor _ in range(1, block_num):               #通过循环将剩下的一系列实线残差结构压入,从1开始,因为0层上面已经搭建好了layers.append(block(self.in_channel,channel,groups=self.groups,width_per_group=self.width_per_group))return nn.Sequential(*layers)       #转换为非关键字参数传入,Sequential将一系列结构组合再一起并返回到layer1def 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)

由于ResNet网络较深,直接训练的话会非常耗时,因此用迁移学习的方法导入预训练好的模型参数:

下载预训练的模型参数的链接在上方代码中

2. train.py

import os
import sys
import jsonimport torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from tqdm import tqdmfrom model import resnet34def main():device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")print("using {} device.".format(device))data_transform = {"train": transforms.Compose([transforms.RandomResizedCrop(224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),"val": transforms.Compose([transforms.Resize(256),      #原图的长宽比固定不动,把最小边长缩放到256transforms.CenterCrop(224),      #中心裁剪transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])}data_root = os.path.abspath(os.path.join(os.getcwd(), "../"))  # get data root pathimage_path = os.path.join(data_root, "data_set", "flower_data")  # flower data set pathassert os.path.exists(image_path), "{} path does not exist.".format(image_path)train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),transform=data_transform["train"])train_num = len(train_dataset)# {'daisy':0, 'dandelion':1, 'roses':2, 'sunflower':3, 'tulips':4}flower_list = train_dataset.class_to_idxcla_dict = dict((val, key) for key, val in flower_list.items())# write dict into json filejson_str = json.dumps(cla_dict, indent=4)with open('class_indices.json', 'w') as json_file:json_file.write(json_str)batch_size = 4nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])  # number of workersprint('Using {} dataloader workers every process'.format(nw))train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size, shuffle=True,num_workers=nw)validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),transform=data_transform["val"])val_num = len(validate_dataset)validate_loader = torch.utils.data.DataLoader(validate_dataset,batch_size=batch_size, shuffle=False,num_workers=nw)print("using {} images for training, {} images for validation.".format(train_num,val_num))net = resnet34()# load pretrain weights# download url: https://download.pytorch.org/models/resnet34-333f7ec4.pthmodel_weight_path = "./resnet34-pre.pth"assert os.path.exists(model_weight_path), "file {} does not exist.".format(model_weight_path)net.load_state_dict(torch.load(model_weight_path, map_location='cpu'))# for param in net.parameters():#     param.requires_grad = False# change fc layer structurein_channel = net.fc.in_featuresnet.fc = nn.Linear(in_channel, 5)net.to(device)# define loss functionloss_function = nn.CrossEntropyLoss()# construct an optimizerparams = [p for p in net.parameters() if p.requires_grad]optimizer = optim.Adam(params, lr=0.0001)epochs = 3best_acc = 0.0save_path = './resNet34.pth'train_steps = len(train_loader)for epoch in range(epochs):# trainnet.train()running_loss = 0.0train_bar = tqdm(train_loader, file=sys.stdout)for step, data in enumerate(train_bar):images, labels = dataoptimizer.zero_grad()logits = net(images.to(device))loss = loss_function(logits, labels.to(device))loss.backward()optimizer.step()# print statisticsrunning_loss += loss.item()train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,epochs,loss)# validatenet.eval()acc = 0.0  # accumulate accurate number / epochwith torch.no_grad():val_bar = tqdm(validate_loader, file=sys.stdout)for val_data in val_bar:val_images, val_labels = val_dataoutputs = net(val_images.to(device))# loss = loss_function(outputs, test_labels)predict_y = torch.max(outputs, dim=1)[1]acc += torch.eq(predict_y, val_labels.to(device)).sum().item()val_bar.desc = "valid epoch[{}/{}]".format(epoch + 1,epochs)val_accurate = acc / val_numprint('[epoch %d] train_loss: %.3f  val_accuracy: %.3f' %(epoch + 1, running_loss / train_steps, val_accurate))if val_accurate > best_acc:best_acc = val_accuratetorch.save(net.state_dict(), save_path)print('Finished Training')if __name__ == '__main__':main()

3 predict.py

import os
import jsonimport torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as pltfrom model import resnet34def main():device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")data_transform = transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# load imageimg_path = "../tulip.jpg"assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)img = Image.open(img_path)plt.imshow(img)# [N, C, H, W]img = data_transform(img)# expand batch dimensionimg = torch.unsqueeze(img, dim=0)# read class_indictjson_path = './class_indices.json'assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)with open(json_path, "r") as f:class_indict = json.load(f)# create modelmodel = resnet34(num_classes=5).to(device)# load model weightsweights_path = "./resNet34.pth"assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)model.load_state_dict(torch.load(weights_path, map_location=device))# predictionmodel.eval()with torch.no_grad():# predict classoutput = torch.squeeze(model(img.to(device))).cpu()predict = torch.softmax(output, dim=0)predict_cla = torch.argmax(predict).numpy()print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],predict[predict_cla].numpy())plt.title(print_res)for i in range(len(predict)):print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],predict[i].numpy()))plt.show()if __name__ == '__main__':main()


http://chatgpt.dhexx.cn/article/auWGGgZj.shtml

相关文章

ResNet网络结构详解与模型的搭建

ResNET(Deep Residual Learning for Image Recognition ) ResNet网络是在2015年由微软实验室提出,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得COCO数据集中目标检测第一名,图像分割第一名。下图是ResNet34层模型的结构简图。…

Resnet网络结构图和对应参数表的简单理解

Resnet Resnet即就是残差网络,本文主要是对于resnet给出的网络结构图进行简单解释。 网络结构图 以上就是34层网络的网络结构图。 以上是18层、34层、50层、101层以及152层网络所对应的残差块。 我刚开始在网上看到这两张图片的时候,感觉一点都不懂&a…

pytorch Resnet 网络结构

最近在学习廖老师的pytorch教程,学到Resnet 这部分着实的烧脑,这个模型都捣鼓了好长时间才弄懂,附上我学习过程中最为不解的网络的具体结构连接(网上一直没有找到对应网络结构,对与一个自学的学渣般的我,很…

ResNet网络结构解析--Pytorch

ResNet101–DSSD/SSD (1)ResNet在Pytorch官方代码中有5种不同深度的结构,分别为18、34、50、101、152(各网络深度指的是“需要通过训练更新参数“的层数,如卷积层,全连接层等),和论…

ResNet网络结构详解及代码复现

1. ResNet论文详解 1.1. Introduction 一般网络越深&#xff0c;特征就越丰富&#xff0c;模型效果也就越好。在深度重要的驱动下&#xff0c;出现了2个问题&#xff1a; 梯度消失和梯度爆炸&#xff1a; 梯度消失&#xff1a;误差梯度<1&#xff0c;当网络层数增多时&…

resnet50网络结构_pytorch实践(改造属于自己的resnet网络结构并训练二分类网络)

我的CSDN博客:https://blog.csdn.net/litt1e 我的公众号:工科宅生活 在学习pytorch过程中,突然想拥有属于自己的网络结构,于是便自己选择了一个比较简单的resnet18进行改造,并用其对蚂蚁和蜜蜂进行分类,比较一下没有经过预训练的resnet18好还是自己改造的resnet_diy好。 …

【DL系列】ResNet网络结构详解、完整代码实现

Name&#xff1a; Deep Residual Learning for Image Recognition Author&#xff1a; 何恺明团队 Publiced&#xff1a; 2015.12_CVPR 文章目录 前言1. 残差网络待解决的问题2. ResNet模型亮点 ResNet模型结构1. 残差学习2. Residual模块3. ResNet模型 ResNet-layers模型完整代…

pytorch实现resnet网络结构

ResNet结构和pytorch实现 resnet的网络结构都是经过5个不同数量的残差块最后一个全连接分类完成的。 在resnet50以后&#xff0c;由于层数的增加残差块发生了变化&#xff0c;从原来3x3卷积变为三层卷积&#xff0c;卷积核分别为1x1、3x3、1x1&#xff0c;减少了网络参数。主…

ResNet网络结构搭建

ResNet 下图为包含有18层(17个卷积层和1个全连接层)、34层(33个卷积层和1个全连接层)、50层(49个卷积层和1个全连接层)、101层(100个卷积层和1个全连接层)、152层(151个卷积层和1个全连接层)的resnet结构 下图是论文中给出的两种残差结构。左边的残差结构是针对层数较少网络&a…

ResNet网络结构

注&#xff1a;深度好像就是channel w*h*c 根据b站up霹雳吧啦的讲解做的笔记 视频地址6.1 ResNet网络结构&#xff0c;BN以及迁移学习详解_哔哩哔哩_bilibiliR 6.2 使用pytorch搭建ResNet并基于迁移学习训练_哔哩哔哩_bilibili ResNet网络解决梯度消失、爆炸&#xff0c;以及…

经典网络ResNet介绍

经典网络ResNet(Residual Networks)由Kaiming He等人于2015年提出&#xff0c;论文名为《Deep Residual Learning for Image Recognition》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/1512.03385.pdf ResNet要解决的是深度神经网络的”退化(degradation)”问题&…

六、ResNet网络详细解析(超详细哦)

1、 RestNet网络 1.1、 RestNet网络结构 ResNet在2015年被提出&#xff0c;在ImageNet比赛classification任务上获得第一名&#xff0c;因为它“简单与实用”并存&#xff0c;之后很多方法都建立在ResNet50或者ResNet101的基础上完成的&#xff0c;检测&#xff0c;分割&…

ResNet结构

文章目录 系列文章目录一、Residual net(残差网络)二、BatchNormalization(BN)三、ResNet结构 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开…

深度学习之图像分类(七)--ResNet网络结构

深度学习之图像分类&#xff08;七&#xff09;ResNet 网络结构 目录 深度学习之图像分类&#xff08;七&#xff09;ResNet 网络结构1. 前言2. Residual3. 网络配置4. 代码 本节学习ResNet网络结构&#xff0c;以及迁移学习入门&#xff0c;学习视频源于 Bilibili&#xff0c;…

[NCTF2019]SQLi 1regexp注入

[NCTF2019]SQLi&regexp注入 知识点&#xff1a; 无引号闭合&#xff0c;可以利用转义符 \ %00作为截断字符可以代替注释符#和-- - regexp注入可以配合 ^ 来爆破字符 解题&#xff1a; 打开题目得到&#xff1a; 可以看做插入语句&#xff1a; select * from users where…

buuctf-[NCTF2019]Keyboard

题目是这样子的&#xff1a; 下载完压缩包并解压后打开txt文件&#xff0c;发现是这样一串密文&#xff1a; 其实答案就在问题题目中&#xff0c;keyboard是键盘的意思&#xff0c;那结果显而易见了&#xff0c;o y i w u e u y u w u i i e不难发现&#xff0c;这些字母在键盘…

NCTF Crypto WriteUp

http://ctf.nuptzj.cn/challenges Crypto篇&#xff1a; 第一题、第二题、第七题和CG-CTF一样&#xff0c;不写了… 第三题&#xff1a; 说了全家桶&#xff0c;那就python跑吧… Flag&#xff1a;nctf{base64_base32_and_base16} 150分到手 第四题&#xff1a; 鬼知道进行…

[NCTF2019]Fake XML cookbook

BUUCTF 刷题 [NCTF2019]Fake XML cookbook BUUCTF 刷题前言一、[NCTF2019]Fake XML cookbook总结 前言 通过刷题拓宽自己的知识面 一、[NCTF2019]Fake XML cookbook &#xff08;1&#xff09;打开后如图所示 &#xff08;2&#xff09;尝试了一下万能密码&#xff0c;没啥用…

[NCTF2019]True XML cookbook

打开环境&#xff0c;看到熟悉的页面&#xff0c;和前面的[NCTF2019]Fake XML cookbook页面一样&#xff0c;应该也是XXE漏洞&#xff0c;这里再介绍一下XXE漏洞&#xff1a; XXE(XML External Entity Injection)全称为XML外部实体注入。 XML是什么&#xff1f; XML指可扩展…

[NCTF2019]Sore

[NCTF2019]Sore 附件&#xff1a; ciphertext.txt&#xff1a; nsfAIHFrMuLynuCApeEstxJOzniQuyBVfAChDEznppfAiEIDcyNFBsCjsLvGlDtqztuaHvHbCmuyGNsIMhGlDtbotCoDzDjhyBzHGfHGfoHsuhlssIMvwlixBHHGfDRjoCKrapNIwqNyuxIBACQhtMwCmMCfEBpsrzEuiLGBoMipTkxrznoHfAkqwzvxuzCzDbL…