文章目錄
- 一、DepGraph剪枝
- (1)項目準備
- 1)剪枝基礎知識
- 2)DepGraph剪枝論文解讀1
- 2)DepGraph剪枝論文解讀2
- 3)YOLO目標檢測系列發展史
- 4)YOLO網絡架構
- (2)項目實戰(YOLOv8應用DepGraph剪枝+finetune)
- 1)安裝軟件環境(基礎環境、Pytorch、YOLOv8)Windows
- 1)安裝軟件環境(基礎環境、Pytorch、YOLOv8)Linux(略)
- 2)準備數據集和修改配置(YOLO版本8.1033)
- 3)訓練數據集、測試訓練的網絡測試和性能評估
- 4)DepGraph剪枝訓練YOLOv8
- 5)剪枝訓練后網絡測試和性能評估
- (3)代碼解析
- 1)Torch Pruning工具包介紹(安裝、普通剪枝示例、掃描分組、根據通道剪枝的高級剪枝器、全局剪枝、依賴圖中不必要的權重更新的稀疏訓練、交互式剪枝、)
- 2)yolov8_pruning腳本代碼解析(代碼針對yolov8 8.1.33)
- 3)額外代碼注釋補充:
- 二、Network Slimming剪枝
- (1)項目準備
- 1)Network Slimming剪枝原理
- 2)YOLO目標檢測系列發展史
- 3)YOLOv8網絡架構
- (2)項目實戰
- 1)安裝基礎環境、安裝Pytorch、安裝YOLOv8
- 2)準備數據集、修改配置文件、訓練數據集
- 3)測試訓練處的網絡和性能統計
- 4)稀疏化訓練
- 5)網絡剪枝
- 6)剪枝后微調
- (3)代碼解析
- 1)修改代碼文件解析
- 2)新增代碼文件解析
一、DepGraph剪枝
(1)項目準備
- 基礎知識背景
①稀疏:在模型剪枝(Model Pruning)中,稀疏表示(Sparsity)是指通過某種方式使模型的參數或結構中出現大量的零值(或接近零的值),從而讓模型的表示變得 “稀疏”
②為什么要剪枝而不是去訓練小網絡:因為彩票事件效應,去小網絡是很難學習成功的
彩票效應:大模型有很多小網絡,如果有一個子網絡訓練成功則可以看做大模型訓練成功
把模型隨機初始化后訓練,剪枝后如果再次隨機初始化權重是很難訓練成功的,但是如果用原先第一次隨機初始化的權重訓練的話就成功,這就說明中獎了
1)剪枝基礎知識
之前我有寫過博客
CUDA與TensorRT學習四:模型部署基礎知識、模型部署的幾大誤區、模型量化、模型剪枝、層融合
①剪枝分類
②粗粒度剪枝和細粒度剪枝對比
粗粒度
細粒度剪枝
③基礎知識
1)神經網絡通常都是過度參數化,權重數很多都是多余的
2)剪枝顆粒度
(1)權重剪枝
權重剪枝,剪枝之后就變成非規則,缺點是難以實現,難以加速
(2)神經元剪枝
- 補充
還有不同顆粒度剪枝
)element wise包括了權重和神經元剪枝,可能會導致非結構化剪枝,得不到GPU加速
)其他四個是結構化剪枝,能得到GPU加速是研究重點
channel:通道剪枝
filter:濾波器剪枝
shape:若干個高度和寬度的神經元剪枝
depth:某個深度方向的神經元都剪枝掉
2)DepGraph剪枝論文解讀1
①論文截圖
②網絡架構中可按照不同層數分配在各個組中,按組來剪枝(同一組有依賴關系
)
如圖所示 CNNS、Transformer、RNNs、 GNNs都可以剪枝。在圖中如果剪枝了CNNs的Con v2,那就必須刪除同組中的{ Conv1、BN1、 BN2} ,從而引入了依賴圖
,明確依賴圖來自動化剪枝
③算法核心
:利用相鄰層的局部依賴關系,遞歸地推導出需要的分組矩陣G
如下圖,a是非結構化剪枝僅僅關注了權重的重要性,b學習結構稀疏層,但是w比w‘耦合權重更多是不稀疏的,也不考慮剪枝掉,唯有c組是學習組的一致結構稀疏
,表示的是要剪枝掉的組里面w和w’都是稀疏的
④相關工具:基于DepGraph算法,作者開發Pytorch結構化剪枝框架Torch-Pruning,與torch.nn.utils.prune最大的差別在于:它會物理地移除參數,同時自動裁剪其他依賴層
,而后者只能把參數置為0
④DepGraph剪枝+fine效果展示:
可以看到橫軸往右隨著剪枝越多,計算量MACs越低,pruned mAP掉點越跳躍,而fine-tune后的模型精度基本變化不大
1)MACs
MACs(Multiply - Accumulate Operations,乘累加操作次數 )代表計算量。它用于衡量模型在推理過程中執行乘法和累加操作的總數,是評估模型計算復雜度的重要指標
2)pruned mAP
表示剪枝后的模型精度
3)recovered mAP
剪枝后的模型微調后的精度
2)DepGraph剪枝論文解讀2
(1)問題點-現有的剪枝存在問題:算法實現和網絡結構強綁定
,需要為不同模型分別開發專用且復雜的剪枝程序
(2)解決方法-依賴圖
:自動方式去分組
(3)原理解析:利用相鄰層的局部關系遞歸式分組
3)YOLO目標檢測系列發展史
①重大分水嶺在2012年,2012年之前是傳統檢測方法,2012年后是基于深度學習檢測方法
②2012年后有兩種發展方式:單階段檢測、雙階段檢測,兩者區別是雙階段檢測器提出了候選框階段然后得出物體的預測框
③單階段檢測框:yolo、SSD、Retina-Net,雙階段檢測框:RCNN、SPPNet、Fast RCNN、Faster RCNN、Pyramid Networks
④yolo發展
4)YOLO網絡架構
- 網絡架構簡圖
①input:輸入圖片
②Backbone:骨干網絡,深度學習的神經網絡
③由于沒有候選框,所以單階段檢測有密集的預測,而多階段檢測有候選框所以是稀疏的預測
④proposal-free表示沒有候選框
⑤yolo主要思想:分框對落入其中的目標進行檢測,一次性預測所有格子所含目標的邊界框、定位置信度、以及所有類別概率向量
Non-max suppression:NMS,非極大抑制,比較多個預測框的IOU
⑥yolo基礎思想:
1、劃分網格
2、通過網格得到物體的邊界框 bounding boxes+置信度得分 confidence + class probility map類別概率圖
3、最終的檢測結果
4、以下圖的B表示有多少尺度邊界框的預測,現在再看是有三個尺度的邊界框,然后用FPN多尺度的融合劃分預測(13x13\26x26\52x52)
5、Anchor錨框機制:預先設置邊界框的大小,每個尺度上都可以有若干個Anchor(下圖每種顏色有三個錨框)
6、不同anchor對比
(2)項目實戰(YOLOv8應用DepGraph剪枝+finetune)
1)安裝軟件環境(基礎環境、Pytorch、YOLOv8)Windows
①準備基礎環境
基礎環境
1)windows 10
2)cuda 11.8
3)cudnn 8.9
4)vs 2022
5)下載安裝顯卡驅動
2)下載cuda 11.8
安裝cuda
3)cudnn 8.9 下載
安裝cudnn
cuda安裝測試
4)vs 2022安裝
5)下載安裝顯卡驅動
②安裝PyTorch
這里是用的Anaconda進行安裝
1)安裝Anaconda
2)安裝pytorch
1)安裝Anaconda
2)安裝pytorch
在環境下面安裝pytorch
再安裝cudnn
③克隆和安裝YOLOv8
1)克隆yolov8并安裝
2)下載yolov8預訓練權重文件
3)安全測速
1)克隆yolov8并安裝
先安裝git
安裝git后克隆yolov8項目
2)下載yolov8預訓練權重文件
這里選用的yolov8s,這里使用的訓練集是coco,下圖是coco數據集上性能的表現
3)安全測速
單次預測圖片
打開文件夾
可以看到檢測圖片
攝像頭實時動態預測:
預測文本的結果:命令如下
最左邊:類別的編號–5是bug,0是person
后面四位小數:預測物體在圖片上的位置(進行了歸一化所以是小數)
1)安裝軟件環境(基礎環境、Pytorch、YOLOv8)Linux(略)
①準備基礎環境
②安裝PyTorch
③克隆和安裝YOLOv8
2)準備數據集和修改配置(YOLO版本8.1033)
①進入ultraiyics解壓目錄輸入 ,安裝好后進入上面安裝測試的步驟
pip install -e .
①testfile下面的圖片是測試圖片
②VOC2007下面是圖片和圖片對應的標注信息和圖片信息
執行這個腳本是劃分數據集和驗證集
TRAIN_RATIO表示80%劃分到訓練集,20%驗證集
4)修改配置文件
①這里的目錄images是相對路徑,相當于vocdevkit目錄下
②name下面是類別的名稱
3)訓練數據集、測試訓練的網絡測試和性能評估
1)訓練數據集命令(利用預訓練的權重來在自己的數據集上進行訓練,也可稱為微調)
斷點續訓練:因斷電或其他原因導致的中斷訓練,可以接著訓練
訓練結果(train是訓練中的變化,val是驗證中的變化,metric是訓練中的指標)
2)訓練結果查看
- 測試訓練出的網絡模型
性能統計
conf:置信度閾值
iou:非極大抑制閾值
4)DepGraph剪枝訓練YOLOv8
+參數說明
觸發掉點20%才會終止迭代
- 訓練后 ultralytics/runs/detect文件夾下
- 結果
5)剪枝訓練后網絡測試和性能評估
-
驗證安裝onnx-runtime
-
注意
非pytorch模型,batch在檢測性能的時候會變成1
-
性能評估
①可以看到剪枝后mAP50為0.966,mAP(50~95)為0.775
②微調后的數據mAP50為0.985,mAP(50~95)為0.821,明顯是比只剪枝精度高的
③可以從圖中看到,在剪枝比例50%附近掉點事最嚴重的,但是經過微調也能恢復到與剛開始mAP差不多的精度
④linux下在做對比
1)從圖片可以看到只剪枝后對比只微調精度在mAP指標上有下降,從0.983下降到0.879大概掉點11%
2)接下來的步驟是先剪枝,結果保存在step_0_pre_val
3)再繼續進行30個epoch的微調(可以30以上的epoch效果會更好),再查看精度(在最好的權重文件best.pt里面),結果保存在step_post_val
4)再做一次pruning剪枝,然后在做30個epoch的微調
可以看到再次微調后mAP只跌到0.78,而mAP(50~95)還是0.96附近
5)打開結果可以看到第二次剪枝后微調,mAP50在30個epoch后還在持續上升
(3)代碼解析
1)Torch Pruning工具包介紹(安裝、普通剪枝示例、掃描分組、根據通道剪枝的高級剪枝器、全局剪枝、依賴圖中不必要的權重更新的稀疏訓練、交互式剪枝、)
①可以給很多網絡剪枝
②安裝步驟
③演示DepGraph進行基本修剪流程,目標層是resnet.conv1,找出與conv1分為同一組的其他層,統一剪枝
④掃描模型所有的分組
⑤高級剪枝器:通過指定所需的通道修剪比例,修剪器將掃描所有可修剪的組并預估重要性從而修剪整個模型,并使用自己的訓練代碼進行微調
代碼備注:分類層別剪枝,分類層是跟類別數相關的
⑥全局剪枝:根據各層的全局重要性分配自適應稀疏性,但會存在過度剪枝風險
⑦稀疏訓練:減少依賴圖中不必要的權重更新
⑧交互類剪枝:要求了解那些層可以拿來剪枝,要求非常了解網絡架構
⑨軟剪枝:將參數歸零而不是移除
⑩組級剪枝
十一、低級剪枝功能:指定那些層來剪枝
2)yolov8_pruning腳本代碼解析(代碼針對yolov8 8.1.33)
-
主體思想
函數中使用了 torch-pruning(tp)庫進行剪枝操作,通過 GroupNormPruner 對象基于 L2 范數的重要性對模型的卷積層進行剪枝。剪枝后,通過微調訓練來恢復模型的性能。在每次迭代中,函數記錄了剪枝前后的 MACs、參數數量和 mAP,并繪制性能圖表,以便觀察剪枝對模型性能的影響。如果 mAP 下降超過指定閾值,函數會提前停止剪枝過程。最后,函數將剪枝后的模型導出為 ONNX 格式,并將最終的剪枝和微調后的模型保存為 .pt 文件,以便后續使用。 -
注意點
需要注意的是,該函數依賴于其他函數和類,如 train_v2 、 replace_c2f_with_c2f_v2 、initialize_weights 等,以及 torch-pruning 庫的相關功能。 -
代碼步驟
①main函數設置讀取配置規則:
②進行多次迭代的剪枝和微調:
③將剪枝后的模型導出為 ONNX 格式
④將最終的剪枝和微調后的模型保存為 .pt 文件 -
具體
①main函數設置讀取配置規則:
創建一個 argparse.ArgumentParser 對象 parser ,用于定義和解析命令行參數
if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument('--model', default='D:/ultralytics/runs/detect/train/weights/best.pt', help='Pretrained pruning target model file')parser.add_argument('--cfg', default='default.yaml',help='Pruning config file.'' This file should have same format with ultralytics/ultralytics/cfg/default.yaml')parser.add_argument('--iterative-steps', default=16, type=int, help='Total pruning iteration step')parser.add_argument('--target-prune-rate', default=0.5, type=float, help='Target pruning rate')parser.add_argument('--max-map-drop', default=0.2, type=float, help='Allowed maximum map drop after fine-tuning')parser.add_argument('--data', type=str, default='VOC-ball.yaml',help='Path to the dataset configuration file')parser.add_argument('--epochs', type=int, default=30, help='Number of epochs for fine-tuning each pruning iteration step')args = parser.parse_args()prune(args)
這段代碼是一個 Python 腳本的主程序部分,它使用 argparse 模塊來解析命令行參數,并調用 prune 函數來
執行模型剪枝。
參數解釋如下:
-》調用 parser.parse_args() 方法解析命令行參數,并將解析結果存儲在 args 變量中
-》調用 prune 函數,并將 args 作為參數傳遞給該函數,開始執行模型剪枝過程
-》當用戶在命令行中運行該腳本時,可以使用以下格式指定參數:
python yolov8_pruning.py --model last.pt --cfg default.yaml --iterative-steps 16 --
target-prune-rate 0.5 --max-map-drop 0.2 --data VOC-ball.yaml --epochs 30
②進行多次迭代的剪枝和微調:
for i in range(args