一、基于PaddleX的可疑人员电子图片信息检查
电子图片信息检查是一项耗费大量人力的工作,本文使用PaddleX动态图进行yolov3_mobilenet迁移学习训练,训练模型加速对关键图片检测,充分解放人力,让ai赋能加速。PaddleX升级到2.1.0,基于动态图的训练和预测依然非常便捷。
检测的主要对象为:
- 身份证
- 聊天记录
- 车票
- 枪支
- 二维码
图过于暴力不给过审,我就删了。
二、环境准备
在新发布的2.X版本中,PaddleX全面升级了对动态图的支持。
1.PaddlePaddle环境
项目环境:PaddlePaddle环境 2.2
2.PaddleX准备
使用PaddleX 2.X版本
!pip install paddlex
!pip list|grep paddlex
paddlex 2.1.0 [33mWARNING: You are using pip version 22.0.4; however, version 22.1.1 is available. You should consider upgrading via the '/opt/conda/envs/python35-paddle120-env/bin/python -m pip install --upgrade pip' command.[0m[33m [0m
三、数据集准备
本项目数据来源于网络,通过EasyData进行标注,导出为VOC格式,目录情况如下:
dataset/ ├── annotations/ ├── images/
而使用PaddleX的API,一键进行数据切分时,数据文件夹切分前后的状态如下:
dataset/ dataset/ ├── Annotations/ <-- ├── Annotations/ ├── JPEGImages/ ├── JPEGImages/ ├── labels.txt ├── test_list.txt ├── train_list.txt ├── val_list.txt
使用稍加整理,就可以使用一键切分快速划分数据集。
1.数据集解压缩
# 解压缩、文件夹重命名仅运行一次 # 解压数据集,并做好数据切分准备 !unzip data/data107101/DatasetId_224359_1630828070.zip
!mv DatasetId_224359_1630828070/Images DatasetId_224359_1630828070/JPEGImages
2.数据集切分
将训练集、验证集和测试集按照7:2:1的比例划分。 PaddleX中提供了简单易用的API,方便用户直接使用进行数据划分。下面这行代码正确执行的前提是,PaddleX的版本和Paddle匹配,要么都是2.0+,要么都是1.8.X。
!paddlex --split_dataset --format VOC --dataset_dir DatasetId_224359_1630828070 --val_value 0.2 --test_value 0.1
四、模型训练
PaddleX最核心的特点就是模型训练极其简单,比如下面几行代码演示的,只要配置了数据集目录,选择好模型即可。
1.引入必要库
import paddlex as pdx from paddlex import transforms as T
2.定义数据增强方法
train_transforms = T.Compose([ T.MixupImage(mixup_epoch=250), T.RandomDistort(), T.RandomExpand(), T.RandomCrop(), T.Resize(target_size=608, interp='RANDOM'), T.RandomHorizontalFlip(), T.Normalize(), ]) eval_transforms = T.Compose([ T.Resize(target_size=608, interp='CUBIC'), T.Normalize(), ])
3.定义数据集
# 定义训练和验证所用的数据集 # API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/datasets/voc.py#L29 train_dataset = pdx.datasets.VOCDetection( data_dir='DatasetId_224359_1630828070', file_list='DatasetId_224359_1630828070/train_list.txt', label_list='DatasetId_224359_1630828070/labels.txt', transforms=train_transforms, shuffle=True) eval_dataset = pdx.datasets.VOCDetection( data_dir='DatasetId_224359_1630828070', file_list='DatasetId_224359_1630828070/val_list.txt', label_list='DatasetId_224359_1630828070/labels.txt', transforms=eval_transforms, shuffle=False)
2021-09-06 19:19:37 [INFO] Starting to read file list from dataset... 2021-09-06 19:19:37 [INFO] 226 samples in file DatasetId_224359_1630828070/train_list.txt, including 226 positive samples and 0 negative samples. creating index... index created! 2021-09-06 19:19:37 [INFO] Starting to read file list from dataset... 2021-09-06 19:19:37 [INFO] 64 samples in file DatasetId_224359_1630828070/val_list.txt, including 64 positive samples and 0 negative samples. creating index... index created!
4.模型引用
涉及到PaddleX中目标检测模型的选择,最关键的就是这行代码(升级后的2.0.4rc可能和之前的包位置不一样)
pdx.det.YOLOv3(num_classes=num_classes, backbone='DarkNet53')
可以先查看下PaddleX目前提供了哪些目标检测模型以及backbone
的支持。
??pdx.det.YOLOv3
# 初始化模型,并进行训练 # 可使用VisualDL查看训练指标,参考https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/train#visualdl可视化训练指标 num_classes = len(train_dataset.labels) model = pdx.det.YOLOv3(num_classes=num_classes, backbone='MobileNetV3_ssld')
5.训练
# 接续训练时必须pretrain_weights=None,否则默认带预训练模型, # pretrain_weights (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET', # 则自动下载在ImageNet图片数据上预训练的模型权重;若为字符串'COCO'。 model.train( num_epochs=1000, train_dataset=train_dataset, train_batch_size=50, eval_dataset=eval_dataset, learning_rate=0.001 / 8, warmup_steps=1000, warmup_start_lr=0.0, save_interval_epochs=10, lr_decay_epochs=[216, 243], pretrain_weights=None, # 如果接续训练,必须设置pretrain_weights=None resume_checkpoint="output/yolov3_mobilenet/epoch_500", save_dir='output/yolov3_mobilenet')
五、模型预测
这里,我们可以进行预测,及时检测到需要的物品。
import glob import numpy as np import threading import time import random import os import base64 import cv2 import json import paddlex as pdx # 传入待预测图片 # image_name = 'DatasetId_224359_1630828070/JPEGImages/qz027.jpg' image_name='cp000000000001.jpg' # 模型保存位置 model = pdx.load_model('output/yolov3_mobilenet/best_model') img = cv2.imread(image_name) result = model.predict(img) print(result)
2021-09-06 23:06:09 [INFO] Model[YOLOv3] loaded. [{'category_id': 0, 'category': 'cp', 'bbox': [96.84454345703125, 283.45458984375, 1002.1554565429688, 412.53955078125], 'score': 0.11080805957317352}, {'category_id': 1, 'category': 'ewm', 'bbox': [849.8785400390625, 491.9258117675781, 143.3311767578125, 214.04342651367188], 'score': 0.7921331524848938}, {'category_id': 1, 'category': 'ewm', 'bbox': [864.4014282226562, 570.3033447265625, 109.937255859375, 80.013671875], 'score': 0.3130922317504883}, {'category_id': 1, 'category': 'ewm', 'bbox': [842.3992919921875, 542.7195434570312, 150.7449951171875, 82.6478271484375], 'score': 0.055740561336278915}]
pdx.det.visualize_detection( image_name, result, threshold=0.50, save_dir='./output/yolov3_mobilenet')
2021-09-06 23:06:18 [INFO] The visualized result is saved at ./output/yolov3_mobilenet/visualize_cp000000000001.jpg
from PIL import Image # img=Image.open('output/yolov3_mobilenet/visualize_sfz008.jpg') img=Image.open('output/yolov3_mobilenet/visualize_cp000000000001.jpg') img.show() img
六、模型裁剪
模型裁剪可以更好地满足在端侧、移动端上部署场景下的性能需求,可以有效得降低模型的体积,以及计算量,加速预测性能。PaddleX集成了PaddleSlim的基于敏感度的通道裁剪算法,通过以下代码,可以在此前训练模型的基础上,加载并进行裁剪,重新开始训练。
# 加载模型 model = pdx.load_model('output/yolov3_mobilenet/best_model') # Step 1/3: 分析模型各层参数在不同的剪裁比例下的敏感度 # API说明:https://github.com/PaddlePaddle/PaddleX/blob/95c53dec89ab0f3769330fa445c6d9213986ca5f/paddlex/cv/models/base.py#L352 model.analyze_sensitivity( dataset=eval_dataset, batch_size=1, save_dir='output/yolov3_mobilenet/prune') # Step 2/3: 根据选择的FLOPs减小比例对模型进行剪裁 # API说明:https://github.com/PaddlePaddle/PaddleX/blob/95c53dec89ab0f3769330fa445c6d9213986ca5f/paddlex/cv/models/base.py#L394 model.prune(pruned_flops=.2) # Step 3/3: 对剪裁后的模型重新训练 # API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/models/detector.py#L154 # 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html model.train( num_epochs=270, train_dataset=train_dataset, train_batch_size=8, eval_dataset=eval_dataset, learning_rate=0.001 / 8, warmup_steps=1000, warmup_start_lr=0.0, save_interval_epochs=5, lr_decay_epochs=[216, 243], pretrain_weights=None, save_dir='output/yolov3_mobilenet/prune')