霹雳吧啦Wz《pytorch图像分类》-p5ResNet网络

《pytorch图像分类》p5ResNet网络结构

  • 1 网络中的亮点
    • 1.1 超深的网络结构
    • 1.2 residual模块
    • 1.3 Batch Normalization
    • 1.4 迁移学习简介
  • 2 模块类代码
    • 2.1 BasicBlock(18 & 32 layers)
    • 2.2 Bottleneck(50 & 101 & 152layers)
    • 2.3 ResNet
  • 3 课程代码
    • 3.1 modle.py
    • 3.2 train.py
    • 3.3 predict.py

1 网络中的亮点

论文连接:Deep Residual Learning for Image Recognition

1.1 超深的网络结构

AlexNet,VggNet等之前学习的网络当中,深度只有十几层到二十几层,如果层数加深,会产生梯度消失或者梯度爆炸现象,错误率反而会增高(如左图),ResNet是添加了残差模块之后才能搭建足够深的网络模型(如右图)。
在这里插入图片描述
网络深度突破了1000层
在这里插入图片描述

1.2 residual模块

残差模块(Residual module)是一种常用于深度卷积神经网络(CNN)中的构建块,用于解决梯度消失或爆炸的问题,并帮助网络更有效地进行训练。
残差模块的核心思想是通过引入跳跃连接shortcut connections(论文中写的术语)来绕过一些卷积层,将输入直接添加到输出中

在这里插入图片描述
当输入特征图和输出特征图在维度上不匹配时,可以通过1x1卷积层调整维度,以确保它们可以相加。
在这里插入图片描述
Down sampling is performed by conv3_1, conv4_1, and conv5_1 with a stride of 2.
下采样由conv3_1、conv4_1和conv5_1执行,步长为2。
在这里插入图片描述

1.3 Batch Normalization

Batch Normalization(批归一化)是一种在深度神经网络中用于提高训练速度和稳定性的技术。它通过对每个小批次(batch)的输入数据进行归一化处理,以使输入的均值和方差保持在稳定范围内

举个例子:我们在烹饪中做蛋糕的过程。每次用相同的配方烤蛋糕时,我们都会按照配方中的比例加入相同的材料,所以无论做几个蛋糕,它们都会有相似的味道和口感。
类似地,神经网络的训练过程中,我们可以将输入数据看作是蛋糕的材料。批归一化通过对每个批次中的数据进行标准化,使得它们具有零均值和单位方差。这相当于将每个批次的数据转化为类似的“蛋糕材料”,这样神经网络在处理不同的批次时,每个批次的数据都可以在相似的范围内变化。这样有利于网络的学习和训练。
(我还得找资料更深一步去学习)

1.4 迁移学习简介

  1. 能够快速的训练出一个理想的结果
  2. 当数据集比较小的时候也能训练出理想的效果

常见的迁移学习方式:

  1. 载入权重后训练所有参数
  2. 载入权重后只训练最后几层参数
  3. 载入权重后在原网络基础上再添加一层全连接层,仅训练最后一个全连接层

2 模块类代码

2.1 BasicBlock(18 & 32 layers)

针对18层和34层的残差结构
expansion是指每个残差块的输出通道数相对于输入通道数的倍数,主分支所采用的卷积核的个数有没有发生变化,expansion=1也就是卷积核个数没有发生变化。
在这里插入图片描述

downsample=None对应的是虚线的结构,比如conv3、conv4和conv5的第一层,见1.2residual结构的第二张图

def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs):

在这里插入图片描述

2.2 Bottleneck(50 & 101 & 152layers)

针对50层、101层和152层的残差结构
expansion=4即输出通道数是输入通道数的4倍。
在这里插入图片描述

def __init__(self, in_channel, out_channel, stride=1, downsample=None,groups=1, width_per_group=64):

2.3 ResNet

在这里插入图片描述

class ResNet(nn.Module):def __init__(self,block,blocks_num,num_classes=1000,include_top=True,groups=1,width_per_group=64):

3 课程代码

3.1 modle.py

import torch.nn as nn
import torchclass BasicBlock(nn.Module):expansion = 1def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs):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)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)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 outclass 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 = 4def __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,blocks_num,num_classes=1000,include_top=True,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])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')def _make_layer(self, block, channel, block_num, stride=1):downsample = Noneif 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)

3.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),transforms.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 = 16nw = 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.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 = "1.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()

1.jpg预测的玫瑰花
在这里插入图片描述
2.jpg预测的雏菊
在这里插入图片描述

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

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

相关文章

爬虫如何获取免费代理IP(二)

89ip代理爬取代码实现 一、代码实现 import requests import time import random from fake_useragent import UserAgent from lxml import etree import os import csv""" 89ip代理爬取 """class IPSipder(object):def __init__(self):self.u…

Python 操作 JMeter 探索:pymeter 实操指南

概要 JMeter 是一个流行的性能测试工具,用于测试 Web 应用程序的性能和负载。它通常与 GUI 一起使用,但如果您想在自动化测试中集成 JMeter,或者以编程方式创建和运行测试计划,那么 pymeter 库将是一个强大的工具。本文将介绍如何…

2023-12-26分割回文串和子集以及子集II

131. 分割回文串 思想:回溯三步骤!① 传入参数 ② 回溯结束条件 ③ 单层搜索逻辑!抽象成回溯树,树枝上是每次从头部穷举切分出的子串,节点上是待切分的剩余字符串【从头开始每次往后加一】 class Solution:def partiti…

JavaScript中实现页面跳转的多种方法【通俗易懂】

