首页 > 分享 > 基于深度学习的花卉识别

基于深度学习的花卉识别

1、数据集

       春天来了,我在公园的小道漫步,看着公园遍野的花朵,看起来真让人心旷神怡,一周工作带来的疲惫感顿时一扫而光。难得一个糙汉子有闲情逸致俯身欣赏这些花朵儿,然而令人尴尬的是,我一朵都也不认识。那时我在想,如果有一个花卉识别软件,可以用手机拍一下就知道这是一种什么花朵儿,那就再好不过了。我不知道市场上是否有这样一种软件,但是作为一个从事深度学习的工程师,我马上知道了怎么做,最关键的不是怎么做,而是数据采集。住所附近就是大型公园,一年司机繁花似锦,得益于此,我可以在闲暇时间里采集到大量的花卉数据。本数据集由本人亲自使用手机进行拍摄采集,原始数据集包含了27万张图片,图片的尺寸为1024x1024,为了方便储存和传输,把原图缩小为224x224。采集数据是一个漫长的过程,因此数据集的发布采用分批发布的形式,也就是每采集够16种花卉,就发布一次数据集。每种花卉的图片数量约为2000张,每次发布的数据集的图片数量约为32000张,每次发布的数据集包含的花卉种类都不一样。目前花卉的种类只有48种,分为三批发布,不过随着时间的推移,采集到的花卉越来越多。这里就把数据集分享出来,供各位人工智能算法研究者使用。以下是花卉数据集的简要介绍和下载地址。
(1)花卉数据集01(数据集+训练代码下载地址)
       花卉数据集01,采集自2022年,一共16种花卉,数据集大小为32000张,图片大小为224x224的彩色图像。数据集包含的花卉名称为:一年蓬,三叶草,三角梅,两色金鸡菊,全叶马兰,全缘金光菊,剑叶金鸡菊,婆婆纳,油菜花,滨菊,石龙芮,绣球小冠花,蒲公英,蓝蓟,诸葛菜,鬼针草。数据集的缩略图如下:
图1 花卉数据集01
(2)花卉数据集02(数据集+训练源码下载地址)
       花卉数据集02,采集与2023年,一共16种花卉,每种花卉约2000张,总共32000,图片大小为224x224。数据集包含的花卉有:千屈菜,射干,旋覆花,曼陀罗,桔梗,棣棠,狗尾草,狼尾草,石竹,秋英,粉黛乱子草,红花酢浆草,芒草,蒲苇,马鞭草,黄金菊。数据集缩略图如下:
图2 花卉数据集02
(3)花卉数据集3(数据集+训练源码下载地址)
       花卉数据集03,采集与2023年,一共16种花卉,每种花卉约2000张,总共32000,图片大小为224x224。数据集包含的花卉有:北香花介,大花耧斗菜,小果蔷薇,小苜蓿,小蜡,泽珍珠菜,玫瑰,粉花绣线菊,线叶蓟,美丽月见草,美丽芍药,草甸鼠尾草,蓝花鼠尾草,蛇莓,长柔毛野豌豆,高羊茅。数据集缩略图如下:
图3 花卉数据集3

2、图片分类模型

       为了研究不同图片分类模型对于花朵的分类效果,以及图片分类模型在不同硬件平台的推理速度,这里分别使用目前主流的22种图片分类模型进行训练,并在cpu平台和GPU平台进行部署测试。这些模型是如下:

resnet系列:resnet18、resnet34、resnet50、resnet101、resnet152。vgg系列:vgg11、vgg13、vgg6、vgg19。squeezenet系列:squeezenet_v1、squeezenet_v2、squeezenet_v3。mobilenet系列:mobilenet_v1、mobilenet_v2。inception系列:inception_v1、inception_v2、inception_v3。其他系列:alexnet、lenet、mnist、tsl16、zfnet。

以上模型的训练代码基于pytorch架构,内置集成22了种模型,可进行傻瓜式训练。以下的代码块为训练代码的主脚本,完整的训练代码以及数据集请在此链接下载:源码下载链接。

