『PPYOLO tiny尝鲜』基于PaddleDetection的人脸疲劳检测
老規(guī)矩,先上
B站視頻
AIStudio鏈接
背景介紹
背景一(老師的福音)
??講臺(tái)上老師認(rèn)真上課,口若懸河;講臺(tái)下同學(xué)頻頻點(diǎn)頭,雙目具閉!
??45分鐘是很緊張的,老師在這個(gè)時(shí)間段內(nèi)需要把計(jì)劃的教學(xué)任務(wù)完成,而如果學(xué)生無法積極配合、認(rèn)真聽講,還在“閉目養(yǎng)神”、留著口水,老師還需要在課堂上叫醒那些“已經(jīng)睡著了的人”,其實(shí)課堂效率就大大降低了。
??而如果此時(shí)能夠通過室內(nèi)攝像頭捕捉學(xué)生面部表情及動(dòng)作,以此來識(shí)別學(xué)生是否在打瞌睡,并向同學(xué)及老師積極反饋,或許能夠大大提高課堂效率,也方便老師及時(shí)了解學(xué)生課堂情況。
背景二(交通出行)
??一個(gè)人開車是一件很累的事,尤其是開長途,到了行車后期,人會(huì)非常疲憊,會(huì)出現(xiàn)“閉目”、“打哈欠”等動(dòng)作。而此時(shí),由于人的反應(yīng)能力受阻,很容易發(fā)生交通事故。
??此時(shí)若有一個(gè)檢測設(shè)備,監(jiān)測駕駛員的面部表情,在其疲憊時(shí)及時(shí)提醒駕駛員注意休息,能夠有效避免因疲勞駕駛而導(dǎo)致的車禍發(fā)生。
??而“眼睛”的睜閉和“嘴”的張閉是檢測人是否疲勞的一種合理方案。
技術(shù)方案
??本項(xiàng)目基于PaddleDetection目標(biāo)檢測開發(fā)套件,選取1.3M超輕量PPYOLO tiny進(jìn)行項(xiàng)目開發(fā),并部署于windows端。
PPYOLO tiny是什么?
??在當(dāng)前移動(dòng)互聯(lián)網(wǎng)、物聯(lián)網(wǎng)、車聯(lián)網(wǎng)等行業(yè)迅猛發(fā)展的背景下,邊緣設(shè)備上直接部署目標(biāo)檢測的需求越來越旺盛。生產(chǎn)線上往往需要在極低硬件成本的硬件例如樹莓派、FPGA、K210 等芯片上部署目標(biāo)檢測算法。而我們常用的手機(jī) App,也很難直接在終端采用超過 6M 的深度學(xué)習(xí)算法。如何在盡量不損失精度的前提下,獲得體積更小、運(yùn)算速度更快的算法呢?得益于 PaddleSlim 飛槳模型壓縮工具的能力,體積僅為 1.3M 的 PP-YOLO Tiny 誕生了!!
精度速度數(shù)據(jù)
??那 PP-YOLO Tiny 具體采用了哪些優(yōu)化策略呢?
??首先,PP-YOLO Tiny 沿用了 PP-YOLO 系列模型的 spp,iou loss, drop block, mixup, sync bn 等優(yōu)化方法,并進(jìn)一步采用了近 10 種針對(duì)移動(dòng)端的優(yōu)化策略:
??1、更適用于移動(dòng)端的骨干網(wǎng)絡(luò):
????骨干網(wǎng)絡(luò)可以說是一個(gè)模型的核心組成部分,對(duì)網(wǎng)絡(luò)的性能、體積影響巨大。PP-YOLO Tiny 采用了移動(dòng)端高性價(jià)比骨干網(wǎng)絡(luò) MobileNetV3。
??2、更適用移動(dòng)端的檢測頭(head):
????除了骨干網(wǎng)絡(luò),PP-YOLO Tiny 的檢測頭(head)部分采用了更適用于移動(dòng)端的深度可分離卷積(Depthwise Separable Convolution),相比常規(guī)的卷積操作,有更少的參數(shù)量和運(yùn)算成本, 更適用于移動(dòng)端的內(nèi)存空間和算力。
??3、去除對(duì)模型體積、速度有顯著影響的優(yōu)化策略:
????在 PP-YOLO 中,采用了近 10 種優(yōu)化策略,但并不是每一種都適用于移動(dòng)端輕量化網(wǎng)絡(luò),比如 iou aware 和 matrix nms 等。這類 Trick 在服務(wù)器端容易計(jì)算,但在移動(dòng)端會(huì)引入很多額外的時(shí)延,對(duì)移動(dòng)端來說性價(jià)比不高,因此去掉反而更適當(dāng)。
??4、使用更小的輸入尺寸
????為了在移動(dòng)端有更好的性能,PP-YOLO Tiny 采用 320 和 416 這兩種更小的輸入圖像尺寸。并在 PaddleDetection2.0 中提供 tools/anchor_cluster.py 腳本,使用戶可以一鍵式的獲得與目標(biāo)數(shù)據(jù)集匹配的 Anchor。例如,在 COCO 數(shù)據(jù)集上,我們使用 320*320 尺度重新聚類了 anchor,并對(duì)應(yīng)的在訓(xùn)練過程中把每 batch 圖?的縮放范圍調(diào)整到 192-512 來適配?尺?輸?圖片的訓(xùn)練,得到更高性能。
??5、召回率優(yōu)化
????在使??尺寸輸入圖片時(shí),對(duì)應(yīng)的目標(biāo)尺寸也會(huì)被縮?,漏檢的概率會(huì)變大,對(duì)應(yīng)的我們采用了如下兩種方法來提升目標(biāo)的召回率:
????a.原真實(shí)框的注冊方法是注冊到網(wǎng)格?最匹配的 anchor 上,優(yōu)化后還會(huì)同時(shí)注冊到所有與該真實(shí)框的 IoU 不小于 0.25 的 anchor 上,提?了真實(shí)框注冊的正例。
????b.原來所有與真實(shí)框 IoU 小于 0.7 的 anchor 會(huì)被當(dāng)錯(cuò)負(fù)例,優(yōu)化后將該閾值減小到 0.5,降低了負(fù)例比例。
????通過以上增加正例、減少負(fù)例的方法,彌補(bǔ)了在小尺寸上的正負(fù)例傾斜問題,提高了召回率。
??6、更大的 batch size
????往往更大的 Batch Size 可以使訓(xùn)練更加穩(wěn)定,獲取更優(yōu)的結(jié)果。在 PP-YOLO Tiny 的訓(xùn)練中,單卡 batch size 由 24 提升到了 32,8 卡總 batch size=8*32=256,最終得到在 COCO 數(shù)據(jù)集上體積 4.3M,精度與預(yù)測速度都較為理想的模型。
??7、量化后壓縮
????最后,結(jié)合 Paddle Inference 和 Paddle Lite 預(yù)測庫支持的后量化策略,即在將權(quán)重保存成量化后的 int8 數(shù)據(jù)。這樣的操作,是模型體積直接壓縮到了 1.3M,而預(yù)測時(shí)使用 Paddle Lite 加載權(quán)重,會(huì)將 int8 數(shù)據(jù)還原回 float32 權(quán)重,所以對(duì)精度和預(yù)測速度?乎沒有任何影響。
??通過以上一系列優(yōu)化,我們就得到了 1.3M 超超超輕量的 PP-YOLO tiny 模型,而算法可以通過 Paddle Lite 直接部署在麒麟 990 等輕量化芯片上,預(yù)測效果也非常理想。
實(shí)地操作
# 先將PaddleDetection從gitee上download下來 !git clone https://gitee.com/paddlepaddle/PaddleDetection.git數(shù)據(jù)處理
??由于原數(shù)據(jù)集中存在圖片數(shù)據(jù)與標(biāo)注數(shù)據(jù)不匹配的問題,故需要將不匹配的這部分?jǐn)?shù)據(jù)刪除。
import os,shutiljpeg = 'dataset/JPEGImages' jpeg_list = os.listdir(jpeg)anno = 'dataset/Annotations' anno_list = os.listdir(anno)for pic in jpeg_list:name = pic.split('.')[0]anno_name = name + '.xml'print(anno_name)if anno_name not in anno_list:os.remove(os.path.join(jpeg,pic)) 這里我們通過paddlex中的數(shù)據(jù)集劃分工具幫助我們進(jìn)行數(shù)據(jù)集劃分。 !pip install paddlex !pip install paddle2onnx 我們設(shè)置了訓(xùn)練集、驗(yàn)證集、測試集比例為8:1:1,訓(xùn)練集共2332個(gè)sammples,驗(yàn)證集和測試集均為291個(gè)samples。 !paddlex --split_dataset --format VOC --dataset_dir dataset --val_value 0.1 --test_value 0.1 PaddleDetection中提供了VOC數(shù)據(jù)集轉(zhuǎn)COCO數(shù)據(jù)集的腳本,但提供的腳本存在一些bug,本人在PaddleDetection的Github issue中找到了一個(gè)修復(fù)后的腳本:x2coco.py。 這里我們將前面修改完畢的VOC格式的數(shù)據(jù)集轉(zhuǎn)化為符合PaddleDetection PPYOLO tiny的COCO數(shù)據(jù)集格式。 !python x2coco.py --dataset_type voc --voc_anno_dir /home/aistudio/dataset/Annotations/ --voc_anno_list /home/aistudio/dataset/ImageSets/Main/train.txt --voc_label_list /home/aistudio/dataset/labels.txt --voc_out_name voc_test.json !python x2coco.py --dataset_type voc --voc_anno_dir /home/aistudio/dataset/Annotations/ --voc_anno_list /home/aistudio/dataset/ImageSets/Main/val.txt --voc_label_list /home/aistudio/dataset/labels.txt --voc_out_name voc_val.json !python x2coco.py --dataset_type voc --voc_anno_dir /home/aistudio/dataset/Annotations/ --voc_anno_list /home/aistudio/dataset/ImageSets/Main/test.txt --voc_label_list /home/aistudio/dataset/labels.txt --voc_out_name voc_train.json !mv voc_train.json dataset/ !mv voc_test.json dataset/ !mv voc_val.json dataset/ Start converting ! 100%|████████████████████████████████████| 1631/1631 [00:00<00:00, 12327.36it/s] Start converting ! 100%|██████████████████████████████████████| 583/583 [00:00<00:00, 12504.37it/s] Start converting ! 100%|████████████████████████████████████| 1283/1283 [00:00<00:00, 12609.82it/s]修改配置文件(./PaddleDetection/configs/ppyolo/ppyolo_tiny_650e_coco.yml)
在yolo系列模型中,可以運(yùn)行tools/anchor_cluster.py來得到適用于你的數(shù)據(jù)集Anchor,使用方法如下:
!python tools/anchor_cluster.py -c configs/ppyolo/ppyolo_tiny_650e_coco.yml -n 9 -s 608 -m v2 -i 1000為了適配在自定義數(shù)據(jù)集上訓(xùn)練,需要對(duì)參數(shù)配置做一些修改:
數(shù)據(jù)路徑配置: 在yaml配置文件中,依據(jù)數(shù)據(jù)準(zhǔn)備中準(zhǔn)備好的路徑,配置TrainReader、EvalReader和TestReader的路徑。
其余參數(shù)具體可參照PaddleDetection,這里不作過多介紹。
然后執(zhí)行訓(xùn)練腳本即可。
%cd PaddleDetection/ !pip install -r requirements.txt !python -u tools/train.py -c configs/ppyolo/ppyolo_tiny_650e_coco.yml \-o pretrain_weights=https://paddledet.bj.bcebos.com/models/pretrained/MobileNetV3_large_x0_5_pretrained.pdparams \--eval \-r output/ppyolo_tiny_650e_coco/1200 \--vdl_log_dir vdl_log_dir/scalar數(shù)據(jù)導(dǎo)出
??訓(xùn)練完后我們將訓(xùn)練過程中保存的模型導(dǎo)出為inference格式模型,其原因在于:PaddlePaddle框架保存的權(quán)重文件分為兩種:支持前向推理和反向梯度的訓(xùn)練模型 和 只支持前向推理的推理模型。二者的區(qū)別是推理模型針對(duì)推理速度和顯存做了優(yōu)化,裁剪了一些只在訓(xùn)練過程中才需要的tensor,降低顯存占用,并進(jìn)行了一些類似層融合,kernel選擇的速度優(yōu)化。而導(dǎo)出的inference格式模型包括__model__、__params__和model.yml三個(gè)文件,分別表示模型的網(wǎng)絡(luò)結(jié)構(gòu)、模型權(quán)重和模型的配置文件(包括數(shù)據(jù)預(yù)處理參數(shù)等)。
# 導(dǎo)出模型,默認(rèn)存儲(chǔ)于output/ppyolo目錄 !python tools/export_model.py -c configs/ppyolo/ppyolo_tiny_650e_coco.yml -o weights=Poutput/ppyolo_tiny_650e_coco/best_model同樣的,PaddleDetection也提供了基于Python的預(yù)測腳本供開發(fā)者使用。
參數(shù)說明如下:
| –model_dir | Yes | 上述導(dǎo)出的模型路徑 |
| –image_file | Option | 需要預(yù)測的圖片 |
| –image_dir | Option | 要預(yù)測的圖片文件夾路徑 |
| –video_file | Option | 需要預(yù)測的視頻 |
| –camera_id | Option | 用來預(yù)測的攝像頭ID,默認(rèn)為-1(表示不使用攝像頭預(yù)測,可設(shè)置為:0 - (攝像頭數(shù)目-1) ),預(yù)測過程中在可視化界面按q退出輸出預(yù)測結(jié)果到:output/output.mp4 |
| –use_gpu | No | 是否GPU,默認(rèn)為False |
| –run_mode | No | 使用GPU時(shí),默認(rèn)為fluid, 可選(fluid/trt_fp32/trt_fp16/trt_int8) |
| –batch_size | No | 預(yù)測時(shí)的batch size,在指定image_dir時(shí)有效 |
| –threshold | No | 預(yù)測得分的閾值,默認(rèn)為0.5 |
| –output_dir | No | 可視化結(jié)果保存的根目錄,默認(rèn)為output/ |
| –run_benchmark | No | 是否運(yùn)行benchmark,同時(shí)需指定--image_file或--image_dir |
| –enable_mkldnn | No | CPU預(yù)測中是否開啟MKLDNN加速 |
| –cpu_threads | No | 設(shè)置cpu線程數(shù),默認(rèn)為1 |
當(dāng)然,在本項(xiàng)目中也提供了PaddleX 訓(xùn)練及導(dǎo)出方式,可供讀者朋友嘗試不同的飛槳套件。
# 環(huán)境變量配置,用于控制是否使用GPU # 說明文檔:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu import os os.environ['CUDA_VISIBLE_DEVICES'] = '0'from paddlex.det import transforms import paddlex as pdx# 定義訓(xùn)練和驗(yàn)證時(shí)的transforms # API說明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html train_transforms = transforms.Compose([transforms.MixupImage(mixup_epoch=250), transforms.RandomDistort(),transforms.RandomExpand(), transforms.RandomCrop(), transforms.Resize(target_size=608, interp='RANDOM'), transforms.RandomHorizontalFlip(),transforms.Normalize() ])eval_transforms = transforms.Compose([transforms.Resize(target_size=608, interp='CUBIC'), transforms.Normalize() ])# 定義訓(xùn)練和驗(yàn)證所用的數(shù)據(jù)集 # API說明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection train_dataset = pdx.datasets.VOCDetection(data_dir='dataset',file_list='dataset/train_list.txt',label_list='dataset/labels.txt',transforms=train_transforms,shuffle=True) eval_dataset = pdx.datasets.VOCDetection(data_dir='dataset',file_list='dataset/val_list.txt',label_list='dataset/labels.txt',transforms=eval_transforms)# 初始化模型,并進(jìn)行訓(xùn)練 # 可使用VisualDL查看訓(xùn)練指標(biāo),參考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html num_classes = len(train_dataset.labels)# API說明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-ppyolo model = pdx.det.PPYOLO(num_classes=num_classes)# API說明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#train # 各參數(shù)介紹與調(diào)整說明: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.000125,lr_decay_epochs=[210, 240],save_dir='output/ppyolo',save_interval_epochs=1,use_vdl=True) !paddlex --export_inference --model_dir=output/ppyolo/best_model --save_dir=./inference_model總結(jié)
以上是生活随笔為你收集整理的『PPYOLO tiny尝鲜』基于PaddleDetection的人脸疲劳检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爸,这下你还敢抽烟么?
- 下一篇: 基于深度学习和机器学习的心电图智能分析参