对于深度学习来说,数据训练需要很强的算力,特别是GPU的支持,而有些电脑是没有GPU的,那么数据训练和推理时间就非常慢长了(深有体会)。PP-LCNet分类模型就很好的解决在CPU上训练和推理速度问题。下面以一个具体图像分类项目来体验一下PP-LCNet模型。
一、模型简介
近年来,有很多轻量级的骨干网络问世,这些网络要么主打 FLOPs 或者 Params 上面的优势,要么就是主打 ARM 设备上的推理速度的优势,很少有网络专门针对 Intel CPU 做特定的优化,导致这些网络在 Intel CPU 端的推理速度并不是很完美。基于此,百度针对 Intel CPU 设备以及其加速库 MKLDNN 设计了特定的骨干网络 PP-LCNet,比起其他的轻量级的 SOTA 模型,该骨干网络可以在不增加推理时间的情况下,进一步提升模型的性能,最终大幅度超越现有的 SOTA 模型。与其他模型的对比图如下
方法
经过大量的实验发现,在基于 Intel CPU 设备上,尤其当启用 MKLDNN 加速库后,很多看似不太耗时的操作反而会增加延时,比如 elementwise-add 操作、split-concat 结构等。所以最终选用了结构尽可能精简、速度尽可能快的 block 组成的 BaseNet(类似 MobileNetV1)。基于 BaseNet,通过实验,总结了四条几乎不增加延时但是可以提升模型精度的方法,融合这四条策略,组合成了 PP-LCNet。下面对这四条策略一一介绍:
更好的激活函数
自从卷积神经网络使用了 ReLU 激活函数后,网络性能得到了大幅度的提升,近些年 ReLU 激活函数的变体也相继出现,如 Leaky-ReLU、P-ReLU、ELU 等,2017 年,谷歌大脑团队通过搜索的方式得到了 swish 激活函数,该激活函数在轻量级网络上表现优异,在 2019 年,MobileNetV3 的作者将该激活函数进一步优化为 H-Swish,该激活函数去除了指数运算,速度更快,网络精度几乎不受影响。我们也经过很多实验发现该激活函数在轻量级网络上有优异的表现。所以在 PP-LCNet 中,我们选用了该激活函数。
合适的位置添加 SE 模块
SE 模块是 SENet 提出的一种通道注意力机制,可以有效提升模型的精度。但是在 Intel CPU 端,该模块同样会带来较大的延时,如何平衡精度和速度是我们要解决的一个问题。虽然在 MobileNetV3 等基于 NAS 搜索的网络中对 SE 模块的位置进行了搜索,但是并没有得出一般的结论,我们通过实验发现,SE 模块越靠近网络的尾部对模型精度的提升越大。
合适的位置添加更大的卷积核
在 MixNet 的论文中,作者分析了卷积核大小对模型性能的影响,结论是在一定范围内大的卷积核可以提升模型的性能,但是超过这个范围会有损模型的性能,所以作者组合了一种 split-concat 范式的 MixConv,这种组合虽然可以提升模型的性能,但是不利于推理。我们通过实验总结了一些更大的卷积核在不同位置的作用,类似 SE 模块的位置,更大的卷积核在网络的中后部作用更明显
GAP 后使用更大的 1x1 卷积层
在 GoogLeNet 之后,GAP(Global-Average-Pooling)后往往直接接分类层,但是在轻量级网络中,这样会导致 GAP 后提取的特征没有得到进一步的融合和加工。如果在此后使用一个更大的 1x1 卷积层(等同于 FC 层),GAP 后的特征便不会直接经过分类层,而是先进行了融合,并将融合的特征进行分类。这样可以在不影响模型推理速度的同时大大提升准确率。
BaseNet 经过以上四个方面的改进,得到了 PP-LCNet
注:以上部分文字资料来源于模型官网
二、项目实战——熊猫老虎分类
1、划分数据集:命令行下运行
paddlex --split_dataset --format ImageNet --dataset_dir pandatiger --val_value 0.2 --test_value 0.1
2、模型训练
#划分数据集7:2:1
#paddlex --split_dataset --format ImageNet --dataset_dir faces --val_value 0.2 --test_value 0.0
#输出部署模型
#paddlex --export_inference --model_dir best_model --save_dir inference
import paddlex as pdx
from paddlex import transforms as T
#定义训练和验证时的transforms
train_transforms=T.Compose(
[T.RandomCrop(crop_size=224),T.RandomHorizontalFlip(),T.Normalize()]
)
eval_transforms=T.Compose(
[T.ResizeByShort(short_size=256),T.CenterCrop(crop_size=224),T.Normalize()]
)
#定义训练和验证时的数据集
train_dataset=pdx.datasets.ImageNet(
data_dir="pandatiger",
file_list="pandatiger/train_list.txt",
label_list="pandatiger/labels.txt",
transforms=train_transforms,
shuffle=True
)
eval_dataset=pdx.datasets.ImageNet(
data_dir="pandatiger",
file_list="pandatiger/val_list.txt",
label_list="pandatiger/labels.txt",
transforms=eval_transforms
)
#初始化模型,并进行训练
num_classes=len(train_dataset.labels)
model=pdx.cls.PPLCNet_ssld(num_classes=num_classes)
model.train(
num_epochs=10,
pretrain_weights="IMAGENET",
train_dataset=train_dataset,
train_batch_size=4,
eval_dataset=eval_dataset,
lr_decay_epochs=[4,6,8],
learning_rate=0.01,
save_dir="output/pplcnet-pandatiger",
use_vdl=False
)
从训练过程来看,在CPU上训练的时间大大减少了,准确率能达到90%以上。
3、导出部署模型:命令行下运行
paddlex --export_inference --model_dir best_model --save_dir inference
4、模型预测
#划分数据集7:2:1
#paddlex --split_dataset --format ImageNet --dataset_dir catdog --val_value 0.2 --test_value 0.1
#输出部署模型
#paddlex --export_inference --model_dir best_model --save_dir inference
import paddlex as pdx
import cv2
import os
import random
#启用GPU
#os.environ["CUDA_VISIBLE_DEVICES"]="0,1"
#创建推理对象
predictor=pdx.deploy.Predictor("output/pplcnet-pandatiger/inference_model",use_gpu=True)
#读取测试数据文本文件
with open("pandatiger/test_list.txt") as f:
d=f.readlines()
#随机取一条数据
rndtest=random.choice(d)
imgfile=os.path.join("pandatiger",rndtest.split(" ")[0])
img=cv2.imread(imgfile)
#预测
result=predictor.predict(img)
#把预测结果输出并显示出来
cv2.namedWindow("result",cv2.WINDOW_NORMAL)
cv2.putText(img,result[0]["category"]+":"+str(round(result[0]["score"],3)),(10,30),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),3)
cv2.imshow("result",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
------------------ Inference Time Info ----------------------
total_time(ms): 53.900000000000006, img_num: 1, batch_size: 1
average latency time(ms): 53.90, QPS: 18.552876
preprocess_time_per_im(ms): 5.90, inference_time_per_batch(ms): 48.00, postprocess_time_per_im(ms): 0.00
从以上看来模型推理时间大大缩短
从预测结果准确率来看,能达到90%以上。
整个项目实施,从数据准备、数据训练、再到模型部署,所花费的时间大大减少,而所要达到的效果也令人非常满意。
本文暂时没有评论,来添加一个吧(●'◡'●)