PyTorch框架——基于WebUI:Gradio深度学习ShuffleNetv2神经网络蔬菜图像识别分类系统

ops/2025/1/23 19:07:53/

第一步:准备数据

蔬菜数据集,英文为Vegetable。

train 目录下有15000 张图片。

共十五种植物的幼苗图片集,分别为classes = ['Bean', 'Bitter_Gourd', 'Bottle_Gourd', 'Brinjal', 'Broccoli', 'Cabbage', 'Capsicum', 'Carrot', 'Cauliflower', 'Cucumber', 'Papaya', 'Potato', 'Pumpkin', 'Radish', 'Tomato' ]

具体信息如下:

第二步:搭建模型

ShuffleNet_V2是由旷视科技的Ma, Ningning等人在《ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design【ECCV-2018】》【论文地址】一文中提出的改进模型,论文中提出了高效网络架构设计的两大原则:第一,使用直接指标(如速度)而非间接指标(如FLOPs);第二,提出了四条与跨平台的设计指南,并在该指南指导下设计了ShuffleNet_V2

ShuffleNetV2的一些关键特点:

  1. 优化的分组卷积‌:ShuffleNetV2使用了一种称为“channel split”的技术,将输入通道分成两半,分别进行不同的处理,然后合并结果以获得更好的性能‌1。

  2. 自适应分组卷积‌:ShuffleNetV2根据输入数据动态调整分组数量,以实现更高的效率‌1。

  3. 多尺度特征融合‌:引入了多尺度特征融合模块,以更好地捕捉不同尺度的特征‌1。

  4. 通道剪枝‌:应用通道剪枝策略来进一步减少计算复杂度,同时保持准确性‌1。

  5. 内存访问成本最小化‌:ShuffleNetV2试图最小化内存访问成本(MAC),通过精细调整组的数量和结构,找到了计算效率和模型性能之间的最佳平衡点‌2。

  6. 直接面向实际运行速度的优化‌:在设计过程中,除了理论上的计算量(FLOPs)外,还直接考虑了模型在实际硬件上的运行速度,包括CPU和GPU的特定性能特征‌2。

  7. 均衡通道宽度‌:保持每层网络的通道数相对均衡可以减少内存访问的开销,并且对模型性能影响不大‌2。

第三步:训练代码

1)损失函数为:交叉熵损失函数

2)ShuffleNet_V2代码:

from functools import partial
from typing import Any, Callable, List, Optionalimport torch
import torch.nn as nn
from torch import Tensorfrom ..transforms._presets import ImageClassification
from ..utils import _log_api_usage_once
from ._api import register_model, Weights, WeightsEnum
from ._meta import _IMAGENET_CATEGORIES
from ._utils import _ovewrite_named_param, handle_legacy_interface__all__ = ["ShuffleNetV2","ShuffleNet_V2_X0_5_Weights","ShuffleNet_V2_X1_0_Weights","ShuffleNet_V2_X1_5_Weights","ShuffleNet_V2_X2_0_Weights","shufflenet_v2_x0_5","shufflenet_v2_x1_0","shufflenet_v2_x1_5","shufflenet_v2_x2_0",
]def channel_shuffle(x: Tensor, groups: int) -> Tensor:batchsize, num_channels, height, width = x.size()channels_per_group = num_channels // groups# reshapex = x.view(batchsize, groups, channels_per_group, height, width)x = torch.transpose(x, 1, 2).contiguous()# flattenx = x.view(batchsize, num_channels, height, width)return xclass InvertedResidual(nn.Module):def __init__(self, inp: int, oup: int, stride: int) -> None:super().__init__()if not (1 <= stride <= 3):raise ValueError("illegal stride value")self.stride = stridebranch_features = oup // 2if (self.stride == 1) and (inp != branch_features << 1):raise ValueError(f"Invalid combination of stride {stride}, inp {inp} and oup {oup} values. If stride == 1 then inp should be equal to oup // 2 << 1.")if self.stride > 1:self.branch1 = nn.Sequential(self.depthwise_conv(inp, inp, kernel_size=3, stride=self.stride, padding=1),nn.BatchNorm2d(inp),nn.Conv2d(inp, branch_features, kernel_size=1, stride=1, padding=0, bias=False),nn.BatchNorm2d(branch_features),nn.ReLU(inplace=True),)else:self.branch1 = nn.Sequential()self.branch2 = nn.Sequential(nn.Conv2d(inp if (self.stride > 1) else branch_features,branch_features,kernel_size=1,stride=1,padding=0,bias=False,),nn.BatchNorm2d(branch_features),nn.ReLU(inplace=True),self.depthwise_conv(branch_features, branch_features, kernel_size=3, stride=self.stride, padding=1),nn.BatchNorm2d(branch_features),nn.Conv2d(branch_features, branch_features, kernel_size=1, stride=1, padding=0, bias=False),nn.BatchNorm2d(branch_features),nn.ReLU(inplace=True),)@staticmethoddef depthwise_conv(i: int, o: int, kernel_size: int, stride: int = 1, padding: int = 0, bias: bool = False) -> nn.Conv2d:return nn.Conv2d(i, o, kernel_size, stride, padding, bias=bias, groups=i)def forward(self, x: Tensor) -> Tensor:if self.stride == 1:x1, x2 = x.chunk(2, dim=1)out = torch.cat((x1, self.branch2(x2)), dim=1)else:out = torch.cat((self.branch1(x), self.branch2(x)), dim=1)out = channel_shuffle(out, 2)return outclass ShuffleNetV2(nn.Module):def __init__(self,stages_repeats: List[int],stages_out_channels: List[int],num_classes: int = 1000,inverted_residual: Callable[..., nn.Module] = InvertedResidual,) -> None:super().__init__()_log_api_usage_once(self)if len(stages_repeats) != 3:raise ValueError("expected stages_repeats as list of 3 positive ints")if len(stages_out_channels) != 5:raise ValueError("expected stages_out_channels as list of 5 positive ints")self._stage_out_channels = stages_out_channelsinput_channels = 3output_channels = self._stage_out_channels[0]self.conv1 = nn.Sequential(nn.Conv2d(input_channels, output_channels, 3, 2, 1, bias=False),nn.BatchNorm2d(output_channels),nn.ReLU(inplace=True),)input_channels = output_channelsself.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)# Static annotations for mypyself.stage2: nn.Sequentialself.stage3: nn.Sequentialself.stage4: nn.Sequentialstage_names = [f"stage{i}" for i in [2, 3, 4]]for name, repeats, output_channels in zip(stage_names, stages_repeats, self._stage_out_channels[1:]):seq = [inverted_residual(input_channels, output_channels, 2)]for i in range(repeats - 1):seq.append(inverted_residual(output_channels, output_channels, 1))setattr(self, name, nn.Sequential(*seq))input_channels = output_channelsoutput_channels = self._stage_out_channels[-1]self.conv5 = nn.Sequential(nn.Conv2d(input_channels, output_channels, 1, 1, 0, bias=False),nn.BatchNorm2d(output_channels),nn.ReLU(inplace=True),)self.fc = nn.Linear(output_channels, num_classes)def _forward_impl(self, x: Tensor) -> Tensor:# See note [TorchScript super()]x = self.conv1(x)x = self.maxpool(x)x = self.stage2(x)x = self.stage3(x)x = self.stage4(x)x = self.conv5(x)x = x.mean([2, 3])  # globalpoolx = self.fc(x)return xdef forward(self, x: Tensor) -> Tensor:return self._forward_impl(x)def _shufflenetv2(weights: Optional[WeightsEnum],progress: bool,*args: Any,**kwargs: Any,
) -> ShuffleNetV2:if weights is not None:_ovewrite_named_param(kwargs, "num_classes", len(weights.meta["categories"]))model = ShuffleNetV2(*args, **kwargs)if weights is not None:model.load_state_dict(weights.get_state_dict(progress=progress, check_hash=True))return model_COMMON_META = {"min_size": (1, 1),"categories": _IMAGENET_CATEGORIES,"recipe": "https://github.com/ericsun99/Shufflenet-v2-Pytorch",
}class ShuffleNet_V2_X0_5_Weights(WeightsEnum):IMAGENET1K_V1 = Weights(# Weights ported from https://github.com/ericsun99/Shufflenet-v2-Pytorchurl="https://download.pytorch.org/models/shufflenetv2_x0.5-f707e7126e.pth",transforms=partial(ImageClassification, crop_size=224),meta={**_COMMON_META,"num_params": 1366792,"_metrics": {"ImageNet-1K": {"acc@1": 60.552,"acc@5": 81.746,}},"_ops": 0.04,"_file_size": 5.282,"_docs": """These weights were trained from scratch to reproduce closely the results of the paper.""",},)DEFAULT = IMAGENET1K_V1class ShuffleNet_V2_X1_0_Weights(WeightsEnum):IMAGENET1K_V1 = Weights(# Weights ported from https://github.com/ericsun99/Shufflenet-v2-Pytorchurl="https://download.pytorch.org/models/shufflenetv2_x1-5666bf0f80.pth",transforms=partial(ImageClassification, crop_size=224),meta={**_COMMON_META,"num_params": 2278604,"_metrics": {"ImageNet-1K": {"acc@1": 69.362,"acc@5": 88.316,}},"_ops": 0.145,"_file_size": 8.791,"_docs": """These weights were trained from scratch to reproduce closely the results of the paper.""",},)DEFAULT = IMAGENET1K_V1class ShuffleNet_V2_X1_5_Weights(WeightsEnum):IMAGENET1K_V1 = Weights(url="https://download.pytorch.org/models/shufflenetv2_x1_5-3c479a10.pth",transforms=partial(ImageClassification, crop_size=224, resize_size=232),meta={**_COMMON_META,"recipe": "https://github.com/pytorch/vision/pull/5906","num_params": 3503624,"_metrics": {"ImageNet-1K": {"acc@1": 72.996,"acc@5": 91.086,}},"_ops": 0.296,"_file_size": 13.557,"_docs": """These weights were trained from scratch by using TorchVision's `new training recipe<https://pytorch.org/blog/how-to-train-state-of-the-art-models-using-torchvision-latest-primitives/>`_.""",},)DEFAULT = IMAGENET1K_V1class ShuffleNet_V2_X2_0_Weights(WeightsEnum):IMAGENET1K_V1 = Weights(url="https://download.pytorch.org/models/shufflenetv2_x2_0-8be3c8ee.pth",transforms=partial(ImageClassification, crop_size=224, resize_size=232),meta={**_COMMON_META,"recipe": "https://github.com/pytorch/vision/pull/5906","num_params": 7393996,"_metrics": {"ImageNet-1K": {"acc@1": 76.230,"acc@5": 93.006,}},"_ops": 0.583,"_file_size": 28.433,"_docs": """These weights were trained from scratch by using TorchVision's `new training recipe<https://pytorch.org/blog/how-to-train-state-of-the-art-models-using-torchvision-latest-primitives/>`_.""",},)DEFAULT = IMAGENET1K_V1@register_model()
@handle_legacy_interface(weights=("pretrained", ShuffleNet_V2_X0_5_Weights.IMAGENET1K_V1))
def shufflenet_v2_x0_5(*, weights: Optional[ShuffleNet_V2_X0_5_Weights] = None, progress: bool = True, **kwargs: Any
) -> ShuffleNetV2:"""Constructs a ShuffleNetV2 architecture with 0.5x output channels, as described in`ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design<https://arxiv.org/abs/1807.11164>`__.Args:weights (:class:`~torchvision.models.ShuffleNet_V2_X0_5_Weights`, optional): Thepretrained weights to use. See:class:`~torchvision.models.ShuffleNet_V2_X0_5_Weights` below formore details, and possible values. By default, no pre-trainedweights are used.progress (bool, optional): If True, displays a progress bar of thedownload to stderr. Default is True.**kwargs: parameters passed to the ``torchvision.models.shufflenetv2.ShuffleNetV2``base class. Please refer to the `source code<https://github.com/pytorch/vision/blob/main/torchvision/models/shufflenetv2.py>`_for more details about this class... autoclass:: torchvision.models.ShuffleNet_V2_X0_5_Weights:members:"""weights = ShuffleNet_V2_X0_5_Weights.verify(weights)return _shufflenetv2(weights, progress, [4, 8, 4], [24, 48, 96, 192, 1024], **kwargs)@register_model()
@handle_legacy_interface(weights=("pretrained", ShuffleNet_V2_X1_0_Weights.IMAGENET1K_V1))
def shufflenet_v2_x1_0(*, weights: Optional[ShuffleNet_V2_X1_0_Weights] = None, progress: bool = True, **kwargs: Any
) -> ShuffleNetV2:"""Constructs a ShuffleNetV2 architecture with 1.0x output channels, as described in`ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design<https://arxiv.org/abs/1807.11164>`__.Args:weights (:class:`~torchvision.models.ShuffleNet_V2_X1_0_Weights`, optional): Thepretrained weights to use. See:class:`~torchvision.models.ShuffleNet_V2_X1_0_Weights` below formore details, and possible values. By default, no pre-trainedweights are used.progress (bool, optional): If True, displays a progress bar of thedownload to stderr. Default is True.**kwargs: parameters passed to the ``torchvision.models.shufflenetv2.ShuffleNetV2``base class. Please refer to the `source code<https://github.com/pytorch/vision/blob/main/torchvision/models/shufflenetv2.py>`_for more details about this class... autoclass:: torchvision.models.ShuffleNet_V2_X1_0_Weights:members:"""weights = ShuffleNet_V2_X1_0_Weights.verify(weights)return _shufflenetv2(weights, progress, [4, 8, 4], [24, 116, 232, 464, 1024], **kwargs)@register_model()
@handle_legacy_interface(weights=("pretrained", ShuffleNet_V2_X1_5_Weights.IMAGENET1K_V1))
def shufflenet_v2_x1_5(*, weights: Optional[ShuffleNet_V2_X1_5_Weights] = None, progress: bool = True, **kwargs: Any
) -> ShuffleNetV2:"""Constructs a ShuffleNetV2 architecture with 1.5x output channels, as described in`ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design<https://arxiv.org/abs/1807.11164>`__.Args:weights (:class:`~torchvision.models.ShuffleNet_V2_X1_5_Weights`, optional): Thepretrained weights to use. See:class:`~torchvision.models.ShuffleNet_V2_X1_5_Weights` below formore details, and possible values. By default, no pre-trainedweights are used.progress (bool, optional): If True, displays a progress bar of thedownload to stderr. Default is True.**kwargs: parameters passed to the ``torchvision.models.shufflenetv2.ShuffleNetV2``base class. Please refer to the `source code<https://github.com/pytorch/vision/blob/main/torchvision/models/shufflenetv2.py>`_for more details about this class... autoclass:: torchvision.models.ShuffleNet_V2_X1_5_Weights:members:"""weights = ShuffleNet_V2_X1_5_Weights.verify(weights)return _shufflenetv2(weights, progress, [4, 8, 4], [24, 176, 352, 704, 1024], **kwargs)@register_model()
@handle_legacy_interface(weights=("pretrained", ShuffleNet_V2_X2_0_Weights.IMAGENET1K_V1))
def shufflenet_v2_x2_0(*, weights: Optional[ShuffleNet_V2_X2_0_Weights] = None, progress: bool = True, **kwargs: Any
) -> ShuffleNetV2:"""Constructs a ShuffleNetV2 architecture with 2.0x output channels, as described in`ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design<https://arxiv.org/abs/1807.11164>`__.Args:weights (:class:`~torchvision.models.ShuffleNet_V2_X2_0_Weights`, optional): Thepretrained weights to use. See:class:`~torchvision.models.ShuffleNet_V2_X2_0_Weights` below formore details, and possible values. By default, no pre-trainedweights are used.progress (bool, optional): If True, displays a progress bar of thedownload to stderr. Default is True.**kwargs: parameters passed to the ``torchvision.models.shufflenetv2.ShuffleNetV2``base class. Please refer to the `source code<https://github.com/pytorch/vision/blob/main/torchvision/models/shufflenetv2.py>`_for more details about this class... autoclass:: torchvision.models.ShuffleNet_V2_X2_0_Weights:members:"""weights = ShuffleNet_V2_X2_0_Weights.verify(weights)return _shufflenetv2(weights, progress, [4, 8, 4], [24, 244, 488, 976, 2048], **kwargs)
 

第四步:统计训练过程中验证集准确率和loss变化

第五步:搭建WebUI:Gradio的界面

第六步:整个工程的内容

有训练代码和训练好的模型以及训练过程,提供数据,提供GUI界面代码

 项目完整文件下载请见演示与介绍视频的简介处给出:➷➷➷

PyTorch框架——基于WebUI:Gradio深度学习ShuffleNetv2神经网络蔬菜图像识别分类系统_哔哩哔哩_bilibili


http://www.ppmy.cn/ops/152538.html

相关文章

视频修复最强算法 部署笔记2025

目录 模型下载: 模型: 原版保存的视频,vs code不播放: 模型下载: Release ProPainter V0.1.0 Release sczhou/ProPainter GitHub huggingface-cli download --resume-download lixiaowen/diffuEraser --local-dir /mnt/pfs/models/huggingface/models--lixiaowen--d…

node_exporter 集成Prometheus+Grafana

一、配置Prometheus采集 nano /root/apisix-docker/example/prometheus_conf/prometheus.yml末尾添加一段- job_name: "nodeexporter"scrape_interval: 5smetrics_path: "metrics"static_configs:- targets: ["192.168.31.135:9100"]#192.168.3…

CentOS 7.9(linux) 设置 MySQL 8.0.30 开机启动详解

文章目录 一、运行级别简介二、MySQL 服务安装与运行验证三、通过 chkconfig 配置开机启动四、验证开机启动配置五、总结 一、运行级别简介 运行级别&#xff08;Runlevel&#xff09;定义了系统的运行模式&#xff0c;常见的运行级别如下&#xff1a; 运行级别描述0关机模式…

后端:MyBatis

文章目录 1. MyBatis1-1. Mybatis 工具类的封装1-2. Mybatis 通过集合或实体类传递参数-实现插入数据(增)1-3. MyBatis 实现删除数据(删)1-4. MyBatis 实现修改数据(改)1-5. MyBatis 实现查询数据(查) 2. MyBatis 配置文件中的一些标签和属性2-1.environments标签2-2. dataSour…

Python爬虫获取微店商品详情时如何设置请求头

在使用Python爬虫获取微店商品详情时&#xff0c;合理设置请求头是确保爬虫请求成功并避免被识别为爬虫的关键步骤。请求头&#xff08;Headers&#xff09;是HTTP请求的一部分&#xff0c;包含了关于请求的元数据&#xff0c;如客户端信息、请求来源、接受的数据类型等。通过设…

18.Elasticsearch 7.15 Query DSL 之 bool查询

bool查询简介 布尔查询允许使用布尔逻辑&#xff08;AND, OR, NOT&#xff09;将多个查询子句组合成复杂查询&#xff0c;是Elasticsearch查询DSL的一部分。bool 查询映射到 Lucene BooleanQuery。它使用一个或多个布尔子句构建&#xff0c;这些布尔子句包括&#xff1a; 布尔…

【Flink系列】4. Flink运行时架构

4. Flink运行时架构 4.1 系统架构 Flink运行时架构——Standalone会话模式为例 1&#xff09;作业管理器&#xff08;JobManager&#xff09; JobManager是一个Flink集群中任务管理和调度的核心&#xff0c;是控制应用执行的主进程。也就是说&#xff0c;每个应用都应该被…

【Python】笔试面试题之生成器、闭包、字典

文章目录 一、生成器是什么1. 最简单的生成器2. 在函数中使用yield关键字 二、闭包是什么&#xff1f;怎么理解&#xff1f;1. 案例12. 案例2&#xff1a;实现项目的日志处理3. 案例3&#xff1a;装饰器就是一种闭包4. 总结 三、Python中字典的底层是怎么实现的1. 相关概念2. P…