【Caffe】多標籤訓練、人臉屬性多工訓練
前言
細節有一些問題,我這裡過一遍整個流程,涉及到的問題都會做講解。包括部署問題,最後我也會講講。
正文
將convert_multilabel.cpp放到caffe/tools/目錄下。
修改81行:
‘>>’ should be ‘> >’
然後註釋掉149行。
命令列在caffe/下執行:
make clean
make all -j8
make py
我是用的CelebA資料集,都是人臉屬性的。
在Anno目錄下找到list_attr_celeba.txt
先命令列執行:
sed -i 's/ / /g' list_attr_celeba.txt
將文件中兩個空格都替換為一個空格。
然後可以通過下面程式碼提取你想要的人臉屬性
#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ Created on Mon Aug 20 16:57:52 2018 @author: hans """ ReadTxt = 'list_attr_celeba.txt' WriteTxt = 'train.txt' r = open(ReadTxt,'r') w = open(WriteTxt,'w') rLine = r.readline().split('\n')[0] while rLine: rLine = r.readline().split('\n')[0] if not rLine: break # image,bangs,eyeglasses,gender, wLine = rLine.split(' ')[0]+' '+rLine.split(' ')[6]+' '+rLine.split(' ')[16]+' '+rLine.split(' ')[21]+'\n' w.write(wLine) r.close() w.close()
接著命令列執行:
sed -i 's/-1/0/g' train.txt
將train.txt文件中-1改成索引0。
對比了一下原圖片,提取的屬性是對的。
然後從train.txt拿出了一部分放到val.txt中
執行指令碼,生成可供訓練用的lmdb資料:
echo "Creating train lmdb..." ~/caffe-multi/build/tools/convert_multilabel \ -resize_height=227 \ -resize_width=227 \ -shuffle=false \ /home/hans/data/face/CelebA/Img/img_align_celeba/ \ train.txt \ ./train_db \ ./train_lb \ 3 echo "Creating val lmdb..." ~/caffe-multi/build/tools/convert_multilabel \ -resize_height=227 \ -resize_width=227 \ -shuffle=false \ /home/hans/data/face/CelebA/Img/img_align_celeba/ \ val.txt \ ./val_db \ ./val_lb \ 3
img_align_celeba是切好人臉的資料集
後面引數3表示我這邊提取了三種人臉屬性。
最後是修改mcnn_Attri.prototxt,均值,歸一化,資料路徑,還有一個很重要,backend一定要改成LMDB!
name: "MCNN_Attri"
layer {
name: "data"
type: "Data"
top: "data"
transform_param {
scale: 0.007843
mean_value: 127.5
mean_value: 127.5
mean_value: 127.5
crop_size: 227
}
include {
phase: TRAIN
}
data_param {
source: "/home/hans/data/face/CelebA/attri/doc/train_db"
batch_size: 192
backend: LMDB
}
}
layer {
name: "labels"
type: "Data"
top: "labels"
include {
phase: TRAIN
}
data_param {
source: "/home/hans/data/face/CelebA/attri/doc/train_lb"
batch_size: 192
backend: LMDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
transform_param {
scale: 0.007843
mean_value: 127.5
mean_value: 127.5
mean_value: 127.5
crop_size: 227
}
include {
phase: TEST
}
data_param {
source: "/home/hans/data/face/CelebA/attri/doc/val_db"
batch_size: 128
backend: LMDB
}
}
layer {
name: "labels"
type: "Data"
top: "labels"
include {
phase: TEST
}
data_param {
source: "/home/hans/data/face/CelebA/attri/doc/val_lb"
batch_size: 128
backend: LMDB
}
}
layer {
name: "sliceL"
type: "Slice"
bottom: "labels"
top: "label_attr6"
top: "label_attr16"
top: "label_attr21"
slice_param {
slice_dim: 1
slice_point: 1
slice_point: 2
}
}
有三個輸出,slice_point刪到2。
【2018.08.22 更新】-----------------------------------------------
這個網路結構在bn2後分成了六組,每一組都有不同個輸出。並且每一組前面都有結構一樣的層,然後到各個任務的全連線層和最終輸出層。將對應不需要的任務層和組刪掉。對於我這三個類別,我發現gender是單獨一組的,眼鏡在第四組,劉海在第六組。為了減少引數量,我將眼鏡和劉海都放到了第六組,刪除了第四組的前面網路。第一組gender的我暫時沒改,擔心三個任務都放到一組裡出現不收斂的情況。不過以後我肯定會做測試。
(訓練輸出很好,在驗證集上準確率非常高,但是實際檢測的時候發現對單獨在一組的性別分別準確,對眼鏡和劉海分別不準確。我下一步還是要將眼鏡和劉海分別放在一組,並且將全連線層改成全域性平均池化。)
(將劉海和眼鏡分別放在了一組,同時刪了全連線層。模型是變小了,只有8M了。驗證集準確率還挺高,98%左右,但是實際實驗效果太差。接下來嘗試換換核心網路,用mobilenet v2或者squeezenet試試。同時我考慮到可能不一定是網路的原因,觀察了一下資料集,有劉海和戴眼鏡的圖片很少。如果換網路也不行,那麼下一步應該要對部分資料做argument了。)
-------------------------------------------------------------------------
【2018.08.29 更新】-----------------------------------------------
在驗證集和測試集上結果都很美好,但是拿攝像頭或者視訊實際應用的時候效果差的離譜。
找到原因了,是我測試時候的預處理方式不對導致的。
-----------------------------------------------------------------------------
【2018.09.04 更新】-----------------------------------------------
幾點心得:
1. 用全卷積+全域性池化替代全連線層,效果影響不大,模型引數量不變。
2.全連線層引數量大,但執行時間很快。也就是說全連線層對模型執行時間影響不大,對模型大小影響較大。
3.查看了每一層的執行時間,發現大卷積核效率很低,最好都改用3*3的小卷積核。
4.卷基層輸出數量最好是2^n。
-----------------------------------------------------------------------------
最後改loss_weight,所有任務的loss_weight加一起等於1。我這裡只有三個任務,所以loss_weight我都設定為0.3333了。
剩下的solver.prototxt我就不說了,跟單任務的一樣。
最後放一張訓練輸出截圖:
後面我會持續更新。。。
1.視覺化程式碼 2018.08.21 已上傳到github, show.py
2.caffe-python推理程式碼 2018.08.21 已上傳到github, face_attri.py
3.ncnn-C++部署程式碼