基于Pytorch框架的深度学习ShufflenetV2神经网络十七种猴子动物识别分类系统源码

news2024/9/20 15:38:16

 第一步:准备数据

17种猴子动物数据:

self.class_indict = ["白头卷尾猴", "弥猴", "山魈", "松鼠猴", "叶猴", "银色绒猴", "印度乌叶猴", "疣猴", "侏绒","白秃猴", "赤猴", "滇金丝猴", "狒狒", "黑色吼猴", "黑叶猴", "金丝猴", "懒猴"],总共有1800张图片,每个文件夹单独放一种数据

第二步:搭建模型

本文选择一个ShufflenetV2网络,其原理介绍如下:

shufflenet v2是旷视提出的shufflenet的升级版本,并被ECCV2018收录。论文说在同等复杂度下,shufflenet v2比shufflenet和mobilenetv2更准确。shufflenet v2是基于四条准则对shufflenet v1进行改进而得到的,这四条准则如下:

(G1)同等通道大小最小化内存访问量 对于轻量级CNN网络,常采用深度可分割卷积(depthwise separable convolutions),其中点卷积( pointwise convolution)即1x1卷积复杂度最大。这里假定输入和输出特征的通道数分别为C1和C2,经证明仅当C1=C2时,内存使用量(MAC)取最小值,这个理论分析也通过实验得到证实。更详细的证明见参考【1】

(G2)过量使用组卷积会增加MAC 组卷积(group convolution)是常用的设计组件,因为它可以减少复杂度却不损失模型容量。但是这里发现,分组过多会增加MAC。更详细的证明见参考【1】

(G3)网络碎片化会降低并行度 一些网络如Inception,以及Auto ML自动产生的网络NASNET-A,它们倾向于采用“多路”结构,即存在一个lock中很多不同的小卷积或者pooling,这很容易造成网络碎片化,减低模型的并行度,相应速度会慢,这也可以通过实验得到证明。

(G4)不能忽略元素级操作 对于元素级(element-wise operators)比如ReLU和Add,虽然它们的FLOPs较小,但是却需要较大的MAC。这里实验发现如果将ResNet中残差单元中的ReLU和shortcut移除的话,速度有20%的提升。

根据前面的4条准则,作者分析了ShuffleNet v1设计的不足,并在此基础上改进得到了ShuffleNetv2,两者模块上的对比下图所示

第三步:训练代码

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

2)训练代码:

import os
import math
import argparse

import torch
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
import torch.optim.lr_scheduler as lr_scheduler

from model import shufflenet_v2_x1_0
from my_dataset import MyDataSet
from utils import read_split_data, train_one_epoch, evaluate


def main(args):
    device = torch.device(args.device if torch.cuda.is_available() else "cpu")

    print(args)
    print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/')
    tb_writer = SummaryWriter()
    if os.path.exists("./weights") is False:
        os.makedirs("./weights")

    train_images_path, train_images_label, val_images_path, val_images_label = read_split_data(args.data_path)

    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])])}

    # 实例化训练数据集
    train_dataset = MyDataSet(images_path=train_images_path,
                              images_class=train_images_label,
                              transform=data_transform["train"])

    # 实例化验证数据集
    val_dataset = MyDataSet(images_path=val_images_path,
                            images_class=val_images_label,
                            transform=data_transform["val"])

    batch_size = args.batch_size
    nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])  # number of workers
    print('Using {} dataloader workers every process'.format(nw))
    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True,
                                               pin_memory=True,
                                               num_workers=nw,
                                               collate_fn=train_dataset.collate_fn)

    val_loader = torch.utils.data.DataLoader(val_dataset,
                                             batch_size=batch_size,
                                             shuffle=False,
                                             pin_memory=True,
                                             num_workers=nw,
                                             collate_fn=val_dataset.collate_fn)

    # 如果存在预训练权重则载入
    model = shufflenet_v2_x1_0(num_classes=args.num_classes).to(device)
    if args.weights != "":
        if os.path.exists(args.weights):
            weights_dict = torch.load(args.weights, map_location=device)
            load_weights_dict = {k: v for k, v in weights_dict.items()
                                 if model.state_dict()[k].numel() == v.numel()}
            print(model.load_state_dict(load_weights_dict, strict=False))
        else:
            raise FileNotFoundError("not found weights file: {}".format(args.weights))

    # 是否冻结权重
    if args.freeze_layers:
        for name, para in model.named_parameters():
            # 除最后的全连接层外,其他权重全部冻结
            if "fc" not in name:
                para.requires_grad_(False)

    pg = [p for p in model.parameters() if p.requires_grad]
    optimizer = optim.SGD(pg, lr=args.lr, momentum=0.9, weight_decay=4E-5)
    # Scheduler https://arxiv.org/pdf/1812.01187.pdf
    lf = lambda x: ((1 + math.cos(x * math.pi / args.epochs)) / 2) * (1 - args.lrf) + args.lrf  # cosine
    scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)

    for epoch in range(args.epochs):
        # train
        mean_loss = train_one_epoch(model=model,
                                    optimizer=optimizer,
                                    data_loader=train_loader,
                                    device=device,
                                    epoch=epoch)

        scheduler.step()

        # validate
        acc = evaluate(model=model,
                       data_loader=val_loader,
                       device=device)

        print("[epoch {}] accuracy: {}".format(epoch, round(acc, 3)))
        tags = ["loss", "accuracy", "learning_rate"]
        tb_writer.add_scalar(tags[0], mean_loss, epoch)
        tb_writer.add_scalar(tags[1], acc, epoch)
        tb_writer.add_scalar(tags[2], optimizer.param_groups[0]["lr"], epoch)

        torch.save(model.state_dict(), "./weights/model-{}.pth".format(epoch))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--num_classes', type=int, default=17)
    parser.add_argument('--epochs', type=int, default=100)
    parser.add_argument('--batch-size', type=int, default=4)
    parser.add_argument('--lr', type=float, default=0.01)
    parser.add_argument('--lrf', type=float, default=0.1)

    # 数据集所在根目录
    # https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
    parser.add_argument('--data-path', type=str,
                        default=r"G:\demo\data\monkeys\training")

    # shufflenetv2_x1.0 官方权重下载地址
    # https://download.pytorch.org/models/shufflenetv2_x1-5666bf0f80.pth
    parser.add_argument('--weights', type=str, default='./shufflenetv2_x1-5666bf0f80.pth',
                        help='initial weights path')
    parser.add_argument('--freeze-layers', type=bool, default=False)
    parser.add_argument('--device', default='cuda:0', help='device id (i.e. 0 or 0,1 or cpu)')

    opt = parser.parse_args()

    main(opt)

