转自AI Studio,原文链接:基于PaddleClas的烟叶烘干阶段分类 - 飞桨AI Studio

、项目背景

烟叶烘烤是烟草加工过程中的一个重要环节,然而在我国,每年烟叶烘烤损失均在10%至15%之间,这严重影响到烟农收益,也影响到工业对烟叶的使用。随着我国现代烟草农业的发展,近十年来,烟叶烘烤普遍采用烟叶智能控制仪进行烘烤,但查阅相关技术和标准,至今还没有一个相对固定的、统一的智能烘烤控制仪的操作及控制标准。仍然需要经验丰富的技术人员对烘干程度进行判断,然后干预机器改变烘干参数,但是这个过程中受人为主观因素影响较大,而且需要实时值守。结合待烤鲜烟叶的主观判断后,随意地对智能烘烤控制仪进行3段式、或7段式、或10段式设置烘烤,并且在烘烤过程中,根据自己的主观判断后又去对烘烤工艺随意调整,将烟叶烤干,烟叶质量就出现了这炕烤好了,那炕却烤坏了,烤好与烤坏之间,没有一个准确的预判。针对该问题,本项目通过深度学习的方式,对传统行业的技术改造进行尝试。

2、工具简介

PaddleClas

飞桨图像识别套件PaddleClas是飞桨为工业界和学术界所准备的一个图像识别任务的工具集,助力使用者训练出更好的视觉模型和应用落地。

特性

  • PP-ShiTu轻量图像识别系统:集成了目标检测、特征学习、图像检索等模块,广泛适用于各类图像识别任务。cpu上0.2s即可完成在10w+库的图像识别。

  • PP-LCNet轻量级CPU骨干网络:专门为CPU设备打造轻量级骨干网络,速度、精度均远超竞品。

  • 丰富的预训练模型库:提供了36个系列共175个ImageNet预训练模型,其中7个精选系列模型支持结构快速修改。

  • 全面易用的特征学习组件:集成arcmargin, triplet loss等12度量学习方法,通过配置文件即可随意组合切换。

  • SSLD知识蒸馏:14个分类预训练模型,精度普遍提升3%以上;其中ResNet50_vd模型在ImageNet-1k数据集上的Top-1精度达到了84.0%, Res2Net200_vd预训练模型Top-1精度高达85.1%。

具体介绍请看PaddleClas

In [1]

#查看paddle版本,使用系统自带的差不多可以满足要求
# 导入所需要的库
from sklearn.utils import shuffle
import os
import pandas as pd
import numpy as np
from PIL import Image
import paddle
import paddle.nn as nn
from paddle.io import Dataset
import paddle.vision.transforms as T
import paddle.nn.functional as F
from paddle.metric import Accuracy
import random
print(paddle.__version__)

3、项目内容

利用PaddleClas套件完成烟叶不同烘干阶段的分类,其中该项目内容包括准备数据集、模型训练、模型推理。从整个过程来看不得不说Paddle的一系列套件刚入门的很友好,可以帮助开发者快速实现自己的需求。

3.1准备数据集

该项目以三阶段式烘干为例。按照制烟厂给的烟叶烘干三个阶段的图片,分别放在三个文件下。形如:

如果大家在进行其他图像分类任务时,可以根据自己待分类的类别进行放到不同文件夹就行,然后按照下面步骤执行,就可以准备好PaddleClas所能使用的数据集。

3.1.1解压数据集

In [1]

!unzip -oq /home/aistudio/data/data132657/test.zip

In [ ]

#查看数据集结构
!tree

3.1.2生成标签

这里生成的文件相当于我们图片的标签,生成的文件如下图所示。

In [ ]

# 先得到整个数据集总的txt
#设置文件根目录
dirpath = "test"
def get_all_txt():
    all_list = []
    i = 0
    for root,dirs,files in os.walk(dirpath): # 分别代表根目录、文件夹、文件。dirpath -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。
        for file in files:
            i = i + 1 
            # 文件中每行格式: 图像相对路径      图像的label_id(注意:\t)。              
            #                test/one/Pic01_2021082512_41_44.jpg 0
            #                test/two/Pic01_2021082818_01_31.jpg     1
            #                test/three/Pic01_2021090103_56_16.jpg 2
            #这里根据我们要分的类别进行设置,这里我们只分了三类          
            if("one" in root):
                all_list.append(os.path.join(root,file)+" 0\n")
            if("two" in root):
                all_list.append(os.path.join(root,file)+" 1\n")
            if("three" in root):
                all_list.append(os.path.join(root,file)+" 2\n")
           
    allstr = ''.join(all_list)
    #将所有的文件所属的类别和文件名保存在all_list.txt
    f = open('all_list.txt','w',encoding='utf-8')
    f.write(allstr)
    return all_list , i

