vgg_face人脸识别

最近参考http://blog.csdn.net/hlx371240/article/details/51388022一文,用LFW数据集对vgg_face.caffemodel进行fine-tune。主要步骤和http://blog.csdn.net/hlx371240/article/details/51388022文中所阐述的步骤没有区别。个别地方稍微补充一下:

1.LFW标定生成程序

#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <assert.h>

#define MAX_PATH_LEN 512

int count =0;
char dirPath[MAX_PATH_LEN];

void listAllFiles(char *dirname)
{
    assert(dirname != NULL);

    char path[512];
    struct dirent *filename;
    DIR *dir;  
   
    dir = opendir(dirname);
    if(dir == NULL)
    {
        printf("open dir %s error!
",dirname);
        exit(1);
    }


    while((filename = readdir(dir)) != NULL)
    {
       if(!strcmp(filename->d_name,".")||!strcmp(filename->d_name,".."))
           continue;

       sprintf(path,"%s/%s",dirname,filename->d_name);

       struct stat s;
       lstat(path,&s);

       if(S_ISDIR(s.st_mode))
       {
           listAllFiles(path);
           count++; //每个子文件夹对应的labelID计算
       }
       else
       {
           printf("%s/%s %d
",dirname,filename->d_name,count);
       }
    }
    closedir(dir);
 }


int main(int argc, char **argv)
{
    if(argc != 2)
    {
        printf("one dir required!(for eample: ./a.out /home/myFolder)
");
        exit(1);
    }
    strcpy(dirPath,argv[1]);
    listAllFiles(dirPath);
    //printf("total files:%d
",count);
    return 0;
}
View Code

程序使用命令:

gcc label_generate.c -o label_generate
./label_generate  $DATA_ROOT/lfw

2. Finetuning的prototxt

我们只针对fc8进行fine-tune,因此将相应的层名称修改为fc8_finetune

# Data Layer
layers {
  name: "data"
  type: DATA
  include {
    phase: TRAIN
  }
 transform_param {
    crop_size: 224
    mean_file: "/$DATA_ROOT/face_mean.binaryproto"
    mirror: true
 }
 data_param {
    source: "/$DATA_ROOT/face_train_lmdb"
    batch_size: 144
    backend: LMDB
  }
  top: "data"
  top: "label"
}
layers {
  name: "data"
  type: DATA
  include {
    phase: TEST
  }
 transform_param {
    crop_size: 224
    mean_file: "/$DATA_ROOT/face_mean.binaryproto"
    mirror: false
 }
 data_param {
    source: "$DATA_ROOT/face_val_lmdb"
    batch_size: 144
    backend: LMDB
 }
 top: "data"
 top: "label"
}
# conv1_1~fc7
layers {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "relu1_1"
  type: RELU
}
layers {
  bottom: "conv1_1"
  top: "conv1_2"
  name: "conv1_2"
  type: CONVOLUTION
  convolution_param {
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv1_2"
  top: "conv1_2"
  name: "relu1_2"
  type: RELU
}
layers {
  bottom: "conv1_2"
  top: "pool1"
  name: "pool1"
  type: POOLING
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layers {
  bottom: "pool1"
  top: "conv2_1"
  name: "conv2_1"
  type: CONVOLUTION
  convolution_param {
    num_output: 128
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv2_1"
  top: "conv2_1"
  name: "relu2_1"
  type: RELU
}
layers {
  bottom: "conv2_1"
  top: "conv2_2"
  name: "conv2_2"
  type: CONVOLUTION
  convolution_param {
    num_output: 128
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv2_2"
  top: "conv2_2"
  name: "relu2_2"
  type: RELU
}
layers {
  bottom: "conv2_2"
  top: "pool2"
  name: "pool2"
  type: POOLING
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layers {
  bottom: "pool2"
  top: "conv3_1"
  name: "conv3_1"
  type: CONVOLUTION
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv3_1"
  top: "conv3_1"
  name: "relu3_1"
  type: RELU
}
layers {
  bottom: "conv3_1"
  top: "conv3_2"
  name: "conv3_2"
  type: CONVOLUTION
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv3_2"
  top: "conv3_2"
  name: "relu3_2"
  type: RELU
}
layers {
  bottom: "conv3_2"
  top: "conv3_3"
  name: "conv3_3"
  type: CONVOLUTION
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv3_3"
  top: "conv3_3"
  name: "relu3_3"
  type: RELU
}
layers {
  bottom: "conv3_3"
  top: "pool3"
  name: "pool3"
  type: POOLING
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layers {
  bottom: "pool3"
  top: "conv4_1"
  name: "conv4_1"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv4_1"
  top: "conv4_1"
  name: "relu4_1"
  type: RELU
}
layers {
  bottom: "conv4_1"
  top: "conv4_2"
  name: "conv4_2"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv4_2"
  top: "conv4_2"
  name: "relu4_2"
  type: RELU
}
layers {
  bottom: "conv4_2"
  top: "conv4_3"
  name: "conv4_3"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv4_3"
  top: "conv4_3"
  name: "relu4_3"
  type: RELU
}
layers {
  bottom: "conv4_3"
  top: "pool4"
  name: "pool4"
  type: POOLING
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layers {
  bottom: "pool4"
  top: "conv5_1"
  name: "conv5_1"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv5_1"
  top: "conv5_1"
  name: "relu5_1"
  type: RELU
}
layers {
  bottom: "conv5_1"
  top: "conv5_2"
  name: "conv5_2"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv5_2"
  top: "conv5_2"
  name: "relu5_2"
  type: RELU
}
layers {
  bottom: "conv5_2"
  top: "conv5_3"
  name: "conv5_3"
  type: CONVOLUTION
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
}
layers {
  bottom: "conv5_3"
  top: "conv5_3"
  name: "relu5_3"
  type: RELU
}
layers {
  bottom: "conv5_3"
  top: "pool5"
  name: "pool5"
  type: POOLING
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layers {
  bottom: "pool5"
  top: "fc6"
  name: "fc6"
  type: INNER_PRODUCT
  inner_product_param {
    num_output: 4096
  }
}
layers {
  bottom: "fc6"
  top: "fc6"
  name: "relu6"
  type: RELU
}
layers {
  bottom: "fc6"
  top: "fc6"
  name: "drop6"
  type: DROPOUT
  dropout_param {
    dropout_ratio: 0.5
  }
}
layers {
  bottom: "fc6"
  top: "fc7"
  name: "fc7"
  type: INNER_PRODUCT
  inner_product_param {
    num_output: 4096
  }
}
layers {
  bottom: "fc7"
  top: "fc7"
  name: "relu7"
  type: RELU
}
layers {
  bottom: "fc7"
  top: "fc7"
  name: "drop7"
  type: DROPOUT
  dropout_param {
    dropout_ratio: 0.5
  }
}
# fc8_finetune and Loss
layers {
  bottom: "fc7"
  top: "fc8"
  name: "fc8_finetune"
  type: INNER_PRODUCT
  inner_product_param {
    num_output: 5749
  }
}
layers {
  name: "loss"
  bottom: "fc8"
  bottom: "label"
  top: "loss"
  type: SOFTMAX_LOSS
}
View Code

3.脚本配置

crete_lmdb.sh:生成训练和测试数据

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

# CAFFE_ROOT is the path of your caffe and you should set it as the absolute path
# train.txt and val.txt are saved in the path $CAFFE_ROOT/VGG/data
EXAMPLE=$CAFFE_ROOT/VGG/lmdb_root
DATA=$CAFFE_ROOT/VGG/data
TOOLS=$CAFFE_ROOT/build/tools

TRAIN_DATA_ROOT=$CAFFE_ROOT/VGG/data
VAL_DATA_ROOT=$CAFFE_ROOT/VGG/data

# 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."
View Code

compute_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=$CAFFE_ROOT/VGG/lmdb_root
DATA=$CAFFE_ROOT/VGG/data
TOOLS=$CAFFE_ROOT/build/tools

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

echo "Done."
View Code

vgg_train.sh:开启训练

#!/usr/bin/env sh

$CAFFE_ROOT/build/tools/caffe train 
    --solver=$CAFFE_ROOT/VGG/solver.prototxt 
    --weights=$CAFFE_ROOT/VGG/VGG_FACE.caffemodel -gpu=0
View Code
爱上一个人,就像突然有了盔甲,也突然有了软肋。
原文地址:https://www.cnblogs.com/venus024/p/5680587.html