tf-faster-rcnn源码解析——shell scripts

tf-faster-rcnn 源码解析shell scripts

之前是用的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

你可能感兴趣的:(深度学习,计算机视觉,faster-rcnn)