✨前言✨   本篇文章主要在于如何使用JavaScript中的各种实现页面跳转的方式 🍒欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍒博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言 在JavaScr…

Fortify漏洞之Sql Injection(sql注入)

Fortify漏洞之Sql Injection(sql注入) 前言 本篇先对Fortify做个简单的认识,同时总结一下sql注入的漏洞! 一、Fortify软件介绍 Fortify是一款能扫描分析代码漏洞的强大工具,是由一家加州软件安全厂商开发而成&#…

为什么要为IP地址申请SSL证书?

在不断发展的互联网世界中,网络安全越来越受到重视,这不仅是因为相关法律法规政策的实施,还因为确保网络安全可以为企业减少财产损失。而确保企业在线业务安全的关键一点,就是SSL证书的部署,SSL证书不仅可以加密数据&a…

Unity中Shader雾效在场景中的调节技巧

文章目录 前言一、修改棋盘格Shader的Cull可以在属性面板控制1、在属性面板定义CullMode2、在SubShader中,使用CullMode3、这样就可以在不同剔除情况下使用棋盘格场景了 二、调节天际线颜色和雾融为一体1、在摄像机设置不渲染天空盒,渲染单一颜色2、采样…

如何解决大模型的「幻觉」问题?

如何解决大模型的「幻觉」问题? 如何解决大模型的「幻觉」问题?幻觉产生原因?模型原因数据层面 幻觉怎么评估?Reference-based(基于参考信息)基于模型的输入、预先定义的目标输出基于模型的输入 Reference-…

Elasticsearch基本操作之索引操作

本文说下Elasticsearch基本操作之索引操作 文章目录 概述创建索引创建索引示例重复创建索引示例 查看索引查看所有索引查看单个索引 删除索引删除索引 概述 由于是使用命令来操作Elasticsearch,可以使用kibana,postman和apifox等工具 我使用了apifox来执…

【bug】【VSCode】远程终端TERMINAL打不开

【bug】【VSCode】远程终端TERMINAL打不开 可能的原因现象分析解决 可能的原因 昨天晚上vscode在打开多个TERMINAL的情况下,挂了一晚上,今早上来看的时候全都lost connections…。然后关闭再打开就出现了如上现象。 早上一来到实验室就要debug… 现象…

西北工业大学计算机组成原理实验报告——verilog前两次

说明 为了有较好的可读性,报告仅仅粘贴关键代码。该PDF带有大纲功能,点击大纲中的对应标题,可以快速跳转。 实验目标 掌握单周期CPU执行指令的流程和原理;学习使用verilog HDL语言实现单周期CPU, 并通过功能仿真;提…

k8s之pod

pod是k8s中最小的资源管理组件 pod也是最小化运行容器化的应用的资源管理对象 pod是一个抽象的概念,可以理解成一个或者多个容器化应用的集合 pod可以是一个或者多个 在一个pod中运行一个容器(最常用的方式) 在一个pod中同时运行多个容器…

第二证券:长期布局重要窗口或至 险资看涨A股

新年伊始,稳妥资金对2024年权益商场出资更为达观。多家险资组织告诉上海证券报记者,在经历了2023年的震动调整行情后,2024年A股商场机遇大于危险,商场体现或将显着优于2023年。 详细来看,两方面要素支撑权益商场向好&…

总结MySQL 的一些知识点:MySQL 排序

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

[每周一更]-(第56期):不能不懂的网络知识

作为程序员,在网络方面具备一定的知识和技能是非常重要的。以下是一些程序员需要熟练掌握的网络知识: 基础网络概念: IP地址:了解IPv4和IPv6地址的格式和分配方式,以及常见的IP地址分类。子网掩码:理解子…

Vue3 使用路由 Router

Vue3 使用路由 Router 之前几篇博文说了一下 vue 的基本语法和 vue 的传参,今天这篇博文稍微说一下 vue3 里面使用路由。 介绍 众所周知,vue 是用来构建单页面应用的前端框架,大于大多数此类型应用来讲,都推荐使用官方支持的 vue…

宋仕强论道之华强北后山寨手机时代(三十六)

今天继续讲华强北山寨手机,跟手机配套周边产品。华强北,作为中国电子产品的集散地和创新中心,一直以来都是电子产品和数码产品的聚集地。在早期,赛格市场以其走私、翻新的电脑和电脑周边产品而闻名。赛格大厦以前5楼以上都是做电脑…

乒乓球廉价底板评测之五F勒布伦打法讨论

菲利克斯勒布伦的直拍打法让直板又焕发了青春,那他的打法又有什么特点呢?和中国众多直板选手的区别在哪呢?这篇微博我们简单分一下。 首先说下他的器材,纤维板中置碳,淘宝上的版本是碳在大芯两侧,是七层板&…

Unity中URP下统一不同平台下的z值

文章目录 前言一、ComputeFogFactor 来计算雾效混合因子二、UNITY_Z_0_FAR_FROM_CLIPSPACE 来统一计算不同平台下的Z值1、DirectX平台2、GL平台下(在Unity.2022.LTS下,该功能没有完善)3、Opengl下 前言 在之前的文章中,我们实现了URP下的雾效…

电动汽车BMS PCB制板的技术分析与可制造性设计

随着电动汽车行业的迅猛发展,各大厂商纷纷投入巨资进行技术研发和创新。电动汽车的核心之一在于其电池管理系统(Battery Management System, BMS),而BMS的心脏则是其印刷电路板(PCB)。通过这篇文章探讨电动…