1. 程式人生 > >【Caffe】多標籤訓練、人臉屬性多工訓練

【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++部署程式碼