實際工作中,目标檢測 yolov3 或者 yolov4 模型移植到 AI 晶片中,經常需要将其先轉換為 caffe1.x 模型,大家可能或多或少也有這方面的需求。例如華為海思 NNIE 隻支援caffe1.x 模型,是以 yolov3/yolov4 模型要想在海思晶片上部署,轉換為 caffe1.x 模型是必須的。
今天,專門給大家寫一下将 yolov3/yolov4 模型轉為 caffe 模型的詳細步驟。
0. 系統環境
- Ubuntu 16.04
- cuda 9.x
1. 部署 caffe 環境
正常的方法是下載下傳 caffe 的源碼,進行編譯安裝。但是,這種方法比較複雜,不太容易成功。更簡單的方法是直接下載下傳 caffe1.x 的docker 鏡像。這種方法需要你提前在 Ubuntu 裡安裝了 nvidia-docker。
打開 docker hub 網站:
https://registry.hub.docker.com/搜尋 caffe,看到這個鏡像:
點選進去,看到該鏡像的下拉指令:
sudo docker pull bvlc/caffe
打開 Ubuntu 終端,輸入上面的下拉指令,将 caffe 的 docker 鏡像下載下傳下來。
下載下傳完成之後,終端輸入指令:
sudo docker images
就可以看到已下載下傳的 caffe 鏡像了。
為鏡像建立容器:
docker run --runtime=nvidia --name caffe -i -t bvlc/caffe /bin/bash
這裡我們給該容器起的名字是 caffe,大家可以自由設定,根據 `sudo docker ps -a` 這條指令來檢視各個容器。
這樣,我們就進入了 caffe1.x 的 docker 容器之内了。
該容器已部署好了 caffe1.x,caffe1.x 路徑為:
2. caffe 源碼修改
因為官方 caffe1.x 架構不支援 yolo3/yolov4 的 upsample 層,是以需要手動增加 upsample 層,對 caffe 源碼進行修改。
克隆 GitHub 上的轉換工具項目:
git clone https://github.com/ChenYingpeng/darknet2caffe.git
将 darknet2caffe/caffe_layers/mish_layer 下的 mish_layer.hpp 檔案和 darknet2caffe/tree/master/caffe_layers/upsample_layer 下的 upsample_layer.hpp 拷貝到容器的路徑:/opt/caffe/include/caffe/layers 下。
将 darknet2caffe/caffe_layers/mish_layer 下的 mish_layer.cpp、mish_layer.cu 檔案和 darknet2caffe/tree/master/caffe_layers/upsample_layer 下的 upsample_layer.cpp、upsample_layer.cu 拷貝到容器的路徑:/opt/caffe/src/caffe/layers/ 下。
将 darknet2caffe/caffe_layers/pooling_layer 下的 pooling_layer.cpp 拷貝到容器的路徑:/opt/caffe/src/caffe/layers/ 下。
然後,打開容器内的 caffe 檔案:/opt/caffe/src/caffe/proto/caffe.proto。按照如下說明修改相應字段的程式。
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
message LayerParameter {
optional TileParameter tile_param = 138;
optional VideoDataParameter video_data_param = 207;
optional WindowDataParameter window_data_param = 129;
++optional UpsampleParameter upsample_param = 149; //added by chen for Yolov3, make sure this id 149 not the same as before.
++optional MishParameter mish_param = 150; //added by chen for yolov4,make sure this id 150 not the same as before.
}
// added by chen for YoloV3
++message UpsampleParameter{
++ optional int32 scale = 1 [default = 1];
++}
// Message that stores parameters used by MishLayer
++message MishParameter {
++ enum Engine {
++ DEFAULT = 0;
++ CAFFE = 1;
++ CUDNN = 2;
++ }
++ optional Engine engine = 2 [default = DEFAULT];
++}
其中,++ 表示該行是增加的内容。
3. caffe 重新編譯
修改完 caffe 的一些源碼之後,需要對 caffe 重新編譯。
進入 /opt/caffe/build 目錄,輸入以下指令:
make clean
make all -j8
make pycaffe -j8
caffe 重新編譯之後,就可以對 yolov3/yolov4 模型進行 caffe 轉換了。
4. 模型轉換
準備好我們已有的 yolov3 模型的配置檔案和權重檔案,例如:yolov3.cfg 和 yolov3.weights。在 darknet2caffe 目錄下,輸入以下指令:
python darknet2caffe.py ./yolov3.cfg ./yolov3.weights ./yolov3.prototxt ./yolov3.caffemodel
如果輸出類似下面的語句,則證明轉換成功!
I0522 10:19:19.015708 25251 net.cpp:228] layer1-act does not need backward computation.
I0522 10:19:19.015712 25251 net.cpp:228] layer1-scale does not need backward computation.
I0522 10:19:19.015714 25251 net.cpp:228] layer1-bn does not need backward computation.
I0522 10:19:19.015718 25251 net.cpp:228] layer1-conv does not need backward computation.
I0522 10:19:19.015722 25251 net.cpp:228] input does not need backward computation.
I0522 10:19:19.015725 25251 net.cpp:270] This network produces output layer139-conv
I0522 10:19:19.015731 25251 net.cpp:270] This network produces output layer150-conv
I0522 10:19:19.015736 25251 net.cpp:270] This network produces output layer161-conv
I0522 10:19:19.015911 25251 net.cpp:283] Network initialization done.
unknow layer type yolo
unknow layer type yolo
save prototxt to ./yolov3.prototxt
save caffemodel to ./yolov3.caffemodel
其中,yolov3.prototxt 和 yolov3.caffemodel 為轉換後的 caffe 模型。
至此,yolov3/yolov4 轉換為 caffe 模型完成!