win7第一个caffe实验【识别人脸年龄和性别】

来源:互联网 发布:搞怪软件有哪些 编辑:程序博客网 时间:2024/06/07 17:41

一、环境配置

http://blog.csdn.net/ITSophia/article/details/77799927

环境配置好以后,可以直接用网上的模型先测试一下正确率 http://www.openu.ac.il/home/hassner/projects/cnn_agegender/

下载下来这个压缩包cnn_age_gender_models_and_data.0.0.2.zip,里面是训练好的caffe模型(.caffemodel)和网络结构(.prototxt),用python自己写了一个图片预处理的文件和加载caffe模型的程序,测试了30张图片,运行结果发现性别正确率还行,但是年龄差距就太大了。于是重新训练


二、选择数据

选择数据是很重要的一步骤,因为很多数据源脏数据很多,可以先用python分析一遍数据源,数据源地址:http://www.openu.ac.il/home/hassner/Adience/data.html#agegender

可以从该网站提供的FTP:agas.openu.ac.il上下载数据源,通过Python分析得到的数据情况为:


发现根据我划分的年龄段,数据源中的(38, 48),(8, 23)年龄段就不在这个范围内,但是已经很大程度上涵盖了,因此剔除了这两个年龄段的数据图片,数量也就是个位数,相较于一万多张图片来说是比较好的年龄段划分了。

还有性别的图片数据比例


训练集、验证集、测试集的划分数量为:


写一个Python脚本,来整理出需要的训练集、验证集图片,以及对应的txt文件,txt文件里的内容是图片名称(如果train文件夹下的图片还有子目录,记得txt文件里的图片名称前要带上子目录的名称的,生成LDMB文件时会用到,幸好下载下来的数据源里的文件名称都正常的)

三、将图片数据转化成LDMB格式

训练集和验证集的准备,以及标签文件的准备可以参考博文:http://www.cnblogs.com/TensorSense/p/6744075.html

虽然caffe是可以直接读图片的,但因为训练的数据很多,所以一般都会选择转换成LDMB(caffe认识图片的格式),生成LDMB非常简单。我们配caffe时,需要在C++里编译很多项目,编译好后会在C:\caffe-master\Build\x64\Release目录下生成convert_imageset.exe,这就是用来帮我们转成LDMB的工具。

现在,我把训练和验证的图片以及对应的train_gender.txt和val_gender.txt放在F:\analyseData\train和F:\analyseData\val目录下,在F:\analyseData目录下新建 comput_image_mean.txt

C:\caffe-master\Build\x64\Release\convert_imageset.exe train/ train_gender.txt train_lmdb -backend=lmdb -resize_height=227 -resize_width=227 -shuffle   pause 

主要是对参数的理解:

C:\caffe-master\Build\x64\Release\convert_imageset.exe:工具convert_imageset.exe的路径

train/ train_gender.txt : train_gender.txt和训练图片位于train/目录下,这里使用的是相对路径,相对路径的root与新建的comput_image_mean.txt的root相同,也就是F:\analyseData。这里记得/后面有个空格!为了读取train_gender.txt文件里每一行数据,数据中开头也是目录名!

train_lmdb: 生成的ldmb的文件夹名称

可以调整图片尺寸统一为227*227,shuffle表示打乱训练数据

生成的LDMB如下:


四、计算训练样本的均值

http://blog.csdn.net/hong__fang/article/details/52425105

(1)编译caffe-windows-master\tools\ 下的compute_image_mean.cpp,生成compute_image_mean.exe;

(2)创建comput_image_mean.txt,添加内容:

SET GLOG_logtostderr=1  C:\caffe-master\Build\x64\Release\compute_image_mean.exe  F:\analyseData\train_lmdb  F:\analyseData\myimg_mean.binaryproto  pause 
然后将.txt改为.bat,双击运行


目录下就生成了myimg_mean.binaryproto文件

五、网络定义及设置

在caffe自带的模型下,可以找到一些网络的实例,可以通过修改这些网络里的配置文件来训练自己的模型

C:\caffe-master\models目录下找一个net的


train_test.prototxt文件:训练网络用这个配置文件

deploy.prototxt文件: 训练完后,用来测试模型的配置文件

如果要把训练好的模型拿来测试新的图片,那必须得要一个deploy.prototxt文件,这个文件实际上和test.prototxt文件差不多,只是头尾不相同而已。deploy文件没有第一层数据输入层,也没有最后的Accuracy层,但最后多了一个Softmax概率层。

http://blog.csdn.net/lg1259156776/article/details/52550865

这篇博文讲得很详细!关于网络的配置

http://blog.csdn.net/haoji007/article/details/53911753

这篇文章详细分析了网络配置里各个参数的含义(老师的博客哦~大赞!)

一开始随便在caffe里拿了一个网络,直接跑我的数据,结果跑了一天一夜,内存占用率98%还停不下来,发现网络里的参数都设置的太大了!于是根据我的10000张训练图片,4000张验证图片的数据量,重新配置网络参数

参数的配置原则:

test_iter*batch_size=val_num

test_interval*batch_size=train_num

base_lr 一般设置为0.01

一般不去改动gamma,momentum,weight_decay


train_val.prototxt:

name: "CaffeNet"layer {  name: "data"  type: "Data"  top: "data"  top: "label"  include {    phase: TRAIN                                                      #训练网络的数据结构  }  transform_param {     mirror: true                                                      #使用镜像    crop_size: 227                                                    #将数据裁剪为227    mean_file: "F:/analyseData/myimg_mean.binaryproto"                #训练集的均值文件  }  data_param {    source: "F:/analyseData/train_lmdb"                               #训练数据集    batch_size: 40                                                    #一次迭代输入的图片数量    backend: LMDB                                                     #数据集的格式  }}layer {  name: "data"  type: "Data"  top: "data"  top: "label"  include {    phase: TEST                                                       #网络验证的数据结构  }  transform_param {    mirror: false    crop_size: 227    mean_file: "F:/analyseData/valimg_mean.binaryproto"  }  data_param {    source: "F:/analyseData/val_lmdb"    batch_size: 50    backend: LMDB  }}layer {  name: "conv1"                                                         type: "Convolution"                                                #卷积层  bottom: "data"                                                     #卷积层1的下面一层是数据层,上面一层是自己,因为要反向传播  top: "conv1"  convolution_param {    num_output: 96                                                   #该层的输出的特征图个数,即改用多少个卷积核去对输入做卷积    kernel_size: 7                                                   #卷积核的尺寸    stride: 4                                                        #卷积的步长  }}layer {  name: "relu1"  type: "ReLU"                                   bottom: "conv1"  top: "conv1"}layer {  name: "pool1"  type: "Pooling"  bottom: "conv1"  top: "pool1"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layer {  name: "norm1"  type: "LRN"  bottom: "pool1"  top: "norm1"  lrn_param {    local_size: 5    alpha: 0.0001    beta: 0.75  }}layer {  name: "conv2"  type: "Convolution"  bottom: "norm1"  top: "conv2"  convolution_param {    num_output: 256    pad: 2    kernel_size: 5  }}layer {  name: "relu2"  type: "ReLU"  bottom: "conv2"  top: "conv2"}layer {  name: "pool2"  type: "Pooling"  bottom: "conv2"  top: "pool2"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layer {  name: "norm2"  type: "LRN"  bottom: "pool2"  top: "norm2"  lrn_param {    local_size: 5    alpha: 0.0001    beta: 0.75  }}layer {  name: "conv3"  type: "Convolution"  bottom: "norm2"  top: "conv3"  convolution_param {    num_output: 384    pad: 1    kernel_size: 3  }}layer{  name: "relu3"   type: "ReLU"  bottom: "conv3"  top: "conv3"}layer {  name: "pool5"  type: "Pooling"  bottom: "conv3"  top: "pool5"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layer {  name: "fc6"  type: "InnerProduct"  bottom: "pool5"  top: "fc6"  inner_product_param {    num_output: 512  }}layer {  name: "relu6"  type: "ReLU"  bottom: "fc6"  top: "fc6"}layer {  name: "drop6"  type: "Dropout"  bottom: "fc6"  top: "fc6"  dropout_param {    dropout_ratio: 0.5  }}layer {  name: "fc7"  type: "InnerProduct"  bottom: "fc6"  top: "fc7"  inner_product_param {    num_output: 512  }}layer {  name: "relu7"  type: "ReLU"  bottom: "fc7"  top: "fc7"}layer {  name: "drop7"  type: "Dropout"  bottom: "fc7"  top: "fc7"  dropout_param {    dropout_ratio: 0.5  }}layer {  name: "fc8"  type: "InnerProduct"  bottom: "fc7"  top: "fc8"  inner_product_param {    num_output: 2                                                      #最后一层输出是类别数目,因为这个性别分两类,所以输出是2  }}layer {  name: "accuracy"  type: "Accuracy"  bottom: "fc8"  bottom: "label"  top: "accuracy"  include {    phase: TEST  }}layer {  name: "loss"  type: "SoftmaxWithLoss"  bottom: "fc8"  bottom: "label"  top: "loss"}


solver.prototxt:

net: "F:/analyseData/caffe/train_val.prototxt"   #训练网络的配置路径test_iter: 80                                    #网络的测试迭代次数,网络一次迭代将对一个batch_size的图片进行测试,要测试验证集中的所有图片test_interval: 250                               #网络迭代多少次进行一次测试。一次迭代即一个batch_size的图片通过网络正向传播和反向传播的过程
base_lr: 0.01                                    #网络的基础学习率,一般设置为0.01lr_policy: "step"                                #学习率变化gamma: 0.1                                       #学习率变化比率,一般不改stepsize: 2218                                   #每多少次学习率递减(迭代多少次)display: 20                                      #每多少次显示一次max_iter: 6720                                   #网络的最大迭代次数。反复训练训练集的图片momentum: 0.9                                    #学习的参数,一般不改weight_decay: 0.0001                             snapshot: 224                                    #每224次保存一次学习的结果,即caffemodelsnapshot_prefix: "F:/analyseData/caffe/caffenet_train" solver_mode: CPU

deploy_gender.prototxt:这个和train_val.prototxt几乎一样,除了首尾的地方

name: "CaffeNet"input: "data"input_dim: 1input_dim: 3input_dim: 227input_dim: 227layers {  name: "conv1"  type: CONVOLUTION  bottom: "data"  top: "conv1"  convolution_param {    num_output: 96    kernel_size: 7    stride: 4  }}layers {  name: "relu1"  type: RELU  bottom: "conv1"  top: "conv1"}layers {  name: "pool1"  type: POOLING  bottom: "conv1"  top: "pool1"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layers {  name: "norm1"  type: LRN  bottom: "pool1"  top: "norm1"  lrn_param {    local_size: 5    alpha: 0.0001    beta: 0.75  }}layers {  name: "conv2"  type: CONVOLUTION  bottom: "norm1"  top: "conv2"  convolution_param {    num_output: 256    pad: 2    kernel_size: 5  }}layers {  name: "relu2"  type: RELU  bottom: "conv2"  top: "conv2"}layers {  name: "pool2"  type: POOLING  bottom: "conv2"  top: "pool2"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layers {  name: "norm2"  type: LRN  bottom: "pool2"  top: "norm2"  lrn_param {    local_size: 5    alpha: 0.0001    beta: 0.75  }}layers {  name: "conv3"  type: CONVOLUTION  bottom: "norm2"  top: "conv3"  convolution_param {    num_output: 384    pad: 1    kernel_size: 3  }}layers{  name: "relu3"   type: RELU  bottom: "conv3"  top: "conv3"}layers {  name: "pool5"  type: POOLING  bottom: "conv3"  top: "pool5"  pooling_param {    pool: MAX    kernel_size: 3    stride: 2  }}layers {  name: "fc6"  type: INNER_PRODUCT  bottom: "pool5"  top: "fc6"  inner_product_param {    num_output: 512  }}layers {  name: "relu6"  type: RELU  bottom: "fc6"  top: "fc6"}layers {  name: "drop6"  type: DROPOUT  bottom: "fc6"  top: "fc6"  dropout_param {    dropout_ratio: 0.5  }}layers {  name: "fc7"  type: INNER_PRODUCT  bottom: "fc6"  top: "fc7"  inner_product_param {    num_output: 512  }}layers {  name: "relu7"  type: RELU  bottom: "fc7"  top: "fc7"}layers {  name: "drop7"  type: DROPOUT  bottom: "fc7"  top: "fc7"  dropout_param {    dropout_ratio: 0.5  }}layers {  name: "fc8"  type: INNER_PRODUCT  bottom: "fc7"  top: "fc8"  inner_product_param {    num_output: 2  }}layers {  name: "prob"  type: SOFTMAX  bottom: "fc8"  top: "prob"}

网络配置文件准备完毕后吗,写一个train_myimg.txt,编辑完后,将txt改为.bat,双击运行即可

SET GLOG_logtostderr=1  C:\caffe-master\Build\x64\Release\caffe.exe  train --solver=F:\analyseData\caffe\solver.prototxt  pause 


C:\caffe-master\Build\x64\Release\caffe.exe   表示caffe.exe的位置

train  表示用来训练模型

--solver=F:\analyseData\caffe\solver.prototxt  整体配置文件的路径

 

运行不通过往往都是因为 train_val.prototxt里面格式写错了

比如:Error parsing text-format caffe.NetParameter: 43:9: Expected string

这是因为不同版本layerlayers不一样,一个文件中不要又有layer,又有layers

而且在layer层里,type类型需要用" "括起来,并且是有指定类型的,区分大小写


训练结束后:


训练时,在同样的accuracy下,loss不断下降,表示训练正常,如果Loss不下降,就表示不收敛


 
阅读全文
0 0