人脸识别-性别识别finetune

本文用记录基于Caffe的人脸性别识别过程。基于imdb-wiki模型做finetune,imdb-wiki数据集合模型可从这里下载:https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/。

准备训练环境

(1)准备OS:Ubuntu16.04

(2)安装Nvidia GPU Driver

https://www.nvidia.com/Download/index.aspx?lang=en-us

(3)安装CUDA

https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html

查看cuda版本的方法:

cat /usr/local/cuda/version.txt

(4)安装cnDNN(可选)

https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html

查看cudnn版本的方法:

cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

(5)安装Docker(可选)

https://docs.docker.com/install/linux/docker-ce/ubuntu/#set-up-the-repository

(6)安装Nvidia Docker(可选)

https://github.com/NVIDIA/nvidia-docker

(7)准备Docker Image(可选)

进入Container的方式之一:,

nvidia-docker exec -it $ContainerID /bin/bash

用nvidia-docker ps查看ContainerID。

准备模型及训练数据集

(1)     下载Imdb-wiki模型

https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/static/gender.caffemodel

https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/static/gender_train.prototxt

如果下载了imdb-wiki的数据集,可以通过如下方式读取数据集的描述文件:

import scipy.io as sio

mat_contents = sio.loadmat(‘wiki.mat‘)

(2)     下载celeba数据集

CelebA是CelebFaces Attribute的缩写,意即名人人脸属性数据集,其包含10,177个名人身份的202,599张人脸图片,每张图片都做好了特征标记,包含人脸bbox标注框、5个人脸特征点坐标以及40个属性标记,CelebA由香港中文大学开放提供,广泛用于人脸相关的计算机视觉训练任务,可用于人脸属性标识训练、人脸检测训练以及landmark标记等,可以从http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html下载img_align_celeba.zip即可。

(3)     生成celeba数据集的训练和测试描述文件

删除list_attr_celeba文件第一行后,提取性别属性:

cat list_attr_celeba | awk -F ‘ ’ ‘{print $1,$2}’ >gender.txt

计算图片文件数量:

cat list_attr_celeba | wc -l

对gender.txt文件行做shuffle:

cat gender.txt | awk  -F"\3" ‘BEGIN{srand();}{value=int(rand()*图片文件数量); print value"\3"$0 }‘ | sort | awk -F"\3" ‘{print $2}‘ >> shuffled

生成训练集:

head -n 图片文件数量*0.9 shuffled > train.txt

tail -n 图片文件数量*0.1 shuffled > test.txt

修改图片路径可能用到的VI命令:1,$ s/old/new/g

(4) 为了更好的识别亚洲人的性别,还可以通过爬取等方式收集标注来补充亚洲人的数据。

 训练模型

(1)准备solver.prototxt

Solver文件解释可参考:

https://github.com/BVLC/caffe/wiki/Solver-Prototxt

(更全面)https://zhuanlan.zhihu.com/p/48462756

net: “gender.prototxt”
test_iter: 100
test_interval: 500
test_compute_loss: true
base_lr: 0.00001
momentum: 0.95
type: “SGD”
weight_decay: 0.0005
lr_policy: “step”
gamma: 0.9
stepsize: 200
display: 100
max_iter: 20000
snapshot: 2000
snapshot_prefix: “gender”
solver_mode: GPU

(2) 修改gender.prototxt

name: "VGG_ILSVRC_16_layers"
layer {
  top: "data"
  type: "ImageData"
  top: "label"
  name: "data"
  transform_param {
    mirror: true
    crop_size: 224
    mean_file: "imagenet_mean.binaryproto"
  }
  image_data_param {
    source: "train.txt"
    batch_size: 32
    new_height: 256
    new_width: 256
  }
  include: { phase: TRAIN }
}
layer {
  top: "data"
  top: "label"
  name: "data"
  type: "ImageData"
  image_data_param {
    new_height: 256
    new_width: 256
    source: "train.txt"
    batch_size: 10
  }
  transform_param {
    crop_size: 224
    mirror: false
    mean_file: "imagenet_mean.binaryproto"
  }
  include: { phase: TEST }
}
layer {
  bottom: "data"
  top: "conv1_1"
  name: "conv1_1"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "relu1_1"
  type: "ReLU"
}
layer {
  bottom: "conv1_1"
  top: "conv1_2"
  name: "conv1_2"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv1_2"
  top: "conv1_2"
  name: "relu1_2"
  type: "ReLU"
}
layer {
  bottom: "conv1_2"
  top: "pool1"
  name: "pool1"
  type: "Pooling"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  bottom: "pool1"
  top: "conv2_1"
  name: "conv2_1"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 128
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv2_1"
  top: "conv2_1"
  name: "relu2_1"
  type: "ReLU"
}
layer {
  bottom: "conv2_1"
  top: "conv2_2"
  name: "conv2_2"

 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 128
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv2_2"
  top: "conv2_2"
  name: "relu2_2"
  type: "ReLU"
}
layer {
  bottom: "conv2_2"
  top: "pool2"
  name: "pool2"
  type: "Pooling"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  bottom: "pool2"
  top: "conv3_1"
  name: "conv3_1"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv3_1"
  top: "conv3_1"
  name: "relu3_1"
  type: "ReLU"
}
layer {
  bottom: "conv3_1"
  top: "conv3_2"
  name: "conv3_2"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv3_2"
  top: "conv3_2"
  name: "relu3_2"
  type: "ReLU"
}
layer {
  bottom: "conv3_2"
  top: "conv3_3"
  name: "conv3_3"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv3_3"
  top: "conv3_3"
  name: "relu3_3"
  type: "ReLU"
}
layer {
  bottom: "conv3_3"
  top: "pool3"
  name: "pool3"
  type: "Pooling"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  bottom: "pool3"
  top: "conv4_1"
  name: "conv4_1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }

  type: "Convolution"
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv4_1"
  top: "conv4_1"
  name: "relu4_1"
  type: "ReLU"
}
layer {
  bottom: "conv4_1"
  top: "conv4_2"
  name: "conv4_2"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv4_2"
  top: "conv4_2"
  name: "relu4_2"
  type: "ReLU"
}
layer {
  bottom: "conv4_2"
  top: "conv4_3"
  name: "conv4_3"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }

  type: "Convolution"
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv4_3"
  top: "conv4_3"
  name: "relu4_3"
  type: "ReLU"
}
layer {
  bottom: "conv4_3"
  top: "pool4"
  name: "pool4"
  type: "Pooling"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  bottom: "pool4"
  top: "conv5_1"
  name: "conv5_1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }

  type: "Convolution"
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv5_1"
  top: "conv5_1"
  name: "relu5_1"
  type: "ReLU"
}
layer {
  bottom: "conv5_1"
  top: "conv5_2"
  name: "conv5_2"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  type: "Convolution"
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv5_2"
  top: "conv5_2"
  name: "relu5_2"
  type: "ReLU"
}
layer {
  bottom: "conv5_2"
  top: "conv5_3"
  name: "conv5_3"
  type: "Convolution"
 param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv5_3"
  top: "conv5_3"
  name: "relu5_3"
  type: "ReLU"
}
layer {
  bottom: "conv5_3"
  top: "pool5"
  name: "pool5"
  type: "Pooling"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  bottom: "pool5"
  top: "fc6"
  name: "fc6"
 param {
    lr_mult: 10
    decay_mult: 1
  }
  param {
    lr_mult: 20
    decay_mult: 0
  }
  type: "InnerProduct"
  inner_product_param {
    num_output: 4096
  }
}
layer {
  bottom: "fc6"
  top: "fc6"
  name: "relu6"
  type: "ReLU"
}
layer {
  bottom: "fc6"
  top: "fc6"
  name: "drop6"
  type: "Dropout"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  bottom: "fc6"
  top: "fc7"
  name: "fc7"
 param {
    lr_mult: 10
    decay_mult: 1
  }
  param {
    lr_mult: 20
    decay_mult: 0
  }
  type: "InnerProduct"
  inner_product_param {
    num_output: 4096
  }
}
layer {
  bottom: "fc7"
  top: "fc7"
  name: "relu7"
  type: "ReLU"
}
layer {
  bottom: "fc7"
  top: "fc7"
  name: "drop7"
  type: "Dropout"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  bottom: "fc7"
  top: "fc8-2"
  name: "fc8-2"
 param {
    lr_mult: 10
    decay_mult: 1
  }
  param {
    lr_mult: 20
    decay_mult: 0
  }
  type: "InnerProduct"
  inner_product_param {
    num_output: 2
  weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  bottom: "fc8-2"
  bottom: "label"
  name: "loss"
  type: "SoftmaxWithLoss"
  include: { phase: TRAIN }
}

layer {
  name: "prob"
  type: "Softmax"
  bottom: "fc8-2"
  top: "prob"
    include {
    phase: TEST
  }
}
layer {
  name: "accuracy_train_top01"
  type: "Accuracy"
  bottom: "fc8-2"
  bottom: "label"
  top: "accuracy_train_top01"
  include {
    phase: TEST
  }
}

imagenet_mean.binaryproto 文件的生成可参考https://github.com/BVLC/caffe/blob/master/examples/imagenet/make_imagenet_mean.sh

或直接从网上下载。

(3)启动训练

caffe train –sovler=pathto/solver.prototxt –weight=pathtto/gender.caffemodel –gpu all

(4)使用训练的模型

实际应用中,我们首先采用人脸检测技术检测人脸,将图片中的人脸取裁剪出来送入训练好的模型进行性别识别。人脸检测技术可以采用dlib库,dlib库人脸检测支持根据具体应用场景进行finetune。

原文地址:https://www.cnblogs.com/dskit/p/10269502.html

时间: 2024-11-06 16:33:06

人脸识别-性别识别finetune的相关文章

C++开发人脸性别识别教程(5)——通过FaceRecognizer类实现性别识别

在之前的博客中已经解决了人脸检测的问题,我们计划在这篇博客中介绍人脸识别.性别识别方面的相关实现方法. 其实性别识别和人脸识别本质上是相似的,因为这里只是一个简单的MFC开发,主要工作并不在算法研究上,因此我们直接将性别识别视为一种特殊的人脸识别模式.人脸识别可能需要分为几十甚至上百个类(因为有几十甚至上百个人),而性别识别则是一种特殊的人脸识别——只有两个类. 一.基本工具 通过OpenCv进行性别识别的基本工具是FaceRecognizer.这是OpenCv2.x版本中的一个基本的人脸识别类

C++开发人脸性别识别教程(17)——添加辅助功能

在之前的博文中已经将性别识别的部分叙述的基本完整,整个程序的开发也接近尾声,在这篇博文中我们再为程序添加三个小的辅助功能:人脸批量分割.文件名修改.方法验证. 一.人脸批量分割 在前面的博文中提到过,进行性别识别训练所用到的训练样本是分割好的男性样本和女性样本,那么如何去制作这些训练样本呢?这就需要进行人脸图像的批量人脸分割. 1.1 添加控件 首先添加一个“人脸批量分割”的按钮:

C++开发人脸性别识别教程(16)——视频人脸性别识别

在之前的博文中我们已经能够顺利驱动摄像头来采集源图像,在这篇博文中将正式为其加入性别识别的代码,实现摄像头视频的人脸性别识别. 一.人脸检测 在得到摄像头采集的源图像之后,首先要做的就是对其进行人脸检测,将人脸区域分割出来.这步相对来说比较简单,只需在定时器时间触发函数中加入人脸检测的代码即可,这里给出OnTimer()函数的整体代码: void CGenderRecognitionMFCDlg::OnTimer(UINT_PTR nIDEvent) { /***********人脸检测并识别*

C++开发人脸性别识别教程(13)——针对单张图片的性别识别

在之前的博文中我们的性别识别程序已经初步成型,能够识别某个文件夹下的图片文件.不过这里有一个问题,假设这个文件夹下有着大量的图片,而我们希望识别这些图片中的某一张,此时需要我们不停的单击“下一张”按钮才会轮询到对应的图片,这是相当麻烦的,因此在这篇博客中我们向程序中添加一个功能——单张图片的性别识别. 一.基本思想 最基本的办法就是在主界面再添加一个按钮控件,命名为“图片文件”(之前的按钮为“图片文件夹”),不过这样会使得界面上的按钮控件过于繁多,给人一种“作者只会用button控件”的感觉.这

C++开发人脸性别识别总结

历时一个月,终于在昨天把<C++开发人脸性别识别总结>系列博客完成了,第一篇博客发表在2015年12月29日,截止昨天2016年2月29日最后一篇完成,去除中间一个月的寒假,正好一个月,首先这里把这系列博客的地址呈上:C++开发人脸性别识别教程. 在发牢骚之前首先强调几个重要问题: (1)在程序中存在一个小的易触发的BUG,就是”初始化“按钮对应的事件触发函数OnBnClickedButtonInitial()中有一句这样的代码: 在实际编程过程中经常需要对代码进行规范化,如果你习惯通过“ct

C++开发人脸性别识别教程(18)——辅助功能之文件名批量修改、方法验证

时光推移了30多天,这个人脸性别识别的小项目也接近尾声了,预计再通过三篇博文的篇幅来完成这个项目的收尾工作.在这篇博文中我们再为程序添加另外两个小的辅助功能:文件名批量修改.方法验证. 一 文件名批量修改 批量修改文件名是一件很基础也很常用的小操作,核心操作就是图像文件的批量读取.批量改名.批量保存.基本思想就是把文件读出来,然后在保存回去(注意不要和别的文件发生覆盖),从这个角度来讲文件名批量修改与上一篇博客C++开发人脸性别识别教程(17)——辅助功能之人脸批量分割中的人脸批量分割简直如出一

C++开发人脸性别识别教程(7)——搭建MFC框架之界面绘制

在之前的博客中我们已经将项目中用到的算法表述完毕,包括人脸检测算法以及四种性别识别算法,在这篇博客中我们将着手搭建基本的MFC框架. 一.框架概况 在这篇博文中我们将搭建最基本的MFC框架,绘制MFC界面. 二.搭建流程 1.新建一个MFC工程并配置OpenCv 打开VS,按下“ctrl+n”,在新建窗口中选择“MFC应用程序”,命名为GenderRecognitionMFC: 单击确定,程序类型选择“基于对话框”,MFC使用选择“在静态库中使用MFC”: 直接单击“完成”,创建完毕.OpenC

(转)C++开发人脸性别识别教程(3)——OpenCv配置和ImageWatch插件介绍

原文地址:http://blog.csdn.net/u013088062/article/details/50435079 OpenCv是C++图像处理的重要工具,这个人脸性别识别的项目就是借助OpenCv进行开发的.虽然网上已经有了很多关于OpenCv的配置教程,但出于教程完整性考虑,这里还是用专门的一篇博客来介绍OpenCv的具体配置方法,同时也介绍一下OpenCv中的一个强有力的图像处理插件——ImageWatch. 由于这个程序是一年前写的,当时的OpenCv的最新版本为2.4.9(现在

C++开发人脸性别识别教程(6)——通过SVM实现性别识别

上一篇教程中我们介绍了怎样使用OpenCv封装的FaceRecognizer类实现简单的人脸性别识别,这里我们为大家提供第二种主要的性别识别手段--支持向量机(SVM). 支持向量机在解决二分类问题方面有着强大的威力(当然也能够解决多分类问题).性别识别是典型的二分类模式识别问题,因此非常适合用SVM进行处理,同一时候OpenCv又对SVM进行了非常好的封装,调用非常方便,因此我们在这个性别识别程序中考虑增加SVM方法. 在这里我们採用了HOG+SVM的模式来进行,即先提取图像的HOG特征.然后