all_list,all_lenth = get_all_txt()
print(all_lenth-1) # 有意者是预测的图片,得减去

3.1.3划分数据集

训练集:测试集=0.8:0.2

并生成相应的标签文件

In [ ]

#随机打乱数据集,然后按照比例划分数据集
random.shuffle(all_list)
random.shuffle(all_list)
train_size = int(all_lenth * 0.8)
train_list = all_list[:train_size]
val_list = all_list[train_size:]

print(len(train_list))
print(len(val_list))
# 运行cell,生成txt 
train_txt = ''.join(train_list)
f_train = open('train_list.txt','w',encoding='utf-8')
f_train.write(train_txt)
f_train.close()
# 运行cell,生成txt
val_txt = ''.join(val_list)
f_val = open('val_list.txt','w',encoding='utf-8')
f_val.write(val_txt)
f_val.close()
725
182

3.2安装PaddleClas

In [ ]

# 安装paddleClas,这里PaddleClas里requiremen的依赖,自带的环境几乎可以满足,所以不需要另外安装
!git clone https://gitee.com/paddlepaddle/PaddleClas.git

In [ ]

!mv test/ PaddleClas/dataset/
!mv all_list.txt PaddleClas/dataset/test
!mv train_list.txt PaddleClas/dataset/test
!mv val_list.txt PaddleClas/dataset/test

移动完之后,形成的数据集结构如图所示

将图片移动PaddleClas下面的数据集里面,如果失败的话,改成绝对路径

3.3模型训练

3.3.1修改配置文件

这里使用PaddleClas/ppcls/configs/quick_start/new_user/ShuffleNetV2_x0_25.yaml配置文件进行训练,这里使用的训练网络为ShuffleNet,大家也可以根据自己的需要进行选择。

# global configs
Global:
  checkpoints: null    #用于断点训练,加载中断前的模型继续训练
  pretrained_model: #./output/ShuffleNetV2_x0_25/best_model #预训练模型,不加载的话收敛相对较慢
  output_dir: ./output/  #模型保存路径
  device: gpu  #使用的设备gpu/cpu
  save_interval: 1  #模型保存间隔
  eval_during_train: True  #训练期间是否开启评估
  eval_interval: 1  #评估间隔,如果觉得间隔较慢可以训练完再进行评估
  epochs: 150  #训练代数
  print_batch_step: 10
  use_visualdl: True  #是否开启数据可视化
  # used for static mode and model export
  image_shape: [3, 224, 224]  #加载图片的尺寸
  save_inference_dir: ./inference  #转成推理模型的保存路径

# model architecture
Arch:
  name: ShuffleNetV2_x0_25  #使用的骨干网络的名称
  class_num: 3  #待分类的类别数
 
# loss function config for traing/eval process损失函数配置,都使用交叉熵损失函数
Loss:
  Train:
    - CELoss:
        weight: 1.0
  Eval:
    - CELoss:
        weight: 1.0
Optimizer:  #优化器配置
  name: Momentum
  momentum: 0.9
  lr:  #学习率配置
    name: Cosine#余弦策略
    learning_rate: 0.0125#学习率
    warmup_epoch: 5 #训练热身
  regularizer:#正则化
    name: 'L2'
    coeff: 0.00001

# data loader for train and eval
DataLoader:
  Train:
    dataset:
      name: ImageNetDataset  #数据读取方式
      image_root: ./dataset/  #图片根目录
      cls_label_path: ./dataset/test/train_list.txt  #训练集标签
      transform_ops:# 训练图像的数据预处理
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - RandCropImage:# 随机裁剪
            size: 224
        - RandFlipImage:# 随机水平翻转
            flip_code: 1
        - NormalizeImage:# 归一化
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]
            std: [0.229, 0.224, 0.225]
            order: ''

    sampler:
      name: DistributedBatchSampler
      batch_size: 256
      drop_last: False
      shuffle: True
    loader:
      num_workers: 0  #这里改成0才能在aistudio运行
      use_shared_memory: True

  Eval:  #参照训练集同样的配置
    dataset: 
      name: ImageNetDataset
      image_root: ./dataset/
      cls_label_path: ./dataset/test/val_list.txt
      transform_ops:
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - ResizeImage:
            resize_short: 256
        - CropImage:
            size: 224
        - NormalizeImage:
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]
            std: [0.229, 0.224, 0.225]
            order: ''
    sampler:
      name: DistributedBatchSampler
      batch_size: 64
      drop_last: False
      shuffle: False
    loader:
      num_workers: 0
      use_shared_memory: True

