caffe总结(十一)使用hdf5格式文件用于回归(regression)

hdf5文件类型使用探讨

最近用caffe做regression问题,先用data layer中的data,float_data试了一下,data用来存放图片,float_data存放regression的values,label存放标签,发现不行,因为float_data和label这俩是指向同一块内存,两者不能共存,除非改caffe源码。关于更改caffe源码进行回归参考博客https://blog.csdn.net/weixin_42535423/article/details/103810673

我又仔细看了一下caffe的源码,具体来讲,caffe读取image和label是这样一个流程:

  1. 编写程序将image和label转换成Datum格式,并写入lmdb

  2. Data layer从lmdb中读取Datum格式的数据,然后转化成一个Batch

  3. 从Batch里面把image和label的数据复制到top的内存或显存

上述的2,3步可以查看data_layer.cpp,base_data_layer.cpp和base_data_layer.cu这三个文件,里面和float_data半点关系都没有,所以就算你把regression values保存在Datum的float_data里面,Data layer也不会把它读出来的。我目前想到的办法只有两种,要么改caffe源码,要么lmdb和hdf5一起用,源码怕改出错,就尝试了一下hdf5格式做输入,虽然搞定了,但也有坑。

说一下怎么把数据写入hdf5文件,我用的是python,numpy格式的数组可以直接存放进去,方法如下:

#1. 先创建一个空的numpy数组
hdf_data = np.zeros((len(all_samples), num), dtype=np.float32)
#2. 填充hdf_data

#3.打开h5文件然后写入hdf_data
h5_file = h5py.File(h5_path, 'w')
h5_file.create_dataset('hdf_data', data=hdf_data)
h5_file.close()
#把h5文件路径写到一个txt中
h5txt_file = open(h5txt_path, 'w')
h5txt_file.write(h5_path)
h5txt_file.close()

在定义网络的prototxt文件中,这样使用

layer {
   name: "hdf5_data"
   type: "HDF5Data"
   top: "hdf_data"
   include {
     phase: TRAIN
   }
   hdf5_data_param {
     source: "your_h5txt_file_path"
     batch_size: 1024
   }
 }

其中source是那个只有一行的txt的路径。top是你需要使用的h5中保存的数据块名称。

需要注意的是,如果是图像数据,预处理要先做,再存进h5文件,因为HDF5Data layer不支持预处理功能。另外这里有个坑,尽量不要把图片放在h5文件中,**因为HDF5Data layer不能按照batch来读取数据,只能一次性把所有数据从h5文件中读到内存中,如果h5文件非常大,就会报错,**具体是挂在HDF5Data的实现代码中了,有一个数据大小的断言。所以既不想改caffe代码又想保证训练程序能跑起来的方法如下:

把regression values按照hdf5格式存放,image和label按照正常数据存放在lmdb即可。在定义网络的prototxt中可以读取不同来源的数据,例如下面这种方法:

layer {
  name: "lmdb_data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  data_param {
    source: "train_data"
    batch_size: 1024
    backend: LMDB
  }
  transform_param {
  	mean_value: 128
  	scale: 0.0078125
  }
}
layer {
  name: "hdf5_data"
  type: "HDF5Data"
  top: "bbox"
  include {
    phase: TRAIN
  }
  hdf5_data_param {
    source: "hdf5_train.txt"
    batch_size: 1024
  }
}

单纯将图片只改为HDF5格式的案例说明

参考资料:

  1. http://stackoverflow.com/questions/33766689/caffe-hdf5-pre-processing
  2. http://corpocrat.com/2015/02/24/facial-keypoints-extraction-using-deep-learning-with-caffe/
  3. http://stackoverflow.com/questions/31774953/test-labels-for-regression-caffe-float-not-allowed/31808324#31808324

在caffe的框架上,如何根据现有的图像及其分值、标准差对图像进行回归,caffe_model是Imagenet训练得到模型、solver.prototxt和train_val.prototxt。本次的数据来源为:http://live.ece.utexas.edu/。 注意:所有的工程建立都是在caffe的根目录下执行。

一、环境:

编码成功的caffe;图像数据库。

二、数据预处理:

  • 在data下建立文件夹“face_key_point”,之后所有的数据处理均在“face_key_point”文件夹下,该文件夹下包含images文件夹和其他文件(.py和.txt文件)。
    1. images文件夹里包含所有的train、test和val图像;
    2. 其他文件

*.py生成文件准备

  • meancreat_hdf5.py

用于产生train.h5和train_h5_list.txt(注意检查该文件中train.h5的路径是否是绝对路径,如果不是,请改一下),可以用HDF5View查看train.h5检查数据是否正确,ImageNum3227*227(SIZE,最好和Imagenet模型的保持一致),适合所有类型的图像(.JPG和.bmp同时处理),代码里对图像已经做过均值处理,具体代码如下:

import h5py, os
import caffe
import numpy as np 
SIZE = 227 # fixed size to all images
with open( 'train.txt', 'r' ) as T :
    lines = T.readlines()        
with open( 'num.txt', 'r' ) as M :
    lines_Num = M.readlines()      
# If you do not have enough memory split data into
# multiple batches and generate multiple separate h5 files
X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' )
XMean = np.zeros( (len(lines), 3, 1, 1), dtype='f4' )
y = np.zeros( (len(lines_Num)), dtype='f4' )
print len(lines)       
for i,l in enumerate(lines):
    sp = l.split('\r\n')
    img = caffe.io.load_image( sp[0] )
    img = caffe.io.resize_image( img, (SIZE, SIZE), 3 ) # resize to fixed size
    img = np.transpose(img, (2, 0, 1))
         # you may apply other input transformations here...
    X[i] = img
# Compute the mean of all images
XMean = sum(X)/len(X)
X = X - XMean
print 'image OK'    
for j, eachLine in enumerate(lines_Num):
    y[j] = float(float(eachLine)/92.432)
print 'Num OK'
with h5py.File('train.h5','w') as H:
    H.create_dataset( 'X', data=X ) # note the name X given to the dataset!
    H.create_dataset( 'y', data=y ) # note the name y given to the dataset!
with open('train_h5_list.txt','w') as L:
    L.write( '/home2/xj_jin/experiment/caffe-master/data/face_key_point/train.h5' ) # list all h5 files you are going to use    
  • meancreat_hdf5test.py

同理,用于产生test.h5和test_h5_list.txt(检查路径),代码里对图像已经做过均值处理,具体代码如下:

import h5py, os
import caffe
import numpy as np
SIZE = 227 # fixed size to all images
with open( 'test.txt', 'r' ) as T :
    lines = T.readlines()        
with open( 'num_test.txt', 'r' ) as M :
    lines_Num = M.readlines()        
# If you do not have enough memory split data into
# multiple batches and generate multiple separate h5 files
X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' )
XMean = np.zeros( (len(lines), 3, 1, 1), dtype='f4' )
y = np.zeros( (len(lines_Num)), dtype='f4' )
print len(lines)
for i,l in enumerate(lines):
    sp = l.split('\r\n')
    img = caffe.io.load_image( sp[0] )
    img = caffe.io.resize_image( img, (SIZE, SIZE), 3 ) # resize to fixed size
    img = np.transpose(img, (2, 0, 1))
         # you may apply other input transformations here...
    X[i] = img        
# Compute the mean of all images
XMean = sum(X)/len(X)
X = X - XMean
print 'image OK'     
for j, eachLine in enumerate(lines_Num):
    y[j] = float(float(eachLine)/87.0656)        
print 'Num OK'                 
with h5py.File('test.h5','w') as H:
    H.create_dataset( 'X', data=X ) # note the name X given to the dataset!
    H.create_dataset( 'y', data=y ) # note the name y given to the dataset!
with open('train_h5_list.txt','w') as L:
    L.write( '/home2/xj_jin/experiment/caffe-master/data/face_key_point/test.h5' ) # list all h5 files you are going to use
  • (3)train.txt和num.txt

train.txt存放着待训练的图片,num.txt存放待训练图片的分值。具体格式如下:

train.txt:(建议检查路径是否存在空格)

/home2/xj_jin/experiment/caffe-master/data/face_key_point/images/00t1.bmp
/home2/xj_jin/experiment/caffe-master/data/face_key_point/images/00t2.bmp
/home2/xj_jin/experiment/caffe-master/data/face_key_point/images/00t3.bmp
/home2/xj_jin/experiment/caffe-master/data/face_key_point/images/00t4.bmp
/home2/xj_jin/experiment/caffe-master/data/face_key_point/images/00t5.bmp

num.txt:

63.9634
25.3353
48.9366
35.8863
66.5092
  • (4) test.txt和num_test.txt

test.txt存放着待训练的图片,num_test.txt存放待训练图片的分值。具体格式和上述一致。

生成train.h5和test.h5数据

在caffe/data/face_key_point下执行:

命令: python meancreat_hdf5.py和 python meancreat_hdf5test.py

三、模型修改

在caffe/model下建立自己的文件夹“face_key_point”,将下载得到的Imagenet的模型和网络结构bvlc_reference_caffenet.caffemodel、train_val.prototxt、solver.prototxt放入该文件夹下。

1.修改solver.prototxt

net: "models/face_key_point/train_val.prototxt"                             -----------------------路径要改
test_iter: 100
test_interval: 1000
# lr for fine-tuning should be lower than when starting from scratch
base_lr: 0.001                                                                                    -----------------------基础学习率根据实际情况改
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer to being done
stepsize: 20000
display: 20
max_iter: 100000
momentum: 0.9
weight_decay: 0.0005
snapshot: 10000
snapshot_prefix: "models/face_key_point/finetune_face_key_point"     ---------------------------路径+自己取名新生成的模型名称
# uncomment the following to default to CPU mode solving
# solver_mode: CPU                                                                                 ---------------------------根据自己的实际情况设置

2. 修改train_val.prototxt网络结构

这里只提供部分的网络结构。

name: "FaceKeyPointCaffeNet"                                                                   ------自己训练的网络模型名称
layer {                                                                                                            -------处理.h5数据的data层
  name: "data"
  type: "HDF5Data"
  top: "X"                                                                             -------和meancreat_hdf5test.py中最后的输出保持一致,原来是data,现在是X
  top: "y"                                                                              ----------和meancreat_hdf5test.py中最后的输出保持一致,原来是label,现在是y
  include {
    phase: TRAIN
  }
  hdf5_data_param {
    source: "data/face_key_point/train_h5_list.txt"            -----------保存的train.h5的绝对路径,可以处理多个.h5数据
    batch_size: 64
  }
}
layer {
  name: "data"
  type: "HDF5Data"
  top: "X"
  top: "y"
  include {
    phase: TEST
  }
  hdf5_data_param {
    source: "data/face_key_point/test_h5_list.txt"
    batch_size: 100
  }
}

。。。

layer {
  name: "ip"
  type: "InnerProduct"
  bottom: "fc8"
  top: "ip"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 1
    weight_filler {
      type: "gaussian"
      std: 0.1
    }
    bias_filler {
      type: "constant"
    }
  }
}

layer {
  name: "loss"
  type: "EuclideanLoss"
  bottom: "ip"
  bottom: "label"
  top: "loss"
}

卷积层、池化层、全连接层、损失等;

最后,因为本次处理的是一个回归问题,所以最后的损失函数(loss)应该是一个回归,而不是分类,保证最后几层的bottom是y,而不是label。

四、训练

注意改掉对应路径即可:

./build/tools/caffe train --solver=models/face_key_point/solver.prototxt --weights=models/face_key_point/bvlc_reference_caffenet.caffemodel -gpu 0
发布了61 篇原创文章 · 获赞 15 · 访问量 966

猜你喜欢

转载自blog.csdn.net/weixin_42535423/article/details/103738986