第四步:统计正确率

第五步:搭建GUI界面

第六步:整个工程的内容

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

代码的下载路径(新窗口打开链接):基于Pytorch框架的深度学习ShufflenetV2神经网络十七种猴子动物识别分类系统源码

有问题可以私信或者留言,有问必答

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

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

相关文章

DDR、LPDDR和GDDR的区别

1、概况 以DDR开头的内存适用于服务器、云计算、网络、笔记本电脑、台式机和消费类应用,支持更宽的通道宽度、更高的密度和不同的形状尺寸。 以LPDDR开头的内存适合面向移动和汽车这些对规格和功耗非常敏感的领域,提供更窄的通道宽度和多种低功耗运行状态…

node.js学习P3-P10

P3 npm package.json(package解读npm工具换镜像源) 一个package.json文件可以的作用 作为一个描述文件,描述了你的项目依赖哪些包 ,用来干什么的允许我们使用“语义版本规则”,指明你项目依赖的版本让你的构建更好的…

cin-getline缓存区

更多资源请关注纽扣编程微信公众号 cin.sync()清除缓存区 如果需要输入如下内容 3 This is C language. This is JAVA language. This is Python language. 写如下程序 #include<bits/stdc.h> using namespace std; string str[100]; int main(){int n;cin>&…

【Pandas】配合Numpy做数据异常值处理

1.四分卫间距确定数据范围 numpy.quantile(a, q, axisNone, outNone, overwrite_inputFalse, methodlinear, keepdimsFalse, *, interpolationNone)[source]计算指定轴的n分位数 参数q给定指定的几分位数&#xff0c;范围[0,1] import numpy as np import pandas as pd def …