Infer:
  infer_imgs: ./dataset/test/1.jpg #待推理的照片路径
  batch_size: 10
  transforms:
    - DecodeImage:
        to_rgb: True
        channel_first: False
    - ResizeImage:
        resize_short: 256
    - CropImage:
        size: 224
    - NormalizeImage:
        scale: 1.0/255.0
        mean: [0.485, 0.456, 0.406]
        std: [0.229, 0.224, 0.225]
        order: ''
    - ToCHWImage:
  PostProcess:
    name: Topk
    topk: 3   #修改成我们的类别数
    class_id_map_file: ./ppcls/configs/quick_start/new_user/label_list.txt  #类别标签和实际分类类别的标签映射

Metric:
  Train:
    - TopkAcc:
        topk: [1, 3]  #根据上面的topk进行设置
  Eval:
    - TopkAcc:
        topk: [1, 3]

这里为了最后预测的结果更好分辨,所以我们将预测的结果和标签进行映射,映射文件label_list.txt内容如下图所示

3.3.2开始训练

在自己的数据集上训练分类模型时,更推荐加载预训练进行微调,训练的速度更快,精度更高。 预训练模型使用以下方式进行下载。

python tools/download.py -a MobileNetV3_small_x1_0 -p ./pretrained -d True

更多的预训练模型可以参考这里: 预训练模型

最优模型保存在该路径下PaddleClas/output/ShuffleNetV2_x0_25/

In [3]

%cd PaddleClas/
# 开始训练 
!python tools/train.py -c ./ppcls/configs/quick_start/new_user/ShuffleNetV2_x0_25.yaml
/home/aistudio/PaddleClas

3.4模型推理

这里在配置文件中ShuffleNetV2_x0_25.yaml进行修改,加载我们训练好的最优模型

pretrained_model: ./output/ShuffleNetV2_x0_25/best_model

In [4]

!python3 tools/infer.py -c ./ppcls/configs/quick_start/new_user/ShuffleNetV2_x0_25.yaml  

3.4.1结果分析

输出的预测结果为{'class_ids': [0, 1, 2], 'scores': [0.99984, 0.00016, 0.0],说明预测0类的概率最大,label_names是我们前面标签映射的结果,预测概率最高的第一阶段。下面显示预测的图片进行验证。

In [3]

import matplotlib.pyplot as plt
from PIL import Image
## 显示原图
img_path= "/home/aistudio/PaddleClas/dataset/test/1.jpg"
img = Image.open(img_path)
plt.figure("test_img", figsize=(20,20))
plt.imshow(img)
plt.show()

4、项目总结

利用PaddleClas快速地完成了基本要求,如果想进一步提升模型精度,以及实现更为复杂的5段式烘干分类和7段式烘干分类还有很多工作要做:

  1. 在实际的5段式烘干分类和7段式烘干分类中,烟叶特征区分更加困难,可以换更大的网络的进行训练,本人亲试使用ResNet50要比这里使用的ShuffleNetV2_x0_25精度要高10%~20%
  2. 通过一些数据增广的方式去扩充训练样本,可以增加训练样本的丰富度,提升模型的泛化性能。PaddleClas开源了8种数据增广方案。包括图像变换类、图像裁剪类以及图像混叠类。该项目烟叶特征相似度较高,慎用数据增广,并不是数据增广的方法用的越多最终的效果就越好。

  1. 由于烟叶烘干的场所比较特殊,一般的相机镜头容易起雾,以及周围环境的影响可能会对采集的图片造成一定的影响,也是我们后续改进中需要考虑的因素。
  2. 连续性变化的区分往往比离散型变化要更难,尤其是在两阶段相邻的图片,更容易预测错误,应结合其他的算法综合考虑进行分类,实现整个烘干过程的全自动化,提高产量。
Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