参考:
1. 数据准备
在 caffe_master/data
中新建文件夹 myalex
,在 myalex/train
文件里存放训练的图片 85 张,在 myalex/val
文件里存放验证集的图片 36 张,在 myalex/test
文件里面放测试的照片
根据训练和测试的图片生成 train.txt 文件、 val.txt 文件和 test.txt 文件,此文件里包含文件名和分类标签。标签为 1 或 -1。
可在 train 文件夹路径下,使用 find -name *.jpeg |cut -d '/' -f2-3 >train.txt 脚本命令来生成 train.txt 文件。val.txt 的生成方法类似。
train.txt 如图所示:
把图片变成 256×256 大小,使用 shell 命令:
for name in /path/to/imagenet/val/*.JPEG; do
convert -resize 256x256\! $name $name
done
或者在下一步创建 leveldb 数据时,将 examples/imagenet/create_imagenet.sh
的 RESIZE 设置为 true 来更改大小。
生成 leveldb 格式数据:在 caffe-master/examples
里创建文件夹 myalex,将 imagenet 文件夹里的 create_imagenet.sh
复制到该文件夹下进行修改,主要修改训练和测试路径的位置,然后在命令行的 caffe-master 路径下,运行 ./examples/myalex/create_imagenet.sh
。运行完毕,将在 myalex 里生成 myalex_train_leveldb 和 myalex_val_leveldb。
修改如下:
#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e
# 改为自己的 train 和 val 路径
EXAMPLE=examples/myalex
DATA=data/myalex
TOOLS=build/tools
TRAIN_DATA_ROOT=data/myalex/train/
VAL_DATA_ROOT=data/myalex/val/
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
# 使用 Alexnet 输入是 277x277 而不是 256x256
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_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.list \
$EXAMPLE/myalex_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.list \
$EXAMPLE/myalex_val_lmdb
echo "Done."
我们得到了这两个东西:
2. 计算图像均值
模型需要从每张图片里减去均值,所以我们必须提前获得图像的均值,用 tools/compute_image_mean.cpp
实现,这个 cpp 是一个很好的例子去熟悉如何操作多个组件,例如协议缓冲区,leveldb,登录等。我们直接复制 Imagenet 的 make_imagenet_mean,并修改路径即可。然后在命令行的 caffe-master 路径下,运行 ./examples/myalex/make_imagenet_mean.sh
,运行结束后,将会在 caffe-master/data/myalex
里生成 myalex_mean.binaryproto。
#!/usr/bin/env sh
# Compute the mean image from the imagenet training lmdb
# N.B. this is available in data/ilsvrc12
EXAMPLE=examples/myalex
DATA=data/myalex
TOOLS=build/tools
$TOOLS/compute_image_mean $EXAMPLE/myalex_train_lmdb \
$DATA/myalex_mean.binaryproto
echo "Done."
3. 定义网络
我们使用 Alexnet,拷贝 caffe/models/bvlc_alexnet
到 caffe/examples/myalex/
要修改 solver.prototxt
和 train_val.prototxt
3.1 修改 solver.prototxt
net: "examples/myalex/bvlc_alexnet/train_val.prototxt"
test_iter: 50 //测试迭代次数
test_interval: 100 //多少次迭代测试一次
base_lr: 0.01 //基础学习率
lr_policy: "step"
gamma: 0.1
stepsize: 100000
display: 20 //多少次迭代显示一次
max_iter: 700 //多少次迭代显示一次
momentum: 0.9
weight_decay: 0.0005
snapshot: 700 //多少次迭代保存一次模型快照
snapshot_prefix: "examples/myalex/bvlc_alexnet/caffe_alexnet_train" //快照保存位置
solver_mode: GPU
3.2 修改 train_val.prototxt
//记得两个参数不止一个!全部修改了!别只修改一个
mean_file : "examples/myalex/imagenet_mean.binaryproto"
//这个是上面生成的均值文件位置
source : "examples/myalex/myalex_train_lmdb"
//这个是上面生成的 lmdb 文件位置
//然后如果你自己要定义类别个数(嫌麻烦就别改这里了!不会影响!),请在最后一层里面
name : "fc8" //这个名字的代表 alexnet 的最后一层,其他的网络自己找
num_output: 2 //alexnet 默认 1000 个 改成你自己的个数,我改成: num_output: 2 //也可以不改,训练不影响
4. 训练网络
到根目录,执行命令:
./build/tools/caffe train --solver=examples/myalex/bvlc_alexnet/solver.prototxt