每日一题——Python实现PAT甲级1029 Median(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的方法 代码功能和结构点评 时间复杂度分析 空间复杂度分析 优化建议 我要更强…

【Text2SQL 论文】IncSQL:通过增量式生成 action 序列来得到 SQL

论文&#xff1a;IncSQL: Training Incremental Text-to-SQL Parsers with Non-Deterministic Oracles ⭐⭐⭐ ICLR 2019&#xff0c;arXiv:1809.05054, Microsoft Research 一、论文速读 本文提出了 IncSQL&#xff0c;一个使用 Non-Deterministic Oracles 思路的增量式 Text…

从零开始打造教育APP:在线教育系统源码与开发流程

很多人疑问&#xff0c;应该如何从零开始打造一个在线教育APP&#xff1f;今天&#xff0c;小编将详细为大家讲解在线教育系统的源码与开发流程。 一、需求分析 对于在线教育APP&#xff0c;需要要明确以下几点&#xff1a; 1.目标用户&#xff1a;明确APP的用户群体&#xf…

字符串和字符串函数(1)

前言&#xff1a; 字符串在C语言中比较特别&#xff0c;没有单另的字符串类型&#xff0c;想要初始化字符串必须用字符变量的数组初始化&#xff0c;但是在C语言标准库函数中提供了大量能对字符串进行修改的函数&#xff0c;比如说可以实现字符串的的拷贝&#xff0c;字符串的追…

判断dom元素是否滚动到底、是否在可视区域

概览 我们日常开发中&#xff0c;在面对懒加载、虚拟列表需求时&#xff0c;经常需要判断dom元素是否滚动到底、是否在可视区域。但是由于涉及的属性太多了&#xff0c;比如scrollTop、clientHeight、scrollHeight、getBoundingClientRect()等属性&#xff0c;现根据这两个场景…

Docker环境安装并使用Elasticsearch

1、拉取es docker pull elasticsearch:7.10.12、查看镜像 docker images3、启动es docker run -d --name esearch -p 9200:9200 -p 9300:9300 elasticsearch:7.10.14、如果启动ES时出现一下问题 Unable to find image docker.elastic.co/elasticsearch/elasticsearch:7.10.…

基于springboot+vue的班级综合测评管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

台灯的功能作用有哪些?看完就知道台灯怎么选!

作为一位家长&#xff0c;我深刻意识到保护孩子眼部健康的重要性。随着科技的飞速发展&#xff0c;孩子们越来越多地使用电子设备&#xff0c;如平板电脑、手机和电视&#xff0c;长时间盯着屏幕成为了他们日常生活的一部分。然而&#xff0c;这些屏幕发出的蓝光和闪烁的光线&a…

C++的第一道门坎:类与对象(一)

1.面向过程与面向对象 1.1面向过程 我们之前学习的C语言就是一种面向过程的语言&#xff0c;面向过程的语言强调的是具体实现的过程&#xff0c;一般用函数来具体实现。我们用面向过程的思想&#xff0c;就可以把炒菜分为以下几个步骤: 1.2面向对象 而对于面向对象的语言而言…

duckdb 插件机制研究

本文研究 duckdb 内置的 extensions 工作机制。 插件架构 在 duckdb 源码内&#xff0c;内置了一组原生插件&#xff0c;位于顶层 extension 目录下&#xff1a; 除此之外&#xff0c;还支持 Out-of-Tree Extension&#xff0c;简单说就是独立的插件&#xff0c;不是集成在源…

零代码创建属于自己的情伤治愈者

前言 在这个社会物质文明生活发展迅速的年代&#xff0c;很多人都有心底里难以说出的痛楚&#xff0c;他们往往都与情伤相关&#xff0c;面对这样的情况&#xff0c;我们结合文心智能体设计出一款适合所有人的情伤治愈工具 体验智能体 文心智能体平台是一款基于自然语言处理和…

【鱼眼镜头10】等距Equidistant模型的Kannala-Brandt模型,opencv的鱼眼标定使用的模型。kalibr中的 pinhole + equidistant 都是指该模型。

Kannala Brandt 模型 / opencv中的fisheye / kalibr中的 pinhole equidistant 都是指该模型。 opencv https://docs.opencv.org/4.x/db/d58/group__calib3d__fisheye.html kalibr https://github.com/ethz-asl/kalibr/wiki/supported-models 在之前的博客【鱼眼镜头1】鱼眼…

linux centos磁盘清理相关

清理磁盘流程 1、查看磁盘挂载路径及使用率 df -h2、查看当前文件下文件大小 du -sh *3、制空文件内容 > 文件名 ###制空当前文件内容&#xff0c;直接清0 列子 >access.loglinux操作系统中&#xff0c;经常会遇到磁盘空间满的问题。遇到这样的问题&#xff0c;先查下…

实战 | 使用YoloV8实例分割识别猪的姿态(含数据集)

导 读 本文主要介绍如何使用YoloV8实例分割识别猪的姿态&#xff08;含数据集&#xff09;。 背景介绍 在本文中&#xff0c;我将介绍如何使用YoloV8在猪的自定义数据集上进行实例分割&#xff0c;以识别和跟踪它们的不同姿态。 数据集 使用的数据集来源于Kokkenborg Aps&…

【智能算法】青蒿素优化算法(AO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;C Yuan受到青蒿素药物治疗疟疾过程启发&#xff0c;提出了青蒿素优化算法&#xff08;Artemisinin Optimization, AO&#xff09;。 2.算法原理 2.1算法思想 AO灵感来…

在C++中自定义命名空间,在命名空间中定义string变量,同时定义一个函数实现单词逆置

代码 #include <iostream> #include <cstring> using namespace std; namespace my_space {string s;void reverse(string s);//定义逆置函数 } using namespace my_space; void my_space::reverse(string s){int lens.size();int i0;int jlen-1;while(i<j){//…