This tutorial is a fine-tuned clone of zeyuanxy's one for the py-faster-rcnn code.
We will illustrate how to train Py-Faster-RCNN on another dataset in the following steps, and we will take INRIA Person as the example dataset.
The current tutorial need you to have clone and tested the regular py-faster-rcnn repository from rbgirshick.
$ git clone https://github.com/rbgirshick/py-faster-rcnn
We will refer to the root directory with $PY_FASTER_RCNN.
You will also need to follow the installation steps from the original py-faster-rcnn readme
When you download and extract the Inria Person dataset you obtain this architecture:
|-- INRIAPerson/
|-- 70X134H96/
|-- 96X160H96/
|-- Test/
|-- test_64x128_H96/
|-- Train/
|-- train_64x128_H96/
But we will use this common architecture for every dataset in $PY_FASTER_RCNN/data
INRIA_Person_devkit/
|-- data/
|-- Annotations/
|-- *.txt (Annotation files)
|-- Images/
|-- *.png (Image files)
|-- ImageSets/
|-- train.txt
A simple way to achieve it is to use symbolic links: (this is only an example for training, some refactoring will be needing in order to use the testset properly)
$ cd $PY_FASTER_RCNN/data
$ mkdir INRIA_Person_devkit/
$ mkdir INRIA_Person_devkit/data/
$ ln -s <INRIAPerson>/Train/annotations/ INRIA_Person_devkit/data/Annotations
$ ln -s <INRIAPerson>/Train/pos/ INRIA_Person_devkit/data/Images
Now we need to write train.txt
that contains all the names(without extensions) of images files that will be used for training.
Basically with the following:
$ cd $PY_FASTER_RCNN/data/INRIA_Person_devkit/data/
$ mkdir ImageSets
$ ls Annotations/ -m | sed s/\\s/\\n/g | sed s/.txt//g | sed s/,//g > ImageSets/train.txt
You need to add a new python file describing the dataset we will use to the directory $PY_FASTER_RCNN/lib/datasets
, see inria.py. Then the following steps should be taken.
- Modify
self._classes
in the constructor function to fit your dataset. - Be careful with the extensions of your image files. See
image_path_from_index
ininria.py
. - Write the function for parsing annotations. See
_load_inria_annotation
ininria.py
. - Do not forget to add
import
syntaxes in your own python file and other python files in the same directory.
Then you should modify the factory.py in the same directory. For example, to add INRIA Person, we should add
from datasets.inria import inria
inria_devkit_path = '$PY_FASTER_RCNN/data/INRIA_Person_devkit'
for split in ['train', 'test']:
name = '{}_{}'.format('inria', split)
__sets[name] = (lambda split=split: inria(split, inria_devkit_path))
NB : $PY_FASTER_RCNN must be replaced by its actual value !
For example, if you want to use the model VGG_CNN_M_1024 with alternated optimizations, then you should adapt the solvers(path) in $PY_FASTER_RCNN/models/VGG_CNN_M_1024/faster_rcnn_alt_opt/
$ cd $PY_FASTER_RCNN/models/
$ mkdir INRIA_Person/
$ cp -r pascal_voc/VGG_CNN_M_1024/faster_rcnn_alt_opt/ INRIA_Person/
It mainly concerns with the number of classes you want to train. Let's assume that the number of classes is C (do not forget to count the background
class). Then you should
- Modify
num_classes
toC
; - Modify
num_output
in thecls_score
layer toC
- Modify
num_output
in thebbox_pred
layer to4 * C
Basically for our binary classifier (Person vs Background) C=2 and you have: - 7 lines to be modified from 21 to 2 - 3 lines to be modified from 84 to 8
$ grep 21 VGG_CNN_M_1024/faster_rcnn_alt_opt/*.pt
INRIA_Person/faster_rcnn_alt_opt/faster_rcnn_test.pt: num_output: 21
INRIA_Person/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt: param_str: "'num_classes': 21"
INRIA_Person/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt: num_output: 21
INRIA_Person/faster_rcnn_alt_opt/stage1_rpn_train.pt: param_str: "'num_classes': 21"
INRIA_Person/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt: param_str: "'num_classes': 21"
INRIA_Person/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt: num_output: 21
INRIA_Person/faster_rcnn_alt_opt/stage2_rpn_train.pt: param_str: "'num_classes': 21"
$ grep 84 VGG_CNN_M_1024/faster_rcnn_alt_opt/*.pt
INRIA_Person/faster_rcnn_alt_opt/faster_rcnn_test.pt: num_output: 84
INRIA_Person/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt: num_output: 84
INRIA_Person/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt: num_output: 84
!!! Change path in solver from pascal_voc to INRIA_Person
!!! copy from /experiment/cfgs/*
The $PY_FASTER_RCNN/models folder must be specified by a config file as in faster_rcnn_alt_opt.yml
$ echo 'MODELS_DIR: "$PY_FASTER_RCNN/models"' >> config.yml
NB : $PY_FASTER_RCNN must be replaced by its actual value !
https://github.com/deboc/py-faster-rcnn/blob/master/lib/datasets/inria_eval.py
In the directory $PY_FASTER_RCNN, run the following command in the shell.
$ ./tools/train_faster_rcnn_alt_opt.py --gpu 0 --net_name INRIA_Person --weights data/imagenet_models/VGG_CNN_M_1024.v2.caffemodel --imdb inria_train --cfg config.yml
Where:
--net_name is the folder name in $PY_FASTER_RCNN/models
(nb: the train_faster_rcnn_alt_opt.py script will automatically look into the /faster_rcnn_alt_opt/ subfolder for the .pt files)
--weights is the optional location of pretrained weights in .caffemodel
--imdb is the full name of the database as specified in the lib/datasets/factory.py file
(nb: dont forget to add the test/train suffix !)
Or the following connection-proof version if you're afraid of ctrl+C or using your hardware remotely like me :)
$ nohup ./tools/train_faster_rcnn_alt_opt.py --gpu 0 --net_name INRIA_Person --weights data/imagenet_models/VGG_CNN_M_1024.v2.caffemodel --imdb inria_train --cfg config.yml &
$ tail nohup.out
(Just needs you to launch a "$ killall python" to interrupt training. Yes...)