基于PaddleHub实现桃子分类

简介: 基于PaddleHub实现桃子分类

一、案例背景


随着时代的快速发展,现今社会进入了人工智能时代。人工智能的力量,给中国农业安上了加速器。现今,人们可以开始利用卫星遥感技术去看庄稼长势,水果分拣可以通过分拣系统来辅助完成,灌溉施肥通过机械化自动进行……

具体以水果分拣场景为例,大型的水果种植园每到丰收的季节,为了分拣水果,会雇佣大量的分拣工人。这会导致产生大量人力成本。同时,人工分拣水平层次不一,使得农场主收益受到很大影响。然而,如今智能水果分拣系统的出现,可以自动根据设置的水果等农作物的品级进行分拣,降低人力成本,提高处理效率,提供分拣的准确性,那么问题来了。

如何搭建一套完整的智能水果分拣系统?巧了,PaddleHub正好可以帮你搞定完整的系统建立!

今天我们带大家利用PaddleHub搭建ResNet50_vd网络,实现桃子分类,让大家亲自感受图像分类的魅力。

本实践旨在通过桃子分类来让大家对图像分类问题有一个初步了解,同时理解和掌握如何使用PaddleHub搭建一个经典的卷积神经网络。

本案例整体结构如下所示:

image.png


二、环境搭建与准备


安装PaddlePaddle: 参考快速安装,aistudio已经预先安装好了PaddlePaddle。

安装PaddleHub:为了保证最新版本稳定,建议执行以下命令安装。

!pip install paddlehub==2.0.4 -i https://pypi.tuna.tsinghua.edu.cn/simple


三、数据准备


在本次教程提供的数据文件中,已经提供了分割好的训练集、验证集、测试集的索引和标注文件。如果用户利用PaddleHub迁移CV类任务使用自定义数据,则需要自行切分数据集,将数据集切分为训练集、验证集和测试集。需要三个文本文件来记录对应的图片路径和标签,此外还需要一个标签文件用于记录标签的名称。相关方法可参考自定义数据集。该桃子分拣系统按照桃子品相分为4个等级。

image.png

其中:

  • R0为最好:颜色鲜红且果实较大
  • B1为次优:果实较大,颜色较红
  • M2为中等:果实中等
  • S3为较差:果实个头比较小


数据分为训练集、验证集和测试集,训练集为每种桃子各1500张,验证集每种桃子各100张,测试集每种桃子为15张。

├─data: 数据目录  
  ├─train_list.txt:训练集数据列表  
  ├─test_list.txt:测试集数据列表 
  ├─validate_list.txt:验证集数据列表 
  ├─label_list.txt:标签列表 
  └─……  

训练集、验证集和测试集的数据列表文件的格式如下,列与列之间以空格键分隔。

图片1路径 图片1标签 
图片2路径 图片2标签 
...

label_list.txt的格式如下:

分类1名称 
分类2名称 
...

随后进行数据集的解压:

!unzip -q -o ./data/data67225/peach.zip -d ./work

准备好数据后即可使用PaddleHub完成数据读取器的构建,实现方法如下所示:构建数据读取Python类,并继承paddle.io.Dataset这个类完成数据读取器构建。在定义数据集时,需要预先定义好对数据集的预处理操作,并且设置好数据模式。在数据集定义中,需要重新定义__init____getitem____len__三个部分。示例如下:

#coding:utf-8
import os
import paddle
import paddlehub as hub
class DemoDataset(paddle.io.Dataset):
    def __init__(self, transforms, num_classes=4, mode='train'):  
        # 数据集存放位置
        self.dataset_dir = "./work/peach-classification"  #dataset_dir为数据集实际路径,需要填写全路径
        self.transforms = transforms
        self.num_classes = num_classes
        self.mode = mode
        if self.mode == 'train':
            self.file = 'train_list.txt'
        elif self.mode == 'test':
            self.file = 'test_list.txt'
        else:
            self.file = 'validate_list.txt'
        self.file = os.path.join(self.dataset_dir , self.file)
        self.data = []
        with open(self.file, 'r') as f:
            for line in f.readlines():
                line = line.strip()
                if line != '':
                    self.data.append(line)
    def __getitem__(self, idx):
        img_path, grt = self.data[idx].split(' ')
        img_path = os.path.join(self.dataset_dir, img_path)
        im = self.transforms(img_path)
        return im, int(grt)
    def __len__(self):
        return len(self.data)

将训练数据输入模型之前,我们通常还需要对原始数据做一些数据处理的工作,比如数据格式的规范化处理,或增加一些数据增强策略。

构建图像分类模型的数据读取器,负责将桃子dataset的数据进行预处理,以特定格式组织并输入给模型进行训练。

如下数据处理策略,只做了三种操作:

1.指定输入图片的尺寸,并将所有样本数据统一处理成该尺寸。

2.对输入图像进行裁剪,并且保持图片中心点不变。

3.对所有输入图片数据进行归一化处理。

