数据准备
输入为截取出来的人脸,分数为0-1浮点型小数,只能用hdf5准备数据集
(数据不均衡先做数据扩充,平衡数据后)
masstohdf5.py :一个hdf5文件太大,我划分为两个,视数据集大小而定,一个hdf5文件最大不能超过2G,参数是保存所有人脸路径的txt文件,这里是3通道彩色图像
#!/usr/bin/env python
# coding=utf-8
import os
from PIL import Image
import sys
import numpy as np
import h5py
IMAGE_SIZE = (112, 112)
filename = sys.argv[1]
setname, ext = filename.split('.')
with open(filename, 'r') as f:
lines = f.readlines()
# anno = list()
# anno = sorted(lines, key= lambda x: float(x.split()[1]), reverse=True)
# for i in anno:
# print(i)
np.random.shuffle(lines)
label_path = 'label_{}x{}'.format(IMAGE_SIZE[0], IMAGE_SIZE[1])
if not os.path.exists(label_path):
os.makedirs(label_path)
for seg in range(2):#int(len(lines)/1000)):
if seg==0:
lines_seg =lines[:int(len(lines)/2)]#[1000*seg:1000*seg+1000-1]
else:
lines_seg = lines[int(len(lines)/2):]
sample_size = len(lines_seg)
imgs = np.zeros((sample_size, 3,)+ IMAGE_SIZE, dtype=np.float32)
scores = np.zeros(sample_size, dtype=np.float32)
h5_filename = '{}/{}_{}.h5'.format(label_path, setname, seg)
with h5py.File(h5_filename, 'a') as h:
for i, line in enumerate(lines_seg):
image_name, score = line[:-1].split()
img = Image.open(os.path.join('data',image_name))
img = img.resize(IMAGE_SIZE, Image.BILINEAR)
img = np.array(img, dtype=np.float32) # img:(h,w,3) RGB
img = img[:, :, ::-1] # img: (h,w,3) BGR
img -= np.array((104, 117, 123)) # BGR
img = img.transpose((2, 0, 1)) # img:(3,h,w)
img = img.reshape((1, )+img.shape)
imgs[i] = img
scores[i] = float(score)
if (i+1) % 100 == 0:
print('processed {} images!'.format(i+1))
h.create_dataset('data', data=imgs)
h.create_dataset('score', data=scores)
with open('{}/{}_h5.txt'.format(label_path, setname), 'a+') as f:
f.write(h5_filename)
f.write('\n')
网络结构
solver.prototxt
net: "./regress_train.prototxt"
test_iter: 100 #len(val_dataset)/batch_size
test_interval: 230
base_lr: 0.01
lr_policy: "step"
gamma: 0.1
stepsize: 5000
display: 50
max_iter: 21000 #len(train_dataset)/batch_size*epoch_size
momentum: 0.85
weight_decay: 0.0005
snapshot: 2000
snapshot_prefix: "./regress_112_result/occ"
solver_mode: GPU
type: "Nesterov"
train.prototxt
name: "Regression"
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "score"
include {
phase: TRAIN
}
hdf5_data_param {
source: "./label_112x112/occ_train_h5.txt"
batch_size: 128
}
}
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "score"
include {
phase: TEST
}
hdf5_data_param {
source: "./label_112x112/occ_val_h5.txt"
batch_size: 128
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 96
kernel_size: 5
stride: 2
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
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: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 96
pad: 2
kernel_size: 3
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
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: "conv3"
type: "Convolution"
bottom: "pool2"
top: "conv3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "fc4"
type: "InnerProduct"
bottom: "pool3"
top: "fc4"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
inner_product_param {
num_output: 192
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "fc4"
top: "fc4"
}
layer {
name: "drop4"
type: "Dropout"
bottom: "fc4"
top: "fc4"
dropout_param {
dropout_ratio: 0.35
}
}
layer {
name: "fc5"
type: "InnerProduct"
bottom: "fc4"
top: "fc5"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
inner_product_param {
num_output: 1
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "sigmoid5"
type: "Sigmoid"
bottom: "fc5"
top: "pred"
}
layer {
name: "loss"
type: "EuclideanLoss"
bottom: "pred"
bottom: "score"
top: "loss"
}
deploy.prototxt
name: "Regression"
input: "data"
input_shape {
dim: 1
dim: 3
dim: 112
dim: 112
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 96
kernel_size: 5
stride: 2
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
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: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 96
pad: 2
kernel_size: 3
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
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: "conv3"
type: "Convolution"
bottom: "pool2"
top: "conv3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "fc4"
type: "InnerProduct"
bottom: "pool3"
top: "fc4"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
inner_product_param {
num_output: 192
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "fc4"
top: "fc4"
}
layer {
name: "drop4"
type: "Dropout"
bottom: "fc4"
top: "fc4"
dropout_param {
dropout_ratio: 0.35
}
}
layer {
name: "fc5"
type: "InnerProduct"
bottom: "fc4"
top: "fc5"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 1
decay_mult: 0
}
inner_product_param {
num_output: 1
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "sigmoid5"
type: "Sigmoid"
bottom: "fc5"
top: "pred"
}
训练
python caffe_root/build/tools/caffe train-solver solver.prototxt