从零开始,一步一步学习caffe的使用,期间贯穿深度学习和调参的相关知识!
数据格式LMDB文件制作
convert_imageset
是将我们准备的数据集文件转换为caffe
接口更快读取的LMDB
或HDF5
数据类型。
文件结构
代码语言:javascript复制|____face-lmdb.sh
|____train.txt
|____train
| |____0 // 存放有人脸图片
| |____1 // 存放无人脸图片
|____val.txt
|____val //直接存放待测试图片
train.txt文件格式
代码语言:javascript复制1/23039_nonface_0image30595.jpg 1
0/34245_faceimage06120.jpg 0
0/10649_faceimage50035.jpg 0
...
val.txt文件格式
代码语言:javascript复制39830_nonface_0image49143.jpg 1
22467_nonface_0image15785.jpg 1
29202_nonface_1image71337.jpg 1
4629_nonface_1image07224.jpg 1
20093_faceimage20295.jpg 0
18655_faceimage09968.jpg 0
...
转换脚本文件
代码语言:javascript复制#!/usr/bin/env sh
# Create the face_48 lmdb inputs
# N.B. set the path to the face_48 train val data dirs
EXAMPLE=/home/xuke/data/face_detect #项目位置
DATA=/home/xuke/data/face_detect #数据项目位置
TOOLS=/home/xuke/caffe/build/tools #caffe tool目录位置
TRAIN_DATA_ROOT=/home/xuke/data/face_detect/train/ #训练数据集根目录
VAL_DATA_ROOT=/home/xuke/data/face_detect/val/ #测试数据集根目录
# Set RESIZE=true to resize the images to 60 x 60. Leave as false if images have
# already been resized using another tool.
RESIZE=true #是否进行图片尺寸变换
if $RESIZE; then
RESIZE_HEIGHT=227
RESIZE_WIDTH=227
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_face_48.sh to the path"
"where the face_48 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_face_48.sh to the path"
"where the face_48 validation data is stored."
exit 1
fi
echo "Creating train lmdb..."
GLOG_logtostderr=1 $TOOLS/convert_imageset
--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
--resize_height=$RESIZE_HEIGHT
--resize_width=$RESIZE_WIDTH
--shuffle
$VAL_DATA_ROOT
$DATA/val.txt
$EXAMPLE/face_val_lmdb
echo "Done."
Status API Training Shop Blog About
生成多标签数据格式HDF5
前面讲到的是LMDB
,在Caffe
中,如果使用LMDB
数据格式的话,默认是只支持“图像 整数单标签”这种形式的数据的。如果训练网络需要一些其他形式的数据或标签(如浮点数据,多标签等等),可以将其制作成HDF5
格式。HDF5数据格式比较灵活,但缺点是占用空间较大。将229多张512x512的图像制作成一个HDF5
文件,能达到1.4GB。 因此建议图像文件的话,最好还是用LMDB
格式,快速且节省空间。因此建议的方法是将图像存储为LMDB
格式,而多标签存储为HDF5
格式。
图像数据转换为LMDB格式
制作流程与前面思路一致,准备图像文件名列表list.txt,需要注意的是因为我们将多标签的值与图像的存储分开,对于图像我们可以不写对应的Label值。convert_imageset会在运行时把每个Label都赋为0.
多标签数据格式
定义name_label.txt文件,文件的格式如下所示:
代码语言:javascript复制8/ballet_106_104.jpg 010011101010011110000010111100001001010100000
8/ballet_106_13.jpg 110000101100001010000010111110001111011100000
8/ballet_106_20.jpg 011100101000001010000010001110000001010100100
8/ballet_106_28.jpg 010110101100001010000000101110001101010000000
8/ballet_106_35.jpg 110110101010001110001000011100001111010000100
8/ballet_106_42.jpg 011110111000001001000100011110001111010100001
8/ballet_106_5.jpg 010101101100101010100101101100011101010000101
8/ballet_106_57.jpg 010000001000001010000010100010001101001100100
注意,list.txt中的文件名一定要和name_label.txt中标签一一对应。这样的话,hdf5_train.h5里面就储存了所有图像对应的标签,每个标签包含多个0或1的值。
转换脚本文件
代码语言:javascript复制import h5py
import numpy as np
import os
label_dim = 45
# 存放标签值的文件
list_txt = 'name_label.txt'
# 要生成的HDFS文件名
hdf5_file_name = 'hdf5_train.h5'
with open(list_txt, 'r') as f:
lines = f.readlines()
samples_num = len(lines)
# 此处可以指定数据类型,如 dtype=float
labels = np.zeros((len(lines), label_dim))
for index in range(samples_num):
img_name, label = lines[index].strip().split()
label_int = [int(l) for l in label]
labels[index, :] = label_int
# 将标签数据写入hdf5文件
h5_file = h5py.File(hdf5_file_name, 'w')
# 此处'multi_label'和网络定义文件中HDF5Data层的top名字是一致的
h5_file.create_dataset('multi_label', data=labels)
h5_file.close()
print 'Complete.'
网络定义
采用两个数据层,一个Data层用于读取图像数据,一个HDF5Data层,用于读取图像对应的多Lable数据。具体Net定义如下:
代码语言:javascript复制name: "TRAIN_NET"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
data_param {
source: "lmdb/train_lmdb"
backend: LMDB
batch_size: 1
}
transform_param {
mirror: true
mean_value: 104.0
mean_value: 117.0
mean_value: 123.0
}
}
layer {
name: "multi_label"
type: "HDF5Data"
top: "multi_label"
hdf5_data_param {
source: "hdf5_train_list.txt"
batch_size: 1
}
}
计算数据集均值
通过caffe
在tool
文件夹中自带的工具compute_image_mean
可以生成我们需要的均值文件。
sudo /home/xuke/caffe/build/tools/compute_image_mean
/home/xuke/caffe/examples/mnist/mnist_train_lmdb
/home/xuke/caffe_case/mean.binaryproto
- 寻找
compute_image_mean
工具 - 锁定训练数据集目标
mnist_train_lmdb
- 生成均值文件的路径及名称
绘制网络结构
使用caffe
Python
接口中的draw_net.py
工具,将设计出的网络模型结构进行可视化。另外推荐一下网页版在线的caffe结构可视化工具——netscope
(https://ethereon.github.io/netscope/#/editor)
安装graphViz
代码语言:javascript复制sudo apt-get install graphviz
安装pydot
代码语言:javascript复制sudo pip install pydot
绘制网络指令
代码语言:javascript复制sudo python /home/xuke/caffe/python/draw_net.py
/home/xuke/caffe/examples/mnist/lenet_train_test.prototxt
/home/xuke/caffe_case/lenet.png --rankdir=BT
- 第一个参数:网络模型的
prototxt
文件 - 第二个参数:保存的图片路径及名字
- 第三个参数:
--rankdir=x
,x
有四种选项,分别是LR
,RL
,TB
,BT
。用来表示网络的方向,分别是从左到右,从右到左,从上到小,从下到上。默认为LR
。
结果
绘制Loss曲线图
通过matplotlib
将caffe
训练过程中的loss
值与Accuracy
值进行图形绘制,便于查看模型训练结果。
加载库文件设置路径
代码语言:javascript复制#加载必要的库
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import sys,os,caffe
#设置当前目录
caffe_root = '/home/xuke/caffe/'
sys.path.insert(0, caffe_root 'python')
os.chdir(caffe_root)
设置求解器
代码语言:javascript复制caffe.set_mode_cpu()
solver = caffe.SGDSolver('/home/xuke/caffe/examples/mnist/lenet_solver.prototxt')
训练并保存Loss与Accuracy值
代码语言:javascript复制niter =1000
test_interval = 200
train_loss = np.zeros(niter)
test_acc = np.zeros(int(np.ceil(niter / test_interval)))
# the main solver loop
for it in range(niter):
solver.step(1) # SGD by Caffe
# store the train loss
train_loss[it] = solver.net.blobs['loss'].data
solver.test_nets[0].forward(start='conv1')
if it % test_interval == 0:
acc=solver.test_nets[0].blobs['accuracy'].data
print 'Iteration', it, 'testing...','accuracy:',acc
test_acc[it // test_interval] = acc
代码语言:javascript复制Iteration 0 testing... accuracy: 0.109999999404
Iteration 200 testing... accuracy: 0.899999976158
Iteration 400 testing... accuracy: 0.949999988079
Iteration 600 testing... accuracy: 0.959999978542
Iteration 800 testing... accuracy: 0.949999988079
绘制Loss及Accuracy曲线
代码语言:javascript复制print(test_acc)
_, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(np.arange(niter), train_loss)
ax2.plot(test_interval * np.arange(len(test_acc)), test_acc, 'r')
ax1.set_xlabel('iteration')
ax1.set_ylabel('train loss')
ax2.set_ylabel('test accuracy')
plt.show()
代码语言:javascript复制[ 0.11 0.89999998 0.94999999 0.95999998 0.94999999]
参考
Caffe中使用HDF5制作多标签数据 http://blog.csdn.net/u011321962/article/details/77868348