import torch import torch.nn as nn import torch.optim as optim from utils.dataloader import CustomImageDataset from torch.utils.data import DataLoader from utils.build_model import build_model import argparse import time import os if __name__ == '__main__': parser =argparse.ArgumentParser(description='图片分类模型训练') parser.add_argument('-input_shape', type=tuple,default=(3,224,224),help='模型输入的通道数、高度、宽度') parser.add_argument('-train_imgs_dir', type=str,default='dataset/train',help='训练集目录') parser.add_argument('-test_imgs_dir', type=str,default='dataset/test',help='测试集目录') parser.add_argument('-classes_file', type=str,default='dataset/classes.txt',help='类别文件') parser.add_argument('-epochs', type=int,default=50,help='迭代次数') parser.add_argument('-batch_size', type=int,default=64,help='批大小,根据显存大小调整') parser.add_argument('-init_weights', type=str,default="init_weights/squeezenet_v1.pth",help='用于初始化的权重,请确保初始化的权重和训练的模型相匹配') parser.add_argument('-optim', type=str,default="adam",help='优化器选择,可选sgd或者adam. sgd优化器训练效果较好,但参数比较难调节,不好收敛') parser.add_argument('-lr', type=float,default=0.0001, help='初始学习率,此参数对模型训练影响较大,如果选择不合适,模型甚至不收敛. 如果遇到模型训练不收敛(损失函数不下降,准确度很低),可以尝试调整学习率. resnet系列推荐优化器选择sgd,学习率设0.001;vgg系列优化器推荐adam,学习率为0.0001,其他模型优化器选择adam,推荐学习率为0.0002') parser.add_argument('-model_name', type=str,default='squeezenet_v1', help='模型名称,可选resnet18/resnet34/resnet50/resnet101/resnet152 /alexnet/lenet/zfnet/tsl16/mnist vgg11/vgg13/vgg16,vgg19 squeezenet_v1/squeezenet_v2/squeezenet_v3 inception_v1/inception_v2/inception_v3 mobilenet_v1/mobilenet_v2/ ') parser.add_argument('-argument', type=bool,default=True,help='是否在训练时开启数据增强模式') args = parser.parse_args() print("模型:",args.model_name) device = ( "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" ) classes=[] try: with open(args.classes_file,"rt",encoding="ANSI")as f: for line in f: classes.append(line.strip()) except: with open(args.classes_file,"rt",encoding="UTF-8")as f: for line in f: classes.append(line.strip()) num_class=len(classes) model=build_model(args.model_name,args.input_shape,num_class) if os.path.exists(args.init_weights): try: model.load_state_dict(args.init_weights) except: model.weights_init() print("参数初始化失败!请确保初始化参数与模型相一致.") else: model.weights_init() print("没有找到名称为%s的权重文件,模型将跳过参数初始化"%(args.init_weights)) model=model.to(device) # Create data loaders. training_data=CustomImageDataset(args.train_imgs_dir,classes,args.argument) test_data=CustomImageDataset(args.test_imgs_dir,classes,False) train_dataloader = DataLoader(training_data, batch_size=args.batch_size,shuffle=True) test_dataloader = DataLoader(test_data, batch_size=args.batch_size) loss_fn=nn.CrossEntropyLoss() if args.optim=="adam": optimizer=optim.Adam(model.parameters(), lr=args.lr) else: optimizer=optim.SGD(model.parameters(), lr=args.lr,momentum=0.9,weight_decay=0.0005) scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer,args.epochs) def train(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) model.train() start=time.time() for batch, (X, y) in enumerate(dataloader): X, y = X.to(device), y.to(device) # Compute prediction error optimizer.zero_grad() pred = model(X) loss = loss_fn(pred, y) # Backpropagation loss.backward() optimizer.step() scheduler.step() if batch % 100 == 0: loss, current = loss.item(), (batch + 1) * len(X) end=time.time() print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}] time: {end-start:>3f}s") def test(dataloader, model, loss_fn): size = len(dataloader.dataset) num_batches = len(dataloader) model.eval() test_loss, correct = 0, 0 with torch.no_grad(): start=time.time() for X, y in dataloader: X, y = X.to(device), y.to(device) pred = model(X) test_loss += loss_fn(pred, y).item() correct += (pred.argmax(1) == y).type(torch.float).sum().item() end=time.time() test_loss /= num_batches correct /= size print(f"Test Error: n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} , Time: {end-start:>3f}sn") return correct best_accuracy=0 for t in range(args.epochs): print(f"Epoch {t+1}n-------------------------------") train(train_dataloader, model, loss_fn, optimizer) current_accuracy=test(test_dataloader, model, loss_fn) if current_accuracy>best_accuracy: best_accuracy=current_accuracy torch.save(model,"weights/%s_best_accuracy.pth"%(args.model_name)) torch.save(model,"weights/%s_last_accuracy_%.2f.pth"%(args.model_name,current_accuracy)) print("Done!")

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129

3、图片分类模型评估

       分别训练了22种模型,图片为224x224的RGB图像。将约96000张图片划分为训练集和测试集,其中测试集占10%,一共9600张,训练集90%,一共86400张。训练充分后,对各种模型的top1、top2、top3、top4、top5准确度进行评估,并分别在cpu平台(intel i9)和gpu平台(RTX 3090)进行推理速度的测试。模型性能评估以及推理速度测试结果如表1所示。

表1 模型性能评估以及推理速度测试结果

模型参数量 [M]计算量 [G]GPU速度[FPS]CPU速度[FPS]Top1准确度[%]Top2准确度[%]Top3准确度[%]Top4准确度[%]Top5准确度[%]resnet1811.193.64557.30204.0598.8499.7099.8699.9399.96resnet3421.307.35347.39104.3598.6499.7499.8699.9399.96resnet5034.9410.31295.2468.1998.6799.6699.8699.9499.97resnet10153.9017.77171.8441.2798.6199.6499.8399.9099.94resnet15268.4123.46130.2131.2098.4499.5899.8699.9299.96vgg11128.9615.25462.2430.0092.8897.3598.6999.2699.48vgg13129.1522.67411.5522.2795.1898.2299.2199.5599.73vgg16134.4630.99340.3420.1495.3598.4899.2999.5099.60vgg19139.7739.33292.5116.7194.8998.2599.0199.3999.62mobilenet_v13.251.16942.09506.4297.4599.4499.7199.8399.90mobilenet_v24.030.91489.69386.2095.9998.9899.5299.7599.81inception_v16.023.20343.56203.4395.8098.7999.4499.7499.83inception_v27.853.34291.10165.4998.3099.5499.8099.8599.90inception_v321.877.65136.2571.8999.0599.8199.9299.9599.97squeezenet_v10.761.61758.27362.2297.4499.3699.6999.8199.86squeezenet_v20.761.61704.60360.7597.2799.2399.6799.8099.85squeezenet_v31.102.37658.07267.2898.2899.5499.7799.8599.89mnist_net214.4551.37189.8110.1389.4796.2098.1498.9199.28AlexNet17.692.35858.92211.7396.2098.7999.4999.6999.76LeNet78.450.941041.7576.1284.8693.7596.5597.9498.70TSL16116.9523.56381.6324.0995.6198.4099.1599.5399.69ZF_Net72.092.68351.8782.6896.5899.0399.4799.6899.80

       从表一展示的结果来看,面对48种花卉的分类任务:如果只关心Top5分类准确度,那么这些模型均能达到98%以上的分类准确度,大部分模型的Top5准确度都能达到99%以上,对于实际应用而言,花卉分类程序通常会给出5个备选项,这样的话,只要5个备选项里边存在一个正确选项,就可以认为花卉分类是成功的。当然,如果追求单一选项的准确性,resnet系列模型、inception系列、squeezenet系列模型,在Top1分类准确度上表现不俗,可以达到97%以上的准确度。通常来说,可以工程化的图片分类模型,不仅仅要求其具备良好的分类准确度,还对其推理速度有一定的要求。表1的推理速度测试数据,分别在Intel i9 CPU平台和英伟达RTX 3090 GPU平台进行测试,推理用的软件接口是onnx推理架构,测试的策略是逐一对1000张224x224的彩色图片输送到模型中进行推理,统计其总的推理时间,然后计算平均推理帧率。从表1的数据可以得知,GPU平台的推理速度要比CPU平台的推理的速度快很多,而且在GPU平台推理帧率高的模型,在CPU平台的推理帧率未必高,反之亦然,也就是说,模型推理帧率的排名,跟硬件平台是有关的。在GPU平台上推理帧率比较靠前的模型是squeezenet系列、mobilenet系列,以及alexnet和lenet;在CPU平台上推理帧率比较靠前的模型是squeezenet系列、mobilenet系列、alexnet、inception_v1、resnet18。综合来说,squeezenet系列、mobilenet系列得分是最高的,因为他们在分类准确度上表现优秀,并且在GPU和CPU平台上的推理帧率都变现不错,而且模型的参数量很小,适合在线部署和嵌入式部署,所以这些模型应当优先选择。另外,从评估和测试的结果来看,还可以得到以下几个结论:

对于可以并行计算的硬件平台来说,比如GPU、NPU以及一些具有批处理能力的CPU,模型的推理帧率跟模型的参数量和计算量没有绝对的关联性,更多的是跟模型的结构有关,如果模型适合于并行计算,那么即使模型具有较大的计算量,其推理速度也可以很快;对于串行执行的计算硬件来说,比如常规指令的CPU,模型的推理速度跟模型的计算量的是线性相关的,也就是说计算量越大,推理帧率越低;适合GPU平台部署的模型未必适合在CPU平台上部署,所以模型的选择要根据最终的部署平台而定。

4、总结

       花卉数据集共包括96000张图片,囊括了48种花卉的类别,其中10%为测试集,90%为训练集。图片的大小为224x224,通道数为3。一共使用了22种模型进行训练,通过模型评估和硬件平台部署测试得出结论:squeezenet_v1、squeezenet_v2、squeezenet_v3、mobilenet_v1、mobilenet_v2几个模型,具有参数量小,计算量小,分类准确度高的优点,并且在GPU平台和CPU平台上推理速度较快,适合在各种平台上部署,特别是适合移动端和嵌入式的部署。

相关知识

基于深度学习的花卉识别系统开发
基于深度学习的花卉识别研究
基于深度迁移学习模型的花卉种类识别
2022年基于深度学习的花卉种类识别研究2000字(8篇).docx
基于深度学习的百合花种类识别研究
基于深度学习和迁移学习的识花实践
基于深度学习的花卉种类识别研究2000字(8篇).docx
深度学习之基于Tensorflow卷积神经网络花卉识别系统
038基于深度学习的花卉自动识别pyqt界面
深度学习机器学习卷积神经网络的花卉识别花种类识别

网址: 基于深度学习的花卉识别 https://m.huajiangbk.com/newsview114136.html

所属分类:花卉
上一篇: 花png图片
下一篇: 红色装饰素材