对数据预处理及加载数据集的示例如下:

import paddlehub.vision.transforms as T
transforms = T.Compose(
        [T.Resize((256, 256)),
         T.CenterCrop(224),
         T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])],
        to_rgb=True)
peach_train = DemoDataset(transforms)
peach_validate =  DemoDataset(transforms, mode='val')
peach_test =  DemoDataset(transforms, mode='test')

PaddleHub提供了丰富的数据预处理方式,具体可以参见预处理


四、模型准备


我们要在PaddleHub中选择合适的预训练模型来Fine-tune,由于桃子分类是一个图像分类任务,这里采用Resnet50模型,并且是采用ImageNet数据集预训练过的版本。这个预训练模型是在图像任务中的一个“万金油”模型,Resnet是目前较为有效的处理图像的网络结构,50层是一个精度和性能兼顾的选择,而ImageNet又是计算机视觉领域公开的最大的分类数据集。所以,在不清楚选择什么模型好的时候,可以优先以这个模型作为baseline。


使用PaddleHub加载ResNet50模型,十分简单,只需一行代码即可实现。关于更多预训练模型信息参PaddleHub模型介绍

#安装预训练模型
!hub install resnet50_vd_imagenet_ssld==1.1.0

# 加载模型
import paddlehub as hub
model = hub.Module(name='resnet50_vd_imagenet_ssld', label_list=["R0", "B1", "M2", "S3"])


五、模型训练


本案例中,我们使用Adam优化器,Adam优化器由Kingma和Lei Ba两位学者在2014年12月提出。对梯度的一阶矩估计(First Moment Estimation,即梯度的均值)和二阶矩估计(Second Moment Estimation,即梯度的未中心化的方差)进行综合考虑,计算出更新步长。具有实现简单,计算高效,对内存需求少,参数的更新不受梯度的伸缩变换影响, 超参数具有很好的解释性,且通常无需调整或仅需很少的微调等优点。我们将学习率设置为0.001,训练10个epochs。

from paddlehub.finetune.trainer import Trainer
import paddle
optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
trainer = Trainer(model, optimizer, checkpoint_dir='img_classification_ckpt', use_gpu=True) 
trainer.train(peach_train, epochs=10, batch_size=16, eval_dataset=peach_validate, save_interval=1)

其中paddle.optimizer.Adam:

  • learning_rate: 全局学习率。默认为1e-3;
  • parameters: 待优化模型参数。


运行配置


Trainer 主要控制Fine-tune的训练,包含以下可控制的参数:

  • model: 被优化模型;
  • optimizer: 优化器选择;
  • use_vdl: 是否使用vdl可视化训练过程;
  • checkpoint_dir: 保存模型参数的地址;
  • compare_metrics: 保存最优模型的衡量指标;

trainer.train 主要控制具体的训练过程,包含以下可控制的参数:

  • train_dataset: 训练时所用的数据集;
  • epochs: 训练轮数;
  • batch_size: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size;
  • num_workers: works的数量,默认为0;
  • eval_dataset: 验证集;
  • log_interval: 打印日志的间隔, 单位为执行批训练的次数。
  • save_interval: 保存模型的间隔频次,单位为执行训练的轮数。

当Fine-tune完成后,我们使用模型来进行预测,实现如下:


六、模型评估


这里我们使用测试集来评估训练完成的模型。

# 模型评估
trainer.evaluate(peach_test, 16)


七、模型预测


这里我们使用训练完成的模型来预测测试集中的一张图片,观察预测结果与真实结果是否一致。

import paddle
import paddlehub as hub
from PIL import Image
import matplotlib.pyplot as plt
img_path = './work/peach-classification/test/M2/0.png'
img = Image.open(img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
label = img_path.split('/')[-2]
result = model.predict([img_path])
print("桃子的真实类别为: {},被预测为:{}".format(label, result))

以上为加载模型后实际预测结果(这里只测试了一张图片),返回的是预测的实际效果,可以看到我们传入待预测的是M2类别的桃子照片,经过Fine-tune之后的模型预测的效果也是M2,由此成功完成了桃子分类的迁移学习。


八、模型部署


由于AIStudio不支持ip访问,以下代码仅做示例,如有需要,请在本地机器运行。

想用我们自己训练的分拣桃子的网络参数,先配置config.json文件:

{
  "modules_info": {
    "resnet50_vd_imagenet_ssld": {
      "init_args": {
          "version": "1.1.0",
          "label_list":["R0", "B1", "M2", "S3"],
          "load_checkpoint": "img_classification_ckpt/best_model/model.pdparams"
      },
      "predict_args": {
          "batch_size": 1
      }
    }
  },
  "port": 8866,
  "gpu": "0"
}

借助 PaddleHub,服务器端的部署也非常简单,直接用一条命令行在服务器启动resnet50分类模型就行了:

$ hub serving start --config config.json

是的,在服务器端这就完全没问题了。相比手动配置各种参数或者调用各种框架,PaddleHub 部署服务器实在是太好用了。

NOTE: 如使用GPU预测,则需要在启动服务之前,请设置CUDA_VISIBLE_DEVICES环境变量,否则不用设置。

在服务端发送请求,请求脚本如下:

import requests
import json
import cv2
import base64
import numpy as np
def cv2_to_base64(image):
    data = cv2.imencode('.jpg', image)[1]
    return base64.b64encode(data.tostring()).decode('utf8')
def base64_to_cv2(b64str):
    data = base64.b64decode(b64str.encode('utf8'))
    data = np.fromstring(data, np.uint8)
    data = cv2.imdecode(data, cv2.IMREAD_COLOR)
    return data
# 发送HTTP请求
org_im = cv2.imread('/PATH/TO/IMAGE')
data = {'images':[cv2_to_base64(org_im)], 'top_k':1}
headers = {"Content-type": "application/json"}
url = "http://127.0.0.1:8866/predict/resnet50_vd_imagenet_ssld"
r = requests.post(url=url, headers=headers, data=json.dumps(data))
data =r.json()["results"]['data']

相信只要有一些 Python 基础,在本地预测、以及部署到服务器端都是没问题的,飞桨的 PaddleHub 已经帮我们做好了各种处理过程。


九、更多PaddleEdu信息内容


1. PaddleEdu一站式深度学习在线百科awesome-DeepLearning中还有其他的能力,大家可以敬请期待:


  • 深度学习入门课

image.png

  • 深度学习百问

image.png

  • 特色课

image.png

  • 产业实践

image.png

PaddleEdu使用过程中有任何问题欢迎在awesome-DeepLearning提issue,同时更多深度学习资料请参阅飞桨深度学习平台



相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
人工智能
adobe2023全家桶阿里云
Adobe系列的软件都挺好的,需要做图、设计的工作者,基本都会用到Adobe系列的软件,一张张优秀图片的制作离不开这些软件的综合运用。
944 0
|
开发工具 git
git,github,gitlab,码云的区别
码云https://gitee.com/enterprises?from=tg-6-7是开源中国社区推出的基于git的代码托管服务平台,基于gitlab。目前招商银行,中国科学技术大学,CSDN等多家企业和机构都在使用码云平台
962 0
|
11月前
|
存储 设计模式 缓存
OkHttp源码解析(小白必看,建议收藏)
本文详细解析了OkHttp3的源码及其实现机制,适合初学者学习。文章从Request与Response结构、HTTPS握手过程、响应码含义、Socket概念到责任链模式的应用逐一讲解。重点分析了OkHttp的工作流程:通过Call对象的enqueue()或execute()方法发起请求,核心是getResponseWithInterceptorChain(),利用拦截器链处理请求,包括用户自定义拦截器、重试、桥接、缓存、连接等步骤。最后还探讨了Dispatcher的任务调度机制。
1128 71
|
7月前
|
机器学习/深度学习 传感器 算法
【高创新】基于优化的自适应差分导纳算法的改进最大功率点跟踪研究(Matlab代码实现)
【高创新】基于优化的自适应差分导纳算法的改进最大功率点跟踪研究(Matlab代码实现)
369 14
|
8月前
|
机器学习/深度学习 算法 机器人
基于蚁群优化算法的直流电机模糊PID控制(Matlab实现)
基于蚁群优化算法的直流电机模糊PID控制(Matlab实现)
210 0
|
10月前
|
缓存 JSON 前端开发
最受欢迎的三方库之harmony-utils
harmony-utils 是一款功能丰富且易于使用的 HarmonyOS 工具库,涵盖 APP、设备、屏幕、授权、通知、文件操作、加解密等多种常用功能,帮助开发者高效构建鸿蒙应用。体积小巧(仅约 130KB),性能优越,适用于 OpenHarmony API 12 及以上版本。
449 0
|
7月前
|
算法 定位技术 调度
基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)
基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)
341 0
|
机器学习/深度学习 人工智能 自然语言处理
人工智能基础知识:介绍人工智能的历史,基本概念和应用领域
人工智能基础知识:介绍人工智能的历史,基本概念和应用领域
16613 0
【HarmonyOS】HMRouter使用详解(二)
HMRouter中使用HMRouterMgr的静态方法push()和replace()来实现路由跳转。使用pop()方法来实现页面返回 * push :目标页面不会替换当前页,而是插入页面栈。可以使用pop实现页面的返回操作。 * replace:目标页面会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。 * pop:返回页面栈的上一个页面,skipedLayerNumber 页面返回的层级数量,默认为0,表示返回上一级,1表示跳过一级页面返回
755 8
【HarmonyOS】HMRouter使用详解(二)
|
人工智能 搜索推荐 测试技术
通义灵码 2.0 智能编码功能评测:Deepseek 加持下的 Python 开发体验
通义灵码 2.0 智能编码功能评测:Deepseek 加持下的 Python 开发体验
689 11

热门文章

最新文章

下一篇
开通oss服务