【Caffe】多标签训练、人脸属性多任务训练

版权声明:本文为博主Hans原创文章,未经博主Hans允许不得转载。http://blog.csdn.net/renhanchi https://blog.csdn.net/renhanchi/article/details/81903684

前言

参考了https://zhuanlan.zhihu.com/p/22190532

细节有一些问题,我这里过一遍整个流程,涉及到的问题都会做讲解。包括部署问题,最后我也会讲讲。

文中涉及到的我用的代码都在这里:https://github.com/HandsomeHans/Face-Attributes-MultiTask-Classification

正文

去原作者github网站下载https://github.com/HolidayXue/CodeSnap这个项目。

将convert_multilabel.cpp放到caffe/tools/目录下。

修改81行:

‘>>’ should be ‘> >’

然后注释掉149行。

命令行在caffe/下运行:

make clean
make all -j8
make py

我是用的CelebA数据集,都是人脸属性的。

下载地址:https://pan.baidu.com/s/17rp2gKqtvuT48yuPfJK3sA

在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 更新】-----------------------------------------------

在验证集和测试集上结果都很美好,但是拿摄像头或者视频实际应用的时候效果差的离谱。

-----------------------------------------------------------------------------

最后改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++部署代码

猜你喜欢

转载自blog.csdn.net/renhanchi/article/details/81903684