说明:这是本人caffe入门时的一些记录;主要采用了博客里一位大神的方式:
https://blog.csdn.net/hjimce/article/details/48933813(博主:hjimce)
还有一些是从21天实战caffe中学习到的,只是为了做学习日志才写下的这篇博客。
从三天前用Windows和Ubuntu装完caffe后,最近开始硬着头皮学习源代码,发现效果一般,遂找了大神们的笔记专研一番, 豁然开朗。
在编译好caffe后,在caffe的目录下会生成一个build文件夹,里面有些caffe的可执行文件:./caffe/build/tools/caffe
在对模型训练的时候,只要在修改一些参数的基础上,就可以构建自己的网络,再调用这个可执行文件即可。
1. 数据格式的处理:(这里面因为懂的不多,所以都是用的hjimce大神那里的东西)
也就是把我们的图片.jpg,.png等图片以及标注标签,打包在一起,搞成caffe可以直接方便调用的文件。后续讲解这部分的东西,让caffe进行调用。
2. 撰写LeNet-5网络的结构文件: 其描述文件位于 ./examples/mnist/lenet_train_val.prototxt 在这一层你将定义每一层的特征数,路径,输入和输出等等。 这个经典的结构是拥有识别手写字体。
name: "LeNet" //网络的名称
layer { //定义一个层 Layer
name: "mnist" //这个层的名字
type: "Data" //这个层的类型是数据层
top: "data" //层共有data1和label两个blob的输出
top: "label"
include {
phase: TRAIN //该层的参数只在训练层有用
}
transform_param {
scale: 0.00390625 //对所有的图片归一化,也就是对输入的数据全部乘以scale 0.0039 = 1/255
}
data_param { //数据层参数
source: "examples/mnist/mnist_train_lmdb" //训练图片的路径
batch_size: 64 //批量数目 一次训练采用图片64张 min-batch
backend: LMDB //数据格式为LMDB
}
}
layer { //一个新的数据层,输出的数据是以下两样,但改层数据仅仅在测试层有用
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb" //测试的图片的路径
batch_size: 100
backend: LMDB
}
}
layer { //定义一个新层 卷积神经网络的第一层,卷积层
name: "conv1"
type: "Convolution" //该层操作为卷积
bottom: "data" //输入的格式 也就是这一层的上一层为data层
top: "conv1" //输出的格式
param {
lr_mult: 1 //权值学习速率倍乘因子,1表示保持与全局参数一致。
}
param {
lr_mult: 2 //bias学习速率倍乘因子,是全局参数的两倍
}
convolution_param { //卷积计算参数设置
num_output: 20 // 输出的特征参数 feature map个数为20
kernel_size: 5 // 卷积核的尺寸, 5*5
stride: 1 // 卷积输出跳跃空间,1表示连续输出,五跳跃
weight_filler {
type: "xavier" //权值使用的xavier填充器
}
bias_filler {
type: "constant" //bias使用的常数填充器,默认为0
}
}
}
layer { //定义新的下采样层Pool1 输入输出的参数如下
name: "pool1"
type: "Pooling"
bottom: "conv1" //前面的层
top: "pool1"
pooling_param {
pool: MAX //采用的最大值采样方法
kernel_size: 2 //下采样窗口尺寸2*2
stride: 2 // 下采样的输出跳跃间隔
}
}
layer { //新的卷积层
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer { //新的下采样层
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer { //全连接层,输入为blob为pool2 输出blob为ip1
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer { //新的非线性层,采用ReLU方法
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer { //分类准确率层,只在Testing阶段有效, 该层用于计算分类的准确率
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer { // 损失层, 损失函数采用SoftmaxLoss
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
以上的东西就是我们要设置的网络结构文件,好好记录一番。
3. 训练/预测的网络求解文件:该文件的路径 ./examples/mnist/lenet_solver.prototxt
这个文件包含了求解网络,梯度下降参数,迭代次数等等,这部分又称作 训练超参数;
# The train/test net protocol buffer definition
net: "examples/mnist/lenet_train_test.prototxt"
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_interval: 500 //训练是每迭代500次,进行一次预测
test_iter: 100 //预测阶段迭代次数为100
# Carry out testing every 500 training iterations.
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01 //学习率
momentum: 0.9 //动量参数
weight_decay: 0.0005 //权重衰减系数
# The learning rate policy
lr_policy: "inv" // 梯度下降的相关策略
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100
# The maximum number of iterations
max_iter: 10000 // 最大迭代次数
# snapshot intermediate results
snapshot: 5000 // 每迭代5000次保存一次结果
snapshot_prefix: "examples/mnist/lenet" //保存结果的路径
# solver mode: CPU or GPU
solver_mode: CPU //训练的硬件选择GPU还是CPU
多一种解释:
初始化参数解读:solver.prototxt;训练用train,训练中的测试用val,训练好后测试test
net: “models/bvlc_reference_caffenet/train_val.prototxt” 【定义好的模型】test_iter: 1000 【测试迭代1000次,每次50张图,定义在train_val.prototxt,共50,000】
test_interval: 1000 【迭代1,000次,测试(校验)一次】
base_lr: 0.01 【初始化学习速率】
lr_policy: “step” 【学习速率更改周期名‘步长’】
gamma: 0.1 【学习速率相关参数】
stepsize: 100000 【每100,000次迭代,学习速率更改一次】
display: 20 【每20次迭代显示一次结果】
max_iter: 450000 【最多迭代450,000次】
momentum: 0.9 【学习速率更改的相关参数】
weight_decay: 0.0005 【学习速率更改的相关参数】
snapshot: 10000 【每10,000次迭代保存一次当前模型】
snapshot_prefix: “models/bvlc_reference_caffenet/caffenet_train” 【当前模型的保存地址】
solver_mode: GPU 【采用GPU】
4. 训练模型 : 在完成整个CNN网络的编写之后,就可以开始训练模型
./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt
5. 用模型进行预测 : 利用训练好的模型可以对测试数据集(或是外部测试集)进行预测;
./build/tools/caffe.bin test \ 表示只做预测(前向传播计算),不进行参数更新(后向传播计算)
-model examples/mnist/lenet_train_test.prototxt \ 指定模型描述文本文件。
-weights examples/mnist/lenet_iter_10000.caffemodel \ 指定模型预先训练好的权值文件
-iterations 100 指定测试迭代次数
附件:lmdb数据格式生成(该部分内容转载自hjimce博客:地址在文首)
这里主要讲解lmdb格式数据的制作。其实在caffe/examples/imagenet 文件夹下面的一些脚本文件可以帮助我们快速生产相关的caffe所需的数据。
create_imagenet.sh这个文件可以帮我们快速的生成lmdb的数据格式文件,因此我们只需要把这个脚本文件复制出来,稍作修改,就可以对我们的训练图片、标注文件进行打包为lmdb格式文件了。制作图片的脚本文件如下:
- <span style="font-size:18px;">#!/usr/bin/env sh
- # Create the imagenet lmdb inputs
- # N.B. set the path to the imagenet train + val data dirs
- EXAMPLE=. # 生成模型训练数据文化夹
- TOOLS=../../build/tools # caffe的工具库,不用变
- DATA=. # python脚步处理后数据路径
- TRAIN_DATA_ROOT=train/ #待处理的训练数据图片路径
- VAL_DATA_ROOT=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=256
- RESIZE_WIDTH=256
- 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 \
- --resize_height=$RESIZE_HEIGHT \
- --resize_width=$RESIZE_WIDTH \
- --shuffle \
- $TRAIN_DATA_ROOT \
- $DATA/train.txt \ #标签训练数据文件
- $EXAMPLE/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/val_lmdb
- echo "Done."</span>
1、文件夹train,用于存放训练图片
2、文件夹val,用于存放验证图片
3、文件train.txt,里面包含这每张图片的名称,及其对应的标签。
- <span style="font-size:18px;">first_batch/train_female/992.jpg 1
- first_batch/train_female/993.jpg 1
- first_batch/train_female/994.jpg 1
- first_batch/train_female/995.jpg 1
- first_batch/train_female/996.jpg 1
- first_batch/train_female/997.jpg 1
- first_batch/train_female/998.jpg 1
- first_batch/train_female/999.jpg 1
- first_batch/train_male/1000.jpg 0
- first_batch/train_male/1001.jpg 0
- first_batch/train_male/1002.jpg 0
- first_batch/train_male/1003.jpg 0
- first_batch/train_male/1004.jpg 0
- first_batch/train_male/1005.jpg 0
- first_batch/train_male/1006.jpg 0
- first_batch/train_male/1007.jpg 0
- first_batch/train_male/1008.jpg 0</span>
上面的标签编号:1,表示女。标签:0,表示男。
4、文件val.txt,同样这个文件也是保存图片名称及其对应的标签。
这四个文件在上面的脚本文件中,都需要调用到。制作玩后,跑一下上面的脚本文件,就ok了,跑完后,即将生成下面两个文件夹:
文件夹下面有两个对应的文件:
制作完后,要看看文件的大小,有没有问题,如果就几k,那么正常是每做好训练数据,除非你的训练图片就几张。