Skip to content

Commit 95017dc

Browse files
training instructions + training scripts done
1 parent d219340 commit 95017dc

File tree

5 files changed

+423
-3
lines changed

5 files changed

+423
-3
lines changed

README.md

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ To run the examples in this repo, you will need some more dependencies:
105105
pip install opencv-python
106106
pip install opencv-contrib-python
107107
```
108+
------------------------------------------------------------
108109

109110
## Inference with pre-trained models
110111

@@ -152,6 +153,7 @@ Let's use video input by enabling the flag `--video_input`, in addition to detec
152153
python detect_objects.py --video_input --class_ids "1" --threshold 0.3 --video_path data/samples/pedestrian_test.mp4 --model_path models/efficientdet_d0_coco17_tpu-32/saved_model --path_to_labelmap models/mscoco_label_map.pbtxt
153154
```
154155

156+
------------------------------------------------------------
155157

156158
## Preparing your custom dataset for training
157159

@@ -181,7 +183,8 @@ I have used the examples provided, and solved some issues to make it work with T
181183
You can find my file in [data_gen/generate_tfrecord.py](data_gen/generate_tfrecord.py), and you can use it as follows:
182184

183185
```bash
184-
python generate_tfrecord.py --path_to_images $DATASET_PATH/train/images --path_to_annot ../data/raccoon_data/train_labels.csv \
186+
python generate_tfrecord.py --path_to_images ../data/raccoon_data/train/images \
187+
--path_to_annot ../data/raccoon_data/train_labels.csv \
185188
--path_to_label_map ../models/raccoon_labelmap.pbtxt \
186189
--path_to_save_tfrecords ../data/raccoon_data/train.record
187190
```
@@ -194,14 +197,113 @@ cd data_gen/
194197
bash gen_data.sh
195198
```
196199

197-
After running this command, you will find the generated csv and tfrecords (.record) files located in [data/raccoon_data](data/raccoon_data).
200+
After running this command, you will find the generated csv and tfrecords (`.record` or `.tfrecord`) files located in [data/raccoon_data](data/raccoon_data).
198201
Et voila, we have the tfrecord files generated, and we can use it in next steps for training.
199202

203+
------------------------------------------------------------
200204

201205
## Training object detection model with your custom dataset
202206

203-
TODO
207+
To start training our model, we need to prepare a configuration file specifying the backbone model and all the required parameters for training and evaluation.
208+
In this [tutorial](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/configuring_jobs.md) from the object detection api you can find explanation of all the required parameters.
209+
But fortunately, they also provide us with many [example config files](https://github.com/tensorflow/models/tree/master/research/object_detection/configs/tf2) that we can use and just modify some parameters to match our requirements.
210+
211+
Here I will be using the the config file of the SSD model with MobileNetV2 backbone as it is small model that can fit in small GPU memory.
212+
So let's first download the pretrained model with coco dataset that is provided in the [model zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf2_detection_zoo.md), and use it as initialization to our model.
213+
This is called fine-tuning, which is simply loading the weights of pretrained model, and use it as a starting point in our training. This will help us too much as we have very small number of images.
214+
You can read more about transfer learning methods from [here](https://cs231n.github.io/transfer-learning/).
215+
216+
```bash
217+
cd models/
218+
# download the mobilenet_v2 model
219+
wget http://download.tensorflow.org/models/object_detection/tf2/20200711/ssd_mobilenet_v2_320x320_coco17_tpu-8.tar.gz
220+
# extract the downloaded file
221+
tar -xzvf ssd_mobilenet_v2_320x320_coco17_tpu-8.tar.gz
222+
```
223+
224+
Then you can download the original config file from [here](https://github.com/tensorflow/models/tree/master/research/object_detection/configs/tf2).
225+
I downloaded [ssd_mobilenet_v2_320x320_coco17_tpu-8.config](https://github.com/tensorflow/models/blob/master/research/object_detection/configs/tf2/ssd_mobilenet_v2_320x320_coco17_tpu-8.config) and made the following changes:
226+
227+
* Changed `num_classes: 1` as we have only class (raccoon), instead of 90 classes in coco dataset.
228+
* Changed `fine_tune_checkpoint_type: "classification"` to `fine_tune_checkpoint_type: "detection"` as we will be using the pre-trained detection model as initialization.
229+
* Added the path of the pretrained model in the field `fine_tune_checkpoint:`, for example using the mobilenet v2 model I added `fine_tune_checkpoint: "../models/ssd_mobilenet_v2_320x320_coco17_tpu-8/checkpoint/ckpt-0"`
230+
* Changed `batch_size: 512` and used a reasonable number to my GPU memory. I have a 4GB of GPU memory, so I am using `batch_size: 16`
231+
* Added the maximum number of training iterations in `num_steps:`, and also use the same number in `total_steps:`
232+
* Adapted the learning rate to our model and batch size (originally they used higher learning rates because they had bigger batch sizes). This values needs some testing and tuning, but finally I used this configuration:
233+
```
234+
cosine_decay_learning_rate {
235+
learning_rate_base: 0.03
236+
total_steps: 3000
237+
warmup_learning_rate: 0.005
238+
warmup_steps: 100 }
239+
```
240+
* The `label_map_path:` should point to your labelmap (here the raccoon labelmap) `label_map_path: "../models/raccoon_labelmap.pbtxt"`
241+
* You need to set the `tf_record_input_reader` under both `train_input_reader` and `eval_input_reader`. This should point to the tfrecords we generated.
242+
```
243+
train_input_reader: {
244+
label_map_path: "../models/raccoon_labelmap.pbtxt"
245+
tf_record_input_reader {
246+
input_path: "../data/raccoon_data/train.record"
247+
}
248+
}
249+
```
250+
251+
Yous should also prepare the labelmap according to your data. For our raccoon dataset, the labelmap file contains:
252+
253+
```
254+
item {
255+
id: 1
256+
name: 'raccoon'
257+
}
258+
```
259+
260+
The labelmap file and the modified configuration files are added to this repo for convenience.
261+
You can find them is [models/raccoon_labelmap.pbtxt](models/raccoon_labelmap.pbtxt) and [models/ssd_mobilenet_v2_raccoon.config](models/ssd_mobilenet_v2_raccoon.config).
262+
263+
Once you prepare the configuration file, you can start training by typing the following commands:
264+
265+
```bash
266+
cd train_tf2
267+
bash start_train.sh
268+
```
269+
270+
The [start_train.sh](train_tf2/start_train.sh) file is a simple shell script that contains all the parameters needed for training, and runs the training script.
271+
The shell file contains the following command:
272+
273+
```bash
274+
out_dir=../models/ssd_mobilenet_v2_raccoon/
275+
mkdir -p $out_dir
276+
python model_main_tf2.py --alsologtostderr --model_dir=$out_dir --checkpoint_every_n=500 \
277+
--pipeline_config_path=../models/ssd_mobilenet_v2_raccoon.config \
278+
--eval_on_train_data 2>&1 | tee $out_dir/train.log
279+
```
280+
281+
It is also recommended to run the validation script along with the training scripts.
282+
The training script saves a checkpoint every _n_ steps while training, and this value can be specified in the parameter `--checkpoint_every_n`.
283+
While training is running, the validation script reads these checkpoints once they are available, and use them to evaluate the model with the validation set.
284+
This will help us to monitor the training progress by printing the values on the terminal, or by using a GUI monitoring package like [tensorboard](https://www.tensorflow.org/tensorboard/get_started) as we will see.
285+
286+
To run the validation script along with training script, open another terminal and run:
287+
288+
```bash
289+
bash start_eval.sh
290+
```
291+
292+
The [start_eval.sh](train_tf2/start_eval.sh) file contains:
293+
294+
```bash
295+
out_dir=../models/ssd_mobilenet_v2_raccoon/
296+
mkdir -p $out_dir
297+
python model_main_tf2.py --alsologtostderr --model_dir=$out_dir \
298+
--pipeline_config_path=../models/ssd_mobilenet_v2_raccoon.config \
299+
--checkpoint_dir=$out_dir 2>&1 | tee $out_dir/eval.log
300+
```
301+
302+
If you don't have enough resources, you can ignore running the validation script, and run it only once when the training is done.
303+
304+
204305

306+
---
205307

206308
## Exporting your trained model for inference
207309

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# SSD with Mobilenet v2
2+
3+
model {
4+
ssd {
5+
inplace_batchnorm_update: true
6+
freeze_batchnorm: false
7+
num_classes: 1
8+
box_coder {
9+
faster_rcnn_box_coder {
10+
y_scale: 10.0
11+
x_scale: 10.0
12+
height_scale: 5.0
13+
width_scale: 5.0
14+
}
15+
}
16+
matcher {
17+
argmax_matcher {
18+
matched_threshold: 0.4
19+
unmatched_threshold: 0.4
20+
ignore_thresholds: false
21+
negatives_lower_than_unmatched: true
22+
force_match_for_each_row: true
23+
use_matmul_gather: true
24+
}
25+
}
26+
similarity_calculator {
27+
iou_similarity {
28+
}
29+
}
30+
encode_background_as_zeros: true
31+
anchor_generator {
32+
ssd_anchor_generator {
33+
num_layers: 6
34+
min_scale: 0.15
35+
max_scale: 0.95
36+
aspect_ratios: 1.0
37+
aspect_ratios: 2.0
38+
aspect_ratios: 0.5
39+
}
40+
}
41+
image_resizer {
42+
fixed_shape_resizer {
43+
height: 300
44+
width: 300
45+
}
46+
}
47+
box_predictor {
48+
convolutional_box_predictor {
49+
min_depth: 0
50+
max_depth: 0
51+
num_layers_before_predictor: 0
52+
use_dropout: false
53+
dropout_keep_probability: 0.8
54+
kernel_size: 1
55+
box_code_size: 4
56+
apply_sigmoid_to_scores: false
57+
class_prediction_bias_init: -4.6
58+
conv_hyperparams {
59+
activation: RELU_6,
60+
regularizer {
61+
l2_regularizer {
62+
weight: 0.00004
63+
}
64+
}
65+
initializer {
66+
random_normal_initializer {
67+
stddev: 0.01
68+
mean: 0.0
69+
}
70+
}
71+
batch_norm {
72+
train: true,
73+
scale: true,
74+
center: true,
75+
decay: 0.97,
76+
epsilon: 0.001,
77+
}
78+
}
79+
}
80+
}
81+
feature_extractor {
82+
type: 'ssd_mobilenet_v2_keras'
83+
min_depth: 16
84+
depth_multiplier: 1.0
85+
conv_hyperparams {
86+
activation: RELU_6,
87+
regularizer {
88+
l2_regularizer {
89+
weight: 0.00004
90+
}
91+
}
92+
initializer {
93+
truncated_normal_initializer {
94+
stddev: 0.03
95+
mean: 0.0
96+
}
97+
}
98+
batch_norm {
99+
train: true,
100+
scale: true,
101+
center: true,
102+
decay: 0.97,
103+
epsilon: 0.001,
104+
}
105+
}
106+
override_base_feature_extractor_hyperparams: true
107+
}
108+
loss {
109+
classification_loss {
110+
weighted_sigmoid_focal {
111+
alpha: 0.75,
112+
gamma: 2.0
113+
}
114+
}
115+
localization_loss {
116+
weighted_smooth_l1 {
117+
delta: 1.0
118+
}
119+
}
120+
classification_weight: 1.0
121+
localization_weight: 1.0
122+
}
123+
normalize_loss_by_num_matches: true
124+
normalize_loc_loss_by_codesize: true
125+
post_processing {
126+
batch_non_max_suppression {
127+
score_threshold: 0.001
128+
iou_threshold: 0.4
129+
max_detections_per_class: 100
130+
max_total_detections: 100
131+
}
132+
score_converter: SIGMOID
133+
}
134+
}
135+
}
136+
137+
train_config: {
138+
fine_tune_checkpoint_version: V2
139+
fine_tune_checkpoint: "../models/ssd_mobilenet_v2_320x320_coco17_tpu-8/checkpoint/ckpt-0"
140+
fine_tune_checkpoint_type: "detection"
141+
batch_size: 16
142+
sync_replicas: true
143+
startup_delay_steps: 0
144+
replicas_to_aggregate: 8
145+
num_steps: 3000
146+
data_augmentation_options {
147+
random_horizontal_flip {
148+
}
149+
}
150+
data_augmentation_options {
151+
ssd_random_crop {
152+
}
153+
}
154+
optimizer {
155+
momentum_optimizer: {
156+
learning_rate: {
157+
cosine_decay_learning_rate {
158+
learning_rate_base: 0.035
159+
total_steps: 3000
160+
warmup_learning_rate: 0.005
161+
warmup_steps: 100
162+
}
163+
}
164+
momentum_optimizer_value: 0.9
165+
}
166+
use_moving_average: false
167+
}
168+
max_number_of_boxes: 100
169+
unpad_groundtruth_tensors: false
170+
}
171+
172+
train_input_reader: {
173+
label_map_path: "../models/raccoon_labelmap.pbtxt"
174+
tf_record_input_reader {
175+
input_path: "../data/raccoon_data/train.record"
176+
}
177+
}
178+
179+
eval_config: {
180+
metrics_set: "coco_detection_metrics"
181+
use_moving_averages: false
182+
}
183+
184+
eval_input_reader: {
185+
label_map_path: "../models/raccoon_labelmap.pbtxt"
186+
shuffle: false
187+
num_epochs: 1
188+
tf_record_input_reader {
189+
input_path: "../data/raccoon_data/val.record"
190+
}
191+
}

0 commit comments

Comments
 (0)