Deep Learning学习 – VGG-Face网络人脸识别

  • Post author:
  • Post category:其他



记录一下使用VGGNet进行人脸识别的实验过程。


  • 数据集:

    训练集 9W+张人脸图片,包含10000 ID。




1.数据集准备




将数据集图片分为训练集以及测试集两个部分,并生成标签文件,记录在.txt文件中。训练与测试图片比例为4:1。


import os,shutil
trainFile = open('train.txt','w')  
testFile = open('test.txt','w')
path = 'train' #原始图片数据路径
dirs = os.listdir(path)
for d in dirs:
    print d
    files = os.listdir(path+'/'+d)
    for i,f in enumerate(files):
        if i<8:
            trainFile.write(f+' '+d+'\n') #记录形式:图片名字 标签(中间有一个空格)  
            shutil.copy(path+'/'+d+'/'+f,'trainset/'+f)  #训练集
        else:
            testFile.write(f+' '+d+'\n')
            shutil.copy(path+'/'+d+'/'+f,'testset/'+f)   #测试集
trainFile.close()
testFile.close()



数据集要尽量大,否则可能最后训练结构不太好。



2.将

图片转换成lmdb格式并求均值


下载caffe代码并编译通过。在该目录下新建文件夹vggface,并将测试集trainset和训练集testset以及标签文件train.txt和test.txt移动到此处。



下面编写脚本文件生成lmdb格式图片。新建vggface.sh,


脚本代码是在网上借鉴修改后的,直接贴出来。图片大小被转为224*224,这是VGG处理图片的格式大小。写好脚本文件后,输入sh vggface.sh即可生成对应两个lmdb格式文件face_train_lmdb和face_test_lmdb。


#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs

EXAMPLE=vggface
DATA=vggface
TOOLS=./build/tools

TRAIN_DATA_ROOT=vggface/train/
VAL_DATA_ROOT=vggface/val/

# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=true
if $RESIZE; then
  RESIZE_HEIGHT=224
  RESIZE_WIDTH=224
else
  RESIZE_HEIGHT=0
  RESIZE_WIDTH=0
fi

if [ ! -d "$TRAIN_DATA_ROOT" ]; then
  echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
  echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
       "where the ImageNet training data is stored."
  exit 1
fi

if [ ! -d "$VAL_DATA_ROOT" ]; then
  echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
  echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
       "where the ImageNet validation data is stored."
  exit 1
fi

echo "Creating train lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset.bin \
    --resize_height=$RESIZE_HEIGHT \
    --resize_width=$RESIZE_WIDTH \
    --shuffle \
    $TRAIN_DATA_ROOT \
    $DATA/train.txt \
    $EXAMPLE/face_train_lmdb

echo "Creating val lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset.bin \
    --resize_height=$RESIZE_HEIGHT \
    --resize_width=$RESIZE_WIDTH \
    --shuffle \
    $VAL_DATA_ROOT \
    $DATA/val.txt \
    $EXAMPLE/face_val_lmdb

echo "Done."



下面编写脚本文件生成均值。新建vgg_mean.sh,脚本代码也是网上借鉴修改的来。写好后执行sh vgg_mean.sh即可生成

face_mean.binaryproto。







#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12

EXAMPLE=vggface
DATA=vggface
TOOLS=./build/tools

$TOOLS/compute_image_mean $EXAMPLE/face_train_lmdb \
  $DATA/face_mean.binaryproto

echo "Done."




3.训练网络





首先去官网上下载vgg caffe模型,下载下来有一个.caffemodel文件,因此是可以直接用来finetune的。





需要自己先配置一下.prototxt文件和.solver文件。













先在vggface文件夹下面建立一个.prototxt文件,命名为vggface_train_test.prototxt,




.prototxt主要是描述一个网路的结构,本身模型已经确定了,因此不需要去改变它的结构,只需要改一下输入,然后让它自动训练新的参数即可。做法是


把之前VGG_FACE_deploy.prototxt的所有的复制过来,然后加入数据层。



加入的数据层部分的代码如下,删掉2-6行,改入自己的数据集即可。




name: "vggface_train_test.prototxt"
layer{
name:"data"
type:"ImageData"
top:"data"
top:"label"
include{
phase: TRAIN
}
transform_param{
mirror:true
crop_size:224
mean_value:104
mean_value:117
mean_value:123
}
image_data_param{
source:"train.txt"
batch_size:64
shuffle:true
new_height:256
new_width:256
}
}
layer{
name:"data"
type:"ImageData"
top:"data"
top:"label"
include{
phase: TEST
}
transform_param{
mirror:true
crop_size:224
mean_value:104
mean_value:117
mean_value:123
}
image_data_param{
source:"val.txt"
batch_size:32
shuffle:true
new_height:256
new_width:256
}
}
layer{
name:"conv1_1"
type:"Convolution"
bottom:"data"
top:"conv1_1"
param{
lr_mult:0
decay_mult:0
}
param{
lr_mult:0
decay_mult:0
}
convolution_param{
num_output:64
kernel_size:3
pad:1
}
}
...
中间忽略,按官方所给即可
...
layer{
name:"fc8_10000"
type:"InnerProduct"
bottom:"fc7"
top:"fc8_10000"
param{
lr_mult:10
decay_mult:1
}
param{
lr_mult:20
decay_mult:0
}
inner_product_param{
num_output:10000
weight_filler{
type:"gaussian"
std:0.01
}
bias_filler{
type:"constant"
value:0
}
}
}
layer{
name:"loss"
type:"SoftmaxWithLoss"
bottom:"fc8_10000"
bottom:"label"
top:"loss"
}
layer{
name:"accuracy"
type:"Accuracy"
bottom:"fc8_10000"
bottom:"label"
top:"accuracy"
include{
phase: TEST
}
}


另外,在文件的最底部,有个num_output: 2622的那一层,这一层主要是概率输出层,就是softmax分类器层。因为vgg训练这个网络,用了2622个人,所以就是2622,现在可以根据自己的人的个数来设置,我用了10000个人,所以就把把num_output: 2622改为了num_output: 10000,并且把name:改为了facefc8 


下面开始改solver文件。如果没有就新建一个solver文件,保存为solver.prototxt。





net: "vggface_train_test.prototxt"
test_iter: 500
test_interval: 500
test_initialization: false
display: 40
average_loss: 40
base_lr: 0.00005
lr_policy: "step"
stepsize: 320000
gamma: 0.96
max_iter: 1000
momentum: 0.9
weight_decay: 0.0002
snapshot: 500
snapshot_prefix: "mymodel"
solver_mode: GPU



最后写一个训练用的脚本文件,命名为vgg_training.sh,如下:









#!/usr/bin/env sh
../build/tools/caffe train \
    --solver=solver.prototxt \
    --weights=VGG_FACE.caffemodel 



weights=vggface/VGG_FACE.caffemodel,这就是在VGG_FACE.caffemodel上finetuing了。




执行sh vgg_training.sh就可以在vggface上finetuing了,跑结果模型也会保存在vggface文件夹中。






对模型使用有matlab例程调用。




下图时训练过程图片













版权声明:本文为jinglingli_SJTU原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。