之前是用的faster rcnn原作者caffe版本的源码,因为一直换服务器,每次都编译一遍caffe着实麻烦,转战tensorflow版本的faster rcnn
因为要用自己的数据,还要改部分模型,所以得搞清楚各种文件结构。首先搞懂模型命令行参数的输入以及数据、各种输出的路径。
这里先看下shell脚本,在experiments/scrips中
train_faster_rcnn.sh(当然也可以不用shell脚本来运行,但就得输入大量参数)
#!/bin/bash
set -x
set -e
export PYTHONUNBUFFERED="True"
#必须要输入的三个参数
GPU_ID=$1
DATASET=$2
NET=$3
#多余参数,用于自定义输出文件名称
array=( $@ )
len=${#array[@]}
EXTRA_ARGS=${array[@]:3:$len}
EXTRA_ARGS_SLUG=${EXTRA_ARGS// /_}
#DATASET选项(只有pascal_voc,pascal_voc_0712.coco三个)
case ${DATASET} in
pascal_voc)
#和factory.py中的__sets字典的key匹配才行
TRAIN_IMDB="voc_2007_trainval"
TEST_IMDB="voc_2007_test"
STEPSIZE="[50000]"
#迭代的次数
ITERS=70000
#Anchor的比例和尺度
ANCHORS="[8,16,32]"
RATIOS="[0.5,1,2]"
;;
pascal_voc_0712)
#同上面的 pacal_voc
TRAIN_IMDB="voc_2007_trainval+voc_2012_trainval"
TEST_IMDB="voc_2007_test"
STEPSIZE="[80000]"
ITERS=110000
ANCHORS="[8,16,32]"
RATIOS="[0.5,1,2]"
;;
coco)
TRAIN_IMDB="coco_2014_train+coco_2014_valminusminival"
TEST_IMDB="coco_2014_minival"
STEPSIZE="[350000]"
ITERS=490000
ANCHORS="[4,8,16,32]"
RATIOS="[0.5,1,2]"
;;
*)
echo "No dataset given"
exit
;;
esac
#训练输出日志路径
LOG="experiments/logs/${NET}_${TRAIN_IMDB}_${EXTRA_ARGS_SLUG}_${NET}.txt.`date +'%Y-%m-%d_%H-%M-%S'`"
exec &> >(tee -a "$LOG")
echo Logging output to "$LOG"
#可以理解为训练完模型输出路径吧。(...没有传进trainval_bet.py,真正的输出路径是在lib/model/config.py中定义)
set +x
if [[ ! -z ${EXTRA_ARGS_SLUG} ]]; then
NET_FINAL=output/${NET}/${TRAIN_IMDB}/${EXTRA_ARGS_SLUG}/${NET}_faster_rcnn_iter_${ITERS}.ckpt
else
NET_FINAL=output/${NET}/${TRAIN_IMDB}/default/${NET}_faster_rcnn_iter_${ITERS}.ckpt
fi
set -x
if [ ! -f ${NET_FINAL}.index ]; then
if [[ ! -z ${EXTRA_ARGS_SLUG} ]]; then
CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/trainval_net.py \
#pretrain权重
--weight data/imagenet_weights/${NET}.ckpt \
--imdb ${TRAIN_IMDB} \
--imdbval ${TEST_IMDB} \
--iters ${ITERS} \
--cfg experiments/cfgs/${NET}.yml \
--tag ${EXTRA_ARGS_SLUG} \
--net ${NET} \
--set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
TRAIN.STEPSIZE ${STEPSIZE} ${EXTRA_ARGS}
else
CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/trainval_net.py \
--weight data/imagenet_weights/${NET}.ckpt \
--imdb ${TRAIN_IMDB} \
--imdbval ${TEST_IMDB} \
--iters ${ITERS} \
--cfg experiments/cfgs/${NET}.yml \
--net ${NET} \
--set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
TRAIN.STEPSIZE ${STEPSIZE} ${EXTRA_ARGS}
fi
fi
#训练完了就直接测试(不测试就删除这句)
./experiments/scripts/test_faster_rcnn.sh $@
在shell脚本中直接定义好各种参数,直接运行shell命令,就不必再运行trainval_net.py时,输入大量的参数(而且还容易忘记输的是啥)。
所以,要自定义模型训练的一些参数和数据集的时候,还要修改这里的shell scripts
下面分析下这个脚本。
参数(按顺序)
GPU_ID,这个没什么好说的。
DATASET,在源码中,case选项里面只有pascal_voc, pascal_voc_0712, coco三个选项,所以只能输入这三个中的一个。(注意,如果使用coco数据集,需要安装cocoAPI)
如果想要使用自己的数据集,除了修改这里的shell命令,还需要在factory.py的字典__sets{}中添加内容,还需根据自己的数据格式建立dataname.py来重载imdb类。(这个之后的博客会继续总结)
Net
1、Net参数再源码中从trainval_net.py来看,有vgg16, res101,mobilenet。因为在lib/nets中只有这几个模型。
2、预训练的模型需要放在data/imagenet_weights下,模型名是Net.ckpt(当然,不怕出错可以改路径)
3、cfg 在experiments/cfgs下,以Net.yml命名,如果
需要其他的预训练的模型,需添加。
所以,综上,如果要训练网络,需要:
1、下载好预训练的模型,并放在data/imagenet_weights下,并以net.ckpt命名。以下是例子(来自github)
For vgg16
mkdir -p data/imagenet_weights
cd data/imagenet_weights
wget -v http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz
tar -xzvf vgg_16_2016_08_28.tar.gz
mv vgg_16.ckpt vgg16.ckpt
cd ../..
For res101
mkdir -p data/imagenet_weights
cd data/imagenet_weights
wget -v http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz
tar -xzvf resnet_v1_101_2016_08_28.tar.gz
mv resnet_v1_101.ckpt res101.ckpt
cd ../..
2、运行shell脚本
./experiments/scripts/train_faster_rcnn.sh [GPU_ID] [DATASET] [NET]
# GPU_ID is the GPU you want to test on
# NET in {vgg16, res50, res101, res152} is the network arch to use
# DATASET {pascal_voc, pascal_voc_0712, coco} is defined in train_faster_rcnn.sh
# Examples:
./experiments/scripts/train_faster_rcnn.sh 0 pascal_voc vgg16
./experiments/scripts/train_faster_rcnn.sh 1 coco res101
同样,综上,如果想要增加一个新的分类网络作为基础网络,需要做的是:
1、在lib/nets中添加新的网络.py,并在trainval_net.py和test_net.py中添加相应的选项。
2、在data/imagenet_weiights文件下添加相应的预训练的模型,名称是Net.ckpt
3、在experiments/cfgs下添加相应的配置文件,名称是Net.yml
4、按上面命令训练
下面是测试的shell脚本,在experiments/scripts/test_faster_rcnn.py
#!/bin/bash
set -x
set -e
export PYTHONUNBUFFERED="True"
#执行shell脚本时,必须要输入的三个参数
GPU_ID=$1
DATASET=$2
NET=$3
array=( $@ )
len=${#array[@]}
#多余的参数(可以不输入)用来命名输出文件
EXTRA_ARGS=${array[@]:3:$len}
EXTRA_ARGS_SLUG=${EXTRA_ARGS// /_}
#输入的第二个参数DATASET必须在以下选项中,如果需要用自己的数据,则需要添加选项(除非不用这个脚本来运行)
case ${DATASET} in
pascal_voc)
TRAIN_IMDB="voc_2007_trainval"
TEST_IMDB="voc_2007_test"
#注意,这里的iters不能随便给,必须是有训练好的模型。
ITERS=70000
ANCHORS="[8,16,32]"
RATIOS="[0.5,1,2]"
;;
pascal_voc_0712)
TRAIN_IMDB="voc_2007_trainval+voc_2012_trainval"
TEST_IMDB="voc_2007_test"
ITERS=110000
ANCHORS="[8,16,32]"
RATIOS="[0.5,1,2]"
;;
coco)
TRAIN_IMDB="coco_2014_train+coco_2014_valminusminival"
TEST_IMDB="coco_2014_minival"
ITERS=490000
ANCHORS="[4,8,16,32]"
RATIOS="[0.5,1,2]"
;;
*)
echo "No dataset given"
exit
;;
esac
#测试日志路径
LOG="experiments/logs/test_${NET}_${TRAIN_IMDB}_${EXTRA_ARGS_SLUG}.txt.`date +'%Y-%m-%d_%H-%M-%S'`"
exec &> >(tee -a "$LOG")
echo Logging output to "$LOG"
set +x
#用于测试的model的路径名。
#有输入EXTRA_ARGS
if [[ ! -z ${EXTRA_ARGS_SLUG} ]]; then
NET_FINAL=output/${NET}/${TRAIN_IMDB}/${EXTRA_ARGS_SLUG}/${NET}_faster_rcnn_iter_${ITERS}.ckpt
#没有输入EXTRA_ARGS
else
NET_FINAL=output/${NET}/${TRAIN_IMDB}/default/${NET}_faster_rcnn_iter_${ITERS}.ckpt
fi
set -x
#这里运行test_net.py,并设置好参数。
#有输入EXTRA_ARGS
if [[ ! -z ${EXTRA_ARGS_SLUG} ]]; then
CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/test_net.py \
--imdb ${TEST_IMDB} \
#使用训练好的模型
--model ${NET_FINAL} \
--cfg experiments/cfgs/${NET}.yml \
--tag ${EXTRA_ARGS_SLUG} \
--net ${NET} \
--set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
${EXTRA_ARGS}
#没有输入EXTRA_ARGS
else
CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/test_net.py \
--imdb ${TEST_IMDB} \
--model ${NET_FINAL} \
--cfg experiments/cfgs/${NET}.yml \
--net ${NET} \
--set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
${EXTRA_ARGS}
fi
从上面看,test使用的model文件名的名称和train生成的文件名的名称格式是一样的,这样就很方便测试了。
如果要测试某个训练好的模型,需要的参数和训练时一样,但是需要把训练好的模型放在相应的位置(或者建立软连接)
所以,如果要测试一个训练好的模型,需要做:
1、建立软连接,将训练好的model连接到output/NET/TRAIN_IMDB/default下,
命名为:{NET}faster_rcnn_iter${ITERS}.ckpt
NET=res101
TRAIN_IMDB=voc_2007_trainval+voc_2012_trainval
mkdir -p output/${NET}/${TRAIN_IMDB}
cd output/${NET}/${TRAIN_IMDB}
ln -s ../../../data/voc_2007_trainval+voc_2012_trainval ./default
cd ../../..
2、运行shell脚本
GPU_ID=0
./experiments/scripts/test_faster_rcnn.sh $GPU_ID pascal_voc_0712 res101