Showing
6 changed files
with
34 additions
and
29 deletions
... | @@ -24,10 +24,10 @@ anchor_path = data_path + 'yolo_anchors.txt' # The path of the anchor txt file. | ... | @@ -24,10 +24,10 @@ anchor_path = data_path + 'yolo_anchors.txt' # The path of the anchor txt file. |
24 | class_name_path = data_path + 'classes.txt' # The path of the class names. | 24 | class_name_path = data_path + 'classes.txt' # The path of the class names. |
25 | 25 | ||
26 | ### Training releated numbers | 26 | ### Training releated numbers |
27 | -batch_size = 6 | 27 | +batch_size = 10 |
28 | img_size = [416, 416] # Images will be resized to `img_size` and fed to the network, size format: [width, height] | 28 | img_size = [416, 416] # Images will be resized to `img_size` and fed to the network, size format: [width, height] |
29 | letterbox_resize = True # Whether to use the letterbox resize, i.e., keep the original aspect ratio in the resized image. | 29 | letterbox_resize = True # Whether to use the letterbox resize, i.e., keep the original aspect ratio in the resized image. |
30 | -total_epoches = 50 | 30 | +total_epoches = 20 |
31 | train_evaluation_step = 10 # Evaluate on the training batch after some steps. | 31 | train_evaluation_step = 10 # Evaluate on the training batch after some steps. |
32 | val_evaluation_epoch = 2 # Evaluate on the whole validation dataset after some epochs. Set to None to evaluate every epoch. | 32 | val_evaluation_epoch = 2 # Evaluate on the whole validation dataset after some epochs. Set to None to evaluate every epoch. |
33 | save_epoch = 5 # Save the model after some epochs. | 33 | save_epoch = 5 # Save the model after some epochs. |
... | @@ -73,7 +73,7 @@ use_label_smooth = True # Whether to use class label smoothing strategy. | ... | @@ -73,7 +73,7 @@ use_label_smooth = True # Whether to use class label smoothing strategy. |
73 | use_focal_loss = True # Whether to apply focal loss on the conf loss. | 73 | use_focal_loss = True # Whether to apply focal loss on the conf loss. |
74 | use_mix_up = True # Whether to use mix up data augmentation strategy. | 74 | use_mix_up = True # Whether to use mix up data augmentation strategy. |
75 | use_warm_up = True # whether to use warm up strategy to prevent from gradient exploding. | 75 | use_warm_up = True # whether to use warm up strategy to prevent from gradient exploding. |
76 | -warm_up_epoch = 3 # Warm up training epoches. Set to a larger value if gradient explodes. | 76 | +warm_up_epoch = 2 # Warm up training epoches. Set to a larger value if gradient explodes. |
77 | 77 | ||
78 | ### some constants in validation | 78 | ### some constants in validation |
79 | # nms | 79 | # nms | ... | ... |
... | @@ -2,8 +2,13 @@ changes from https://github.com/wizyoung/YOLOv3_TensorFlow | ... | @@ -2,8 +2,13 @@ changes from https://github.com/wizyoung/YOLOv3_TensorFlow |
2 | 2 | ||
3 | by Seongju Kim, kareus1@khu.ac.kr | 3 | by Seongju Kim, kareus1@khu.ac.kr |
4 | 4 | ||
5 | +I only tested in colab environment yet (2020.05.16), | ||
6 | +so let me know if there are some errors/problems in python code version | ||
7 | +(##last changed: 2020.05.16) | ||
8 | + | ||
5 | 1] changed TextLineDataset to TFRecordDataset. (also changed data parsing in data utils and eval utils) | 9 | 1] changed TextLineDataset to TFRecordDataset. (also changed data parsing in data utils and eval utils) |
6 | 2] fixed restore-does-not-exist problem in train/eval mode | 10 | 2] fixed restore-does-not-exist problem in train/eval mode |
7 | 3] fixed saver to save the parameter only when save-optimizer option is true | 11 | 3] fixed saver to save the parameter only when save-optimizer option is true |
8 | 4] changed parameter 'mode' to bool value 'is_training' in data util functions (string value 'mode' is passed as byte string, so functions do not evaluate if-clauses as expected. ex) 'train' != b'train') | 12 | 4] changed parameter 'mode' to bool value 'is_training' in data util functions (string value 'mode' is passed as byte string, so functions do not evaluate if-clauses as expected. ex) 'train' != b'train') |
9 | -5] wrote TFRecord binary iterator, which runs without tf session (references: https://github.com/pgmmpk/tfrecord ) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
13 | +5] wrote TFRecord binary iterator, which runs without tf session (references: https://github.com/pgmmpk/tfrecord ) | ||
14 | +6] removed logging/tenorboard summary code. (I will add it later if necessary) | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -9,22 +9,20 @@ import random | ... | @@ -9,22 +9,20 @@ import random |
9 | PY_VERSION = sys.version_info[0] | 9 | PY_VERSION = sys.version_info[0] |
10 | iter_cnt = 0 | 10 | iter_cnt = 0 |
11 | 11 | ||
12 | -FEATURE_DESCRIPTION = { | 12 | +def _parse_tfrecord(data): |
13 | - 'index': tf.FixedLenFeature([], tf.int64), | 13 | + example = tf.train.Example() |
14 | - 'image': tf.FixedLenFeature([], tf.string), | 14 | + example.ParseFromString(data) |
15 | - 'width': tf.FixedLenFeature([], tf.int64), | 15 | + features = example.features.feature |
16 | - 'height': tf.FixedLenFeature([], tf.int64), | 16 | + return features |
17 | - 'boxes': tf.VarLenFeature(tf.int64) | ||
18 | -} | ||
19 | 17 | ||
20 | def parse_tfrecord(data): | 18 | def parse_tfrecord(data): |
21 | # tfrecord parser for TFRecordDataset (raw data) | 19 | # tfrecord parser for TFRecordDataset (raw data) |
22 | - features = tf.parse_single_example(data, FEATURE_DESCRIPTION) | 20 | + features = _parse_tfrecord(data) |
23 | - index = int(features['index']) | 21 | + index = features['index'].int64_list.value[0] |
24 | - encoded_image = np.frombuffer(features['image'], dtype = np.uint8) | 22 | + encoded_image = np.frombuffer(features['image'].bytes_list.value[0], dtype = np.uint8) |
25 | - width = int(features['width']) | 23 | + width = features['width'].int64_list.value[0] |
26 | - height = int(features['height']) | 24 | + height = features['height'].int64_list.value[0] |
27 | - boxes = features['boxes'].eval() | 25 | + boxes = features['boxes'].int64_list.value |
28 | 26 | ||
29 | assert len(boxes) % 5 == 0, 'Annotation error occured in box array.' | 27 | assert len(boxes) % 5 == 0, 'Annotation error occured in box array.' |
30 | box_cnt = len(boxes) // 5 | 28 | box_cnt = len(boxes) // 5 |
... | @@ -33,7 +31,7 @@ def parse_tfrecord(data): | ... | @@ -33,7 +31,7 @@ def parse_tfrecord(data): |
33 | labels = [] | 31 | labels = [] |
34 | 32 | ||
35 | for i in range(box_cnt): | 33 | for i in range(box_cnt): |
36 | - label, x_min, y_min, x_max, y_max = int(boxes[i * 5]), float(boxes[i * 5 + 1]), float(boxes[i * 5 + 2]), float(boxes[i * 5 + 3]) ## do we need to change int to float? is there float rectangle sample? | 34 | + label, x_min, y_min, x_max, y_max = int(boxes[i * 5]), float(boxes[i * 5 + 1]), float(boxes[i * 5 + 2]), float(boxes[i * 5 + 3]), float(boxes[i * 5 + 4]) ## do we need to change int to float? is there float rectangle sample? |
37 | aligned_boxes.append([x_min, y_min, x_max, y_max]) | 35 | aligned_boxes.append([x_min, y_min, x_max, y_max]) |
38 | labels.append(label) | 36 | labels.append(label) |
39 | 37 | ... | ... |
... | @@ -99,6 +99,8 @@ with tf.Session() as sess: | ... | @@ -99,6 +99,8 @@ with tf.Session() as sess: |
99 | sess.run([tf.global_variables_initializer()]) | 99 | sess.run([tf.global_variables_initializer()]) |
100 | if os.path.exists(args.restore_path): | 100 | if os.path.exists(args.restore_path): |
101 | saver_to_restore.restore(sess, args.restore_path) | 101 | saver_to_restore.restore(sess, args.restore_path) |
102 | + else: | ||
103 | + raise ValueError('there is no model to evaluate. You should move/create the checkpoint file to restore path') | ||
102 | 104 | ||
103 | print('\nStart evaluation...\n') | 105 | print('\nStart evaluation...\n') |
104 | 106 | ... | ... |
... | @@ -22,18 +22,18 @@ pred_scores_flag = tf.placeholder(tf.float32, [1, None, None]) | ... | @@ -22,18 +22,18 @@ pred_scores_flag = tf.placeholder(tf.float32, [1, None, None]) |
22 | gpu_nms_op = gpu_nms(pred_boxes_flag, pred_scores_flag, args.class_num, args.nms_topk, args.score_threshold, args.nms_threshold) | 22 | gpu_nms_op = gpu_nms(pred_boxes_flag, pred_scores_flag, args.class_num, args.nms_topk, args.score_threshold, args.nms_threshold) |
23 | 23 | ||
24 | ### tf.data pipeline | 24 | ### tf.data pipeline |
25 | -train_dataset = tf.data.TFRecordDataset(filenames=train_file, compression_type='GZIP') | 25 | +train_dataset = tf.data.TFRecordDataset(filenames=args.train_file, compression_type='GZIP') |
26 | -train_dataset = train_dataset.shuffle(train_img_cnt) | 26 | +train_dataset = train_dataset.shuffle(args.train_img_cnt) |
27 | -train_dataset = train_dataset.batch(batch_size) | 27 | +train_dataset = train_dataset.batch(args.batch_size) |
28 | train_dataset = train_dataset.map( | 28 | train_dataset = train_dataset.map( |
29 | lambda x: tf.py_func(get_batch_data, | 29 | lambda x: tf.py_func(get_batch_data, |
30 | inp=[x, args.class_num, args.img_size, args.anchors, True, args.multi_scale_train, args.use_mix_up, args.letterbox_resize], | 30 | inp=[x, args.class_num, args.img_size, args.anchors, True, args.multi_scale_train, args.use_mix_up, args.letterbox_resize], |
31 | Tout=[tf.int64, tf.float32, tf.float32, tf.float32, tf.float32]), | 31 | Tout=[tf.int64, tf.float32, tf.float32, tf.float32, tf.float32]), |
32 | num_parallel_calls=args.num_threads | 32 | num_parallel_calls=args.num_threads |
33 | ) | 33 | ) |
34 | -train_dataset = train_dataset.prefetch(prefetech_buffer) | 34 | +train_dataset = train_dataset.prefetch(args.prefetech_buffer) |
35 | 35 | ||
36 | -val_dataset = tf.data.TFRecordDataset(filenames=val_file, compression_type='GZIP') | 36 | +val_dataset = tf.data.TFRecordDataset(filenames=args.val_file, compression_type='GZIP') |
37 | val_dataset = val_dataset.batch(1) | 37 | val_dataset = val_dataset.batch(1) |
38 | val_dataset = val_dataset.map( | 38 | val_dataset = val_dataset.map( |
39 | lambda x: tf.py_func(get_batch_data, | 39 | lambda x: tf.py_func(get_batch_data, |
... | @@ -41,7 +41,7 @@ val_dataset = val_dataset.map( | ... | @@ -41,7 +41,7 @@ val_dataset = val_dataset.map( |
41 | Tout=[tf.int64, tf.float32, tf.float32, tf.float32, tf.float32]), | 41 | Tout=[tf.int64, tf.float32, tf.float32, tf.float32, tf.float32]), |
42 | num_parallel_calls=args.num_threads | 42 | num_parallel_calls=args.num_threads |
43 | ) | 43 | ) |
44 | -val_dataset.prefetch(prefetech_buffer) | 44 | +val_dataset.prefetch(args.prefetech_buffer) |
45 | 45 | ||
46 | iterator = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes) | 46 | iterator = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes) |
47 | train_init_op = iterator.make_initializer(train_dataset) | 47 | train_init_op = iterator.make_initializer(train_dataset) |
... | @@ -71,13 +71,13 @@ saver_to_restore = tf.train.Saver(var_list=tf.contrib.framework.get_variables_to | ... | @@ -71,13 +71,13 @@ saver_to_restore = tf.train.Saver(var_list=tf.contrib.framework.get_variables_to |
71 | update_vars = tf.contrib.framework.get_variables_to_restore(include=update_part) | 71 | update_vars = tf.contrib.framework.get_variables_to_restore(include=update_part) |
72 | 72 | ||
73 | 73 | ||
74 | -global_step = tf.Variable(float(global_step), trainable=False, collections=[tf.GraphKeys.LOCAL_VARIABLES]) | 74 | +global_step = tf.Variable(float(args.global_step), trainable=False, collections=[tf.GraphKeys.LOCAL_VARIABLES]) |
75 | if use_warm_up: | 75 | if use_warm_up: |
76 | learning_rate = tf.cond(tf.less(global_step, train_batch_num * warm_up_epoch), | 76 | learning_rate = tf.cond(tf.less(global_step, train_batch_num * warm_up_epoch), |
77 | lambda: learning_rate_init * global_step / (train_batch_num * warm_up_epoch), | 77 | lambda: learning_rate_init * global_step / (train_batch_num * warm_up_epoch), |
78 | - lambda: config_learning_rate(global_step - args.train_batch_num * args.warm_up_epoch)) | 78 | + lambda: config_learning_rate(args, global_step - args.train_batch_num * args.warm_up_epoch)) |
79 | else: | 79 | else: |
80 | - learning_rate = config_learning_rate(global_step) | 80 | + learning_rate = config_learning_rate(args, global_step) |
81 | 81 | ||
82 | optimizer = config_optimizer(args.optimizer_name, learning_rate) | 82 | optimizer = config_optimizer(args.optimizer_name, learning_rate) |
83 | 83 | ||
... | @@ -105,7 +105,7 @@ with tf.Session() as sess: | ... | @@ -105,7 +105,7 @@ with tf.Session() as sess: |
105 | if os.path.exists(args.restore_path): | 105 | if os.path.exists(args.restore_path): |
106 | saver_to_restore.restore(sess, args.restore_path) | 106 | saver_to_restore.restore(sess, args.restore_path) |
107 | 107 | ||
108 | - print('\nStart training...\n') | 108 | + print('\nStart training...: Total epoches =', args.total_epoches, '\n') |
109 | 109 | ||
110 | best_mAP = -np.Inf | 110 | best_mAP = -np.Inf |
111 | 111 | ||
... | @@ -163,7 +163,7 @@ with tf.Session() as sess: | ... | @@ -163,7 +163,7 @@ with tf.Session() as sess: |
163 | 163 | ||
164 | # calc mAP | 164 | # calc mAP |
165 | rec_total, prec_total, ap_total = AverageMeter(), AverageMeter(), AverageMeter() | 165 | rec_total, prec_total, ap_total = AverageMeter(), AverageMeter(), AverageMeter() |
166 | - gt_dict = parse_gt_rec(args.val_file, args.img_size, args.letterbox_resize) | 166 | + gt_dict = parse_gt_rec(args.val_file, 'GZIP', args.img_size, args.letterbox_resize) |
167 | 167 | ||
168 | info = '======> Epoch: {}, global_step: {}, lr: {:.6g} <======\n'.format(epoch, __global_step, __lr) | 168 | info = '======> Epoch: {}, global_step: {}, lr: {:.6g} <======\n'.format(epoch, __global_step, __lr) |
169 | 169 | ... | ... |
code/yolov3/yolov3.ipynb
0 → 100644
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment