本文用记录基于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,$22}' >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。

基于人脸识别+IMDB-WIFI+Caffe的性别识别的更多相关文章

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

    在之前的博客中已经攻克了人脸检測的问题,我们计划在这篇博客中介绍人脸识别.性别识别方面的相关实现方法. 事实上性别识别和人脸识别本质上是相似的,由于这里仅仅是一个简单的MFC开发,主要工作并不在算法研 ...

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

    在之前的博文中我们已经可以顺利驱动摄像头来採集源图像.在这篇博文中将正式为其加入性别识别的代码,实现摄像头视频的人脸性别识别. 一.人脸检測 在得到摄像头採集的源图像之后,首先要做的就是对其进行人脸检 ...

  3. C++开发人脸性别识别教程(12)——加入性别识别功能

    经过之前几篇博客的解说,我们已经成功搭建了MFC应用框架,并实现了主要的图像显示和人脸检測程序,在这篇博文中我们要向当中加入性别识别代码. 关于性别识别,之前已经专门拿出两篇博客的篇幅来进行解说.这里 ...

  4. 基于深度学习的人脸性别识别系统(含UI界面,Python代码)

    摘要:人脸性别识别是人脸识别领域的一个热门方向,本文详细介绍基于深度学习的人脸性别识别系统,在介绍算法原理的同时,给出Python的实现代码以及PyQt的UI界面.在界面中可以选择人脸图片.视频进行检 ...

  5. 人脸和性别识别(基于OpenCV)

    描写叙述 人脸识别包含四个步骤 人脸检測:定位人脸区域,仅仅关心是不是脸: 人脸预处理:对人脸检測出来的图片进行调整优化. 收集和学习人脸:收集要识别的人的预处理过的人脸,然后通过一些算法去学习怎样识 ...

  6. 基于OpenCV性别识别

    叙述性说明 所谓的性别识别推断检测到的面部是男性还是女性.它是一个二值分类问题. 识别算法可以用于SVM,BP神经网络.LDA,PCA,PCA+LDA等等.OpenCV官网给出的文档是基于Fisher ...

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

    在之前的博客中我们已经将项目中用到的算法表述完成,包含人脸检測算法以及四种性别识别算法,在这篇博客中我们将着手搭建主要的MFC框架. 一.框架概况 在这篇博文中我们将搭建最主要的MFC框架.绘制MFC ...

  8. python手写bp神经网络实现人脸性别识别1.0

    写在前面:本实验用到的图片均来自google图片,侵删! 实验介绍 用python手写一个简单bp神经网络,实现人脸的性别识别.由于本人的机器配置比较差,所以无法使用网上很红的人脸大数据数据集(如lf ...

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

    历时一个月,最终在昨天把<C++开发人脸性别识别总结>系列博客完毕了,第一篇博客发表在2015年12月29日,截止昨天2016年2月29日最后一篇完毕,去除中间一个月的寒假,正好一个月,首 ...

随机推荐

  1. Kafaka高可用集群环境搭建

    zk集群环境搭建:https://www.cnblogs.com/toov5/p/9897868.html 三台主机每台的Java版本1.8 下面kafka集群的搭建:  3台虚拟机均进行以下操作:  ...

  2. 算法总结之 在单链表和双链表中删除倒数第k个节点

    分别实现两个函数,一个可以删除单链表中倒数第k个节点,另一个可以删除双链表中倒数第k个节点 思路: 如果链表为空,或者k<1 参数无效 除此之外 让链表从头开始走到尾,每移动一步,就让k的值减1 ...

  3. AJAX跨域资源共享 CORS 详解

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing). 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从 ...

  4. c#.NET中日志信息写入Windows日志中解决方案

    1. 目的应用系统的开发和维护离不开日志系统,选择一个功能强大的日志系统解决方案是应用系统开发过程中很重要的一部分.在.net环境下的日志系统解决方案有许多种,log4net是其中的佼佼者.在Wind ...

  5. Spark-运行时架构

    Spark运行时架构 在分布式环境下,Spark集群采用的时主/从结构.在一个Spark集群中,有一个节点负责中央协调,调度各个分布式工作节点.这个中央协调节点被称为驱动器(Driver),与之对应的 ...

  6. vue中编辑代码是不注意格式时会报错

    1.是因为我们使用了eslint的代码规范,我们不要使用这种规范就好 2.在build目录下找到webpack.base.conf.js 在里面找到关于eslint的相关配置注释或移除掉就好

  7. 【转】Oracle中插入和取出图片(用BLOB类型)

    原文地址:http://czllfy.iteye.com/blog/66737 其他参考资料地址:http://lavasoft.blog.51cto.com/62575/321882/ 要在orac ...

  8. Node.js初接触(一)

    本来还在纠结着到底要学哪一种后台语言呢,突然发现node.js很火,既然能被这么多人推崇,自然是有他的优势的.去百度百科看了一眼,或许是我理解能力太差,并没有了解到很多关于node.js的东西,大概就 ...

  9. python中的列表和字典(二)

    三. 字典以及相关使用 1. 字典的定义 dict{} 2. 字典特征:字典是无序的,key-value键值对形式,key值不重复 3. 字典的赋值:dictA = {keyA: valueA, ke ...

  10. uva 11088 暴力枚举子集/状压dp

    https://vjudge.net/problem/UVA-11088 对于每一种子集的情况暴力枚举最后一个三人小组取最大的一种情况即可,我提前把三个人的子集情况给筛出来了. 即 f[S]=MAX{ ...