diff --git a/README.md b/README.md index 0fefe77bb4c078a15c4f02a6d189a240cf304de6..23558c5a9e7c099c1599da7bfa1d25ac910fe87a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## 简介 -PaddleSeg是基于[PaddlePaddle](https://www.paddlepaddle.org.cn)开发的语义分割库,覆盖了DeepLabv3+, U-Net, ICNet, PSPNet, HRNet等主流分割模型。通过统一的配置,帮助用户更便捷地完成从训练到部署的全流程图像分割应用。 +PaddleSeg是基于[PaddlePaddle](https://www.paddlepaddle.org.cn)开发的语义分割库,覆盖了DeepLabv3+, U-Net, ICNet, PSPNet, HRNet, Fast-SCNN等主流分割模型。通过统一的配置,帮助用户更便捷地完成从训练到部署的全流程图像分割应用。
@@ -33,7 +33,7 @@ PaddleSeg是基于[PaddlePaddle](https://www.paddlepaddle.org.cn)开发的语义 - **模块化设计** -支持U-Net, DeepLabv3+, ICNet, PSPNet, HRNet五种主流分割网络,结合预训练模型和可调节的骨干网络,满足不同性能和精度的要求;选择不同的损失函数如Dice Loss, BCE Loss等方式可以强化小目标和不均衡样本场景下的分割精度。 +支持U-Net, DeepLabv3+, ICNet, PSPNet, HRNet, Fast-SCNN六种主流分割网络,结合预训练模型和可调节的骨干网络,满足不同性能和精度的要求;选择不同的损失函数如Dice Loss, BCE Loss等方式可以强化小目标和不均衡样本场景下的分割精度。 - **高性能** @@ -163,6 +163,14 @@ A: 请将PaddlePaddle升级至1.5.2版本或以上。

   微信公众号                官方技术交流QQ群

## 更新日志 +* 2020.02.25 + + **`v0.4.0`** + * 新增适用于实时场景且不需要预训练模型的分割网络Fast-SCNN,提供基于Cityscapes的[预训练模型](./docs/model_zoo.md)1个。 + * 新增LaneNet车道线检测网络,提供[预训练模型](https://github.com/PaddlePaddle/PaddleSeg/tree/release/v0.4.0/contrib/LaneNet#%E4%B8%83-%E5%8F%AF%E8%A7%86%E5%8C%96)一个。 + * 新增基于PaddleSlim的分割库压缩策略([量化](./slim/quantization/README.md), [蒸馏](./slim/distillation/README.md), [剪枝](./slim/prune/README.md), [搜索](./slim/nas/README.md)) + + * 2019.12.15 **`v0.3.0`** diff --git a/contrib/LaneNet/README.md b/contrib/LaneNet/README.md index b86777305c160edae7a55349d719c9df2a2da4f9..1448951e900dbb8bb235be476698eb13d62f5e4c 100644 --- a/contrib/LaneNet/README.md +++ b/contrib/LaneNet/README.md @@ -108,7 +108,7 @@ SOLVER: 使用下述命令启动训练 ```shell -CUDA_VISIBLE_DEVICES=0 python -u train.py --cfg configs/lanenet.yaml --use_gpu --use_mpio --do_eval +CUDA_VISIBLE_DEVICES=0 python -u train.py --cfg configs/lanenet.yaml --use_gpu --do_eval ``` ## 六. 进行评估 diff --git a/contrib/LaneNet/eval.py b/contrib/LaneNet/eval.py index 9256c4f024e7d15c9c018c4fe5930e5b7865c7e0..025fb4e7284adefdafa4365ace347a68e2addf48 100644 --- a/contrib/LaneNet/eval.py +++ b/contrib/LaneNet/eval.py @@ -101,10 +101,10 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): for b in data_gen: yield b - py_reader, pred, grts, masks, accuracy, fp, fn = build_model( + data_loader, pred, grts, masks, accuracy, fp, fn = build_model( test_prog, startup_prog, phase=ModelPhase.EVAL) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, drop_last=False, batch_size=cfg.BATCH_SIZE) # Get device environment @@ -127,7 +127,9 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): # Use streaming confusion matrix to calculate mean_iou np.set_printoptions( precision=4, suppress=True, linewidth=160, floatmode="fixed") - fetch_list = [pred.name, grts.name, masks.name, accuracy.name, fp.name, fn.name] + fetch_list = [ + pred.name, grts.name, masks.name, accuracy.name, fp.name, fn.name + ] num_images = 0 step = 0 avg_acc = 0.0 @@ -137,7 +139,7 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): all_step = cfg.DATASET.TEST_TOTAL_IMAGES // cfg.BATCH_SIZE + 1 timer = Timer() timer.start() - py_reader.start() + data_loader.start() while True: try: step += 1 @@ -153,7 +155,8 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): print( "[EVAL]step={} accuracy={:.4f} fp={:.4f} fn={:.4f} step/sec={:.2f} | ETA {}" - .format(step, avg_acc / num_images, avg_fp / num_images, avg_fn / num_images, speed, + .format(step, avg_acc / num_images, avg_fp / num_images, + avg_fn / num_images, speed, calculate_eta(all_step - step, speed))) timer.restart() @@ -162,7 +165,8 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): break print("[EVAL]#image={} accuracy={:.4f} fp={:.4f} fn={:.4f}".format( - num_images, avg_acc / num_images, avg_fp / num_images, avg_fn / num_images)) + num_images, avg_acc / num_images, avg_fp / num_images, + avg_fn / num_images)) return avg_acc / num_images, avg_fp / num_images, avg_fn / num_images diff --git a/contrib/LaneNet/models/model_builder.py b/contrib/LaneNet/models/model_builder.py index ed6c275ecd51a2fc9f7f2fdf125300ce026c0a0a..b274e95a7b761f0345923c7702f91420a2469404 100644 --- a/contrib/LaneNet/models/model_builder.py +++ b/contrib/LaneNet/models/model_builder.py @@ -25,6 +25,7 @@ from pdseg.loss import multi_softmax_with_loss from loss import discriminative_loss from models.modeling import lanenet + class ModelPhase(object): """ Standard name for model phase in PaddleSeg @@ -107,35 +108,31 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): width = cfg.EVAL_CROP_SIZE[0] height = cfg.EVAL_CROP_SIZE[1] - image_shape = [cfg.DATASET.DATA_DIM, height, width] - grt_shape = [1, height, width] + image_shape = [-1, cfg.DATASET.DATA_DIM, height, width] + grt_shape = [-1, 1, height, width] class_num = cfg.DATASET.NUM_CLASSES with fluid.program_guard(main_prog, start_prog): with fluid.unique_name.guard(): - image = fluid.layers.data( - name='image', shape=image_shape, dtype='float32') - label = fluid.layers.data( - name='label', shape=grt_shape, dtype='int32') + image = fluid.data(name='image', shape=image_shape, dtype='float32') + label = fluid.data(name='label', shape=grt_shape, dtype='int32') if cfg.MODEL.MODEL_NAME == 'lanenet': - label_instance = fluid.layers.data( + label_instance = fluid.data( name='label_instance', shape=grt_shape, dtype='int32') - mask = fluid.layers.data( - name='mask', shape=grt_shape, dtype='int32') + mask = fluid.data(name='mask', shape=grt_shape, dtype='int32') - # use PyReader when doing traning and evaluation + # use DataLoader.from_generator when doing traning and evaluation if ModelPhase.is_train(phase) or ModelPhase.is_eval(phase): - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[image, label, label_instance, mask], capacity=cfg.DATALOADER.BUF_SIZE, iterable=False, use_double_buffer=True) - loss_type = cfg.SOLVER.LOSS if not isinstance(loss_type, list): loss_type = list(loss_type) - + logits = seg_model(image, class_num) if ModelPhase.is_train(phase): @@ -144,25 +141,30 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): if cfg.MODEL.MODEL_NAME == 'lanenet': embeding_logit = logits[1] logits = logits[0] - disc_loss, _, _, l_reg = discriminative_loss(embeding_logit, label_instance, 4, - image_shape[1:], 0.5, 3.0, 1.0, 1.0, 0.001) + disc_loss, _, _, l_reg = discriminative_loss( + embeding_logit, label_instance, 4, image_shape[2:], 0.5, + 3.0, 1.0, 1.0, 0.001) if "softmax_loss" in loss_type: weight = None if cfg.MODEL.MODEL_NAME == 'lanenet': weight = get_dynamic_weight(label) - seg_loss = multi_softmax_with_loss(logits, label, mask, class_num, weight) + seg_loss = multi_softmax_with_loss(logits, label, mask, + class_num, weight) loss_valid = True valid_loss.append("softmax_loss") if not loss_valid: - raise Exception("SOLVER.LOSS: {} is set wrong. it should " - "include one of (softmax_loss, bce_loss, dice_loss) at least" - " example: ['softmax_loss']".format(cfg.SOLVER.LOSS)) + raise Exception( + "SOLVER.LOSS: {} is set wrong. it should " + "include one of (softmax_loss, bce_loss, dice_loss) at least" + " example: ['softmax_loss']".format(cfg.SOLVER.LOSS)) invalid_loss = [x for x in loss_type if x not in valid_loss] if len(invalid_loss) > 0: - print("Warning: the loss {} you set is invalid. it will not be included in loss computed.".format(invalid_loss)) + print( + "Warning: the loss {} you set is invalid. it will not be included in loss computed." + .format(invalid_loss)) avg_loss = disc_loss + 0.00001 * l_reg + seg_loss @@ -202,12 +204,12 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): accuracy, fp, fn = compute_metric(pred, label) if ModelPhase.is_eval(phase): - return py_reader, pred, label, mask, accuracy, fp, fn + return data_loader, pred, label, mask, accuracy, fp, fn if ModelPhase.is_train(phase): optimizer = solver.Solver(main_prog, start_prog) decayed_lr = optimizer.optimise(avg_loss) - return py_reader, avg_loss, decayed_lr, pred, label, mask, disc_loss, seg_loss, accuracy, fp, fn + return data_loader, avg_loss, decayed_lr, pred, label, mask, disc_loss, seg_loss, accuracy, fp, fn def compute_metric(pred, label): @@ -216,19 +218,27 @@ def compute_metric(pred, label): idx = fluid.layers.where(pred == 1) pix_cls_ret = fluid.layers.gather_nd(label, idx) - correct_num = fluid.layers.reduce_sum(fluid.layers.cast(pix_cls_ret, 'float32')) + correct_num = fluid.layers.reduce_sum( + fluid.layers.cast(pix_cls_ret, 'float32')) - gt_num = fluid.layers.cast(fluid.layers.shape(fluid.layers.gather_nd(label, - fluid.layers.where(label == 1)))[0], 'int64') - pred_num = fluid.layers.cast(fluid.layers.shape(fluid.layers.gather_nd(pred, idx))[0], 'int64') + gt_num = fluid.layers.cast( + fluid.layers.shape( + fluid.layers.gather_nd(label, fluid.layers.where(label == 1)))[0], + 'int64') + pred_num = fluid.layers.cast( + fluid.layers.shape(fluid.layers.gather_nd(pred, idx))[0], 'int64') accuracy = correct_num / gt_num false_pred = pred_num - correct_num - fp = fluid.layers.cast(false_pred, 'float32') / fluid.layers.cast(fluid.layers.shape(pix_cls_ret)[0], 'int64') - - label_cls_ret = fluid.layers.gather_nd(label, fluid.layers.where(label == 1)) - mis_pred = fluid.layers.cast(fluid.layers.shape(label_cls_ret)[0], 'int64') - correct_num - fn = fluid.layers.cast(mis_pred, 'float32') / fluid.layers.cast(fluid.layers.shape(label_cls_ret)[0], 'int64') + fp = fluid.layers.cast(false_pred, 'float32') / fluid.layers.cast( + fluid.layers.shape(pix_cls_ret)[0], 'int64') + + label_cls_ret = fluid.layers.gather_nd(label, + fluid.layers.where(label == 1)) + mis_pred = fluid.layers.cast(fluid.layers.shape(label_cls_ret)[0], + 'int64') - correct_num + fn = fluid.layers.cast(mis_pred, 'float32') / fluid.layers.cast( + fluid.layers.shape(label_cls_ret)[0], 'int64') accuracy.stop_gradient = True fp.stop_gradient = True fn.stop_gradient = True @@ -239,7 +249,8 @@ def get_dynamic_weight(label): label = fluid.layers.reshape(label, [-1]) unique_labels, unique_id, counts = fluid.layers.unique_with_counts(label) counts = fluid.layers.cast(counts, 'float32') - weight = 1.0 / fluid.layers.log((counts / fluid.layers.reduce_sum(counts) + 1.02)) + weight = 1.0 / fluid.layers.log( + (counts / fluid.layers.reduce_sum(counts) + 1.02)) return weight diff --git a/contrib/LaneNet/train.py b/contrib/LaneNet/train.py index 3ee9489c9b18b19b6b84615a400815a3bc33ccb2..c2f5bee7547eabe9ef5c998b197fbaf59130d679 100644 --- a/contrib/LaneNet/train.py +++ b/contrib/LaneNet/train.py @@ -232,9 +232,9 @@ def train(cfg): cfg.BATCH_SIZE_PER_DEV = batch_size_per_dev print_info("batch_size_per_dev: {}".format(batch_size_per_dev)) - py_reader, avg_loss, lr, pred, grts, masks, emb_loss, seg_loss, accuracy, fp, fn = build_model( + data_loader, avg_loss, lr, pred, grts, masks, emb_loss, seg_loss, accuracy, fp, fn = build_model( train_prog, startup_prog, phase=ModelPhase.TRAIN) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -315,7 +315,10 @@ def train(cfg): format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) # fetch_list = [avg_loss.name, lr.name, accuracy.name, precision.name, recall.name] - fetch_list = [avg_loss.name, lr.name, seg_loss.name, emb_loss.name, accuracy.name, fp.name, fn.name] + fetch_list = [ + avg_loss.name, lr.name, seg_loss.name, emb_loss.name, accuracy.name, + fp.name, fn.name + ] if args.debug: # Fetch more variable info and use streaming confusion matrix to # calculate IoU results if in debug mode @@ -359,7 +362,7 @@ def train(cfg): print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: # If not in debug mode, avoid unnessary log and calculate @@ -385,16 +388,15 @@ def train(cfg): avg_fn /= args.log_steps speed = args.log_steps / timer.elapsed_time() print(( - "epoch={} step={} lr={:.5f} loss={:.4f} seg_loss={:.4f} emb_loss={:.4f} accuracy={:.4} fp={:.4} fn={:.4} step/sec={:.3f} | ETA {}" - ).format(epoch, global_step, lr[0], avg_loss, avg_seg_loss, avg_emb_loss, avg_acc, avg_fp, avg_fn, speed, - calculate_eta(all_step - global_step, speed))) + "epoch={} step={} lr={:.5f} loss={:.4f} seg_loss={:.4f} emb_loss={:.4f} accuracy={:.4} fp={:.4} fn={:.4} step/sec={:.3f} | ETA {}" + ).format(epoch, global_step, lr[0], avg_loss, avg_seg_loss, + avg_emb_loss, avg_acc, avg_fp, avg_fn, speed, + calculate_eta(all_step - global_step, speed))) if args.use_tb: log_writer.add_scalar('Train/loss', avg_loss, global_step) - log_writer.add_scalar('Train/lr', lr[0], - global_step) - log_writer.add_scalar('Train/speed', speed, - global_step) + log_writer.add_scalar('Train/lr', lr[0], global_step) + log_writer.add_scalar('Train/speed', speed, global_step) sys.stdout.flush() avg_loss = 0.0 avg_seg_loss = 0.0 @@ -405,7 +407,7 @@ def train(cfg): timer.restart() except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) @@ -423,10 +425,8 @@ def train(cfg): if args.use_tb: log_writer.add_scalar('Evaluate/accuracy', accuracy, global_step) - log_writer.add_scalar('Evaluate/fp', fp, - global_step) - log_writer.add_scalar('Evaluate/fn', fn, - global_step) + log_writer.add_scalar('Evaluate/fp', fp, global_step) + log_writer.add_scalar('Evaluate/fn', fn, global_step) # Use Tensorboard to visualize results if args.use_tb and cfg.DATASET.VIS_FILE_LIST is not None: diff --git a/docs/imgs/fast-scnn.png b/docs/imgs/fast-scnn.png new file mode 100644 index 0000000000000000000000000000000000000000..2b00eb88401b9981a6d59595bbdf4e1f692db934 Binary files /dev/null and b/docs/imgs/fast-scnn.png differ diff --git a/docs/models.md b/docs/models.md index a452aa3639c3901d8f75d1aa4f5f1b7f393ce0b7..c36fff5fc88aef362f3ab4f7175b7d60f579e418 100644 --- a/docs/models.md +++ b/docs/models.md @@ -5,6 +5,7 @@ - [PSPNet](#PSPNet) - [ICNet](#ICNet) - [HRNet](#HRNet) +- [Fast-SCNN](#Fast-SCNN) ## U-Net U-Net [1] 起源于医疗图像分割,整个网络是标准的encoder-decoder网络,特点是参数少,计算快,应用性强,对于一般场景适应度很高。U-Net最早于2015年提出,并在ISBI 2015 Cell Tracking Challenge取得了第一。经过发展,目前有多个变形和应用。 @@ -58,6 +59,14 @@ HRNet在人体姿态估计、语义分割和目标检测领域都取得了显著 ![](./imgs/hrnet.png) +### Fast-SCNN + +Fast-SCNN [7] 是一个面向实时的语义分割网络。在双分支的结构基础上,大量使用了深度可分离卷积和逆残差(inverted-residual)模块,并且使用特征融合构造金字塔池化模块 (Pyramid Pooling Module)来融合上下文信息。这使得Fast-SCNN在保持高效的情况下能学习到丰富的细节信息。 + +整个网络结构如下: + +![](./imgs/fast-scnn.png) + ## 参考文献 [1] [U-Net: Convolutional Networks for Biomedical Image Segmentation](https://arxiv.org/abs/1505.04597) @@ -72,3 +81,6 @@ HRNet在人体姿态估计、语义分割和目标检测领域都取得了显著 [6] [Deep High-Resolution Representation Learning for Visual Recognition](https://arxiv.org/abs/1908.07919) +[7] [Fast-SCNN: Fast Semantic Segmentation Network](https://arxiv.org/abs/1902.04502) + + diff --git a/pdseg/eval.py b/pdseg/eval.py index b842431fb895c0985da1de5d5ef65073534a9835..426e52f9287bbdb5e4b2e2a4bb617ee910aeff5e 100644 --- a/pdseg/eval.py +++ b/pdseg/eval.py @@ -92,10 +92,10 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): for b in data_gen: yield b[0], b[1], b[2] - py_reader, avg_loss, pred, grts, masks = build_model( + data_loader, avg_loss, pred, grts, masks = build_model( test_prog, startup_prog, phase=ModelPhase.EVAL) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, drop_last=False, batch_size=cfg.BATCH_SIZE) # Get device environment @@ -128,7 +128,7 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): all_step = cfg.DATASET.TEST_TOTAL_IMAGES // cfg.BATCH_SIZE + 1 timer = Timer() timer.start() - py_reader.start() + data_loader.start() while True: try: step += 1 diff --git a/pdseg/models/backbone/mobilenet_v2.py b/pdseg/models/backbone/mobilenet_v2.py index ba9c2e7812cb2e19cc839e84b201e45c357cc692..740284b319bd836d9c27682c1c22d556d2b98aa1 100644 --- a/pdseg/models/backbone/mobilenet_v2.py +++ b/pdseg/models/backbone/mobilenet_v2.py @@ -308,8 +308,8 @@ def MobileNetV2_scale(): if __name__ == '__main__': - image_shape = [3, 224, 224] - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') + image_shape = [-1, 3, 224, 224] + image = fluid.data(name='image', shape=image_shape, dtype='float32') model = MobileNetV2_x1_0() logit, decode_ends = model.net(image) #print("logit:", logit.shape) diff --git a/pdseg/models/backbone/xception.py b/pdseg/models/backbone/xception.py index 09b356973bdafc21952eaa9c88ab43c861677d57..5c07f240625744356c5df4644342cff6c81af687 100644 --- a/pdseg/models/backbone/xception.py +++ b/pdseg/models/backbone/xception.py @@ -311,7 +311,7 @@ def xception_71(): if __name__ == '__main__': - image_shape = [3, 224, 224] - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') + image_shape = [-1, 3, 224, 224] + image = fluid.data(name='image', shape=image_shape, dtype='float32') model = xception_65() logit = model.net(image) diff --git a/pdseg/models/model_builder.py b/pdseg/models/model_builder.py index 668d69e44aeb91cc7705a79f092730ae6a1fdb09..4092a41718ef2e7109b33e99a5777860569df741 100644 --- a/pdseg/models/model_builder.py +++ b/pdseg/models/model_builder.py @@ -166,8 +166,8 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): width = cfg.EVAL_CROP_SIZE[0] height = cfg.EVAL_CROP_SIZE[1] - image_shape = [cfg.DATASET.DATA_DIM, height, width] - grt_shape = [1, height, width] + image_shape = [-1, cfg.DATASET.DATA_DIM, height, width] + grt_shape = [-1, 1, height, width] class_num = cfg.DATASET.NUM_CLASSES with fluid.program_guard(main_prog, start_prog): @@ -175,25 +175,22 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): # 在导出模型的时候,增加图像标准化预处理,减小预测部署时图像的处理流程 # 预测部署时只须对输入图像增加batch_size维度即可 if ModelPhase.is_predict(phase): - origin_image = fluid.layers.data( + origin_image = fluid.data( name='image', shape=[-1, -1, -1, cfg.DATASET.DATA_DIM], - dtype='float32', - append_batch_size=False) + dtype='float32') image, valid_shape, origin_shape = export_preprocess( origin_image) else: - image = fluid.layers.data( + image = fluid.data( name='image', shape=image_shape, dtype='float32') - label = fluid.layers.data( - name='label', shape=grt_shape, dtype='int32') - mask = fluid.layers.data( - name='mask', shape=grt_shape, dtype='int32') + label = fluid.data(name='label', shape=grt_shape, dtype='int32') + mask = fluid.data(name='mask', shape=grt_shape, dtype='int32') - # use PyReader when doing traning and evaluation + # use DataLoader when doing traning and evaluation if ModelPhase.is_train(phase) or ModelPhase.is_eval(phase): - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[image, label, mask], capacity=cfg.DATALOADER.BUF_SIZE, iterable=False, @@ -227,7 +224,8 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): if "softmax_loss" in loss_type: weight = cfg.SOLVER.CROSS_ENTROPY_WEIGHT avg_loss_list.append( - multi_softmax_with_loss(logits, label, mask, class_num, weight)) + multi_softmax_with_loss(logits, label, mask, class_num, + weight)) loss_valid = True valid_loss.append("softmax_loss") if "dice_loss" in loss_type: @@ -300,12 +298,12 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN): return pred, logit if ModelPhase.is_eval(phase): - return py_reader, avg_loss, pred, label, mask + return data_loader, avg_loss, pred, label, mask if ModelPhase.is_train(phase): optimizer = solver.Solver(main_prog, start_prog) decayed_lr = optimizer.optimise(avg_loss) - return py_reader, avg_loss, decayed_lr, pred, label, mask + return data_loader, avg_loss, decayed_lr, pred, label, mask def to_int(string, dest="I"): diff --git a/pdseg/models/modeling/hrnet.py b/pdseg/models/modeling/hrnet.py index 741834e157105b233403772f2672ed60aafc488f..4b95461a1adf5c96cd8737540b3509944ea7900e 100644 --- a/pdseg/models/modeling/hrnet.py +++ b/pdseg/models/modeling/hrnet.py @@ -202,7 +202,7 @@ def hrnet(input, num_classes): return logit if __name__ == '__main__': - image_shape = [3, 769, 769] - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') + image_shape = [-1, 3, 769, 769] + image = fluid.data(name='image', shape=image_shape, dtype='float32') logit = hrnet(image, 4) print("logit:", logit.shape) diff --git a/pdseg/models/modeling/icnet.py b/pdseg/models/modeling/icnet.py index 354468c9efbe3d3429845f7605927556ef3b505a..f6364ff282b3feea2b2bebe796d34434f59b18ca 100644 --- a/pdseg/models/modeling/icnet.py +++ b/pdseg/models/modeling/icnet.py @@ -191,7 +191,7 @@ def icnet(input, num_classes): if __name__ == '__main__': - image_shape = [3, 320, 320] - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') + image_shape = [-1, 3, 320, 320] + image = fluid.data(name='image', shape=image_shape, dtype='float32') logit = icnet(image, 4) print("logit:", logit.shape) diff --git a/pdseg/models/modeling/unet.py b/pdseg/models/modeling/unet.py index 0f613a83b7f468cf1573b4f57f36e8e51fefb7ac..215737aa658bcd4046ecaa77bb04fd11a329be24 100644 --- a/pdseg/models/modeling/unet.py +++ b/pdseg/models/modeling/unet.py @@ -129,7 +129,7 @@ def unet(input, num_classes): if __name__ == '__main__': - image_shape = [3, 320, 320] - image = fluid.layers.data(name='image', shape=image_shape, dtype='float32') + image_shape = [-1, 3, 320, 320] + image = fluid.data(name='image', shape=image_shape, dtype='float32') logit = unet(image, 4) print("logit:", logit.shape) diff --git a/pdseg/train.py b/pdseg/train.py index 8254f1655c97c09204d2e4a64e2404907270fcfc..9e30c0f2050bd4987d84675985a86922e1c993c3 100644 --- a/pdseg/train.py +++ b/pdseg/train.py @@ -103,7 +103,7 @@ def parse_args(): help='If set True, enable continuous evaluation job.' 'This flag is only used for internal test.', action='store_true') - + # NOTE: This for benchmark parser.add_argument( '--is_profiler', @@ -114,7 +114,7 @@ def parse_args(): '--profiler_path', help='the profiler output file path.(used for benchmark)', default='./seg.profiler', - type=str) + type=str) return parser.parse_args() @@ -265,9 +265,9 @@ def train(cfg): batch_size_per_dev = cfg.BATCH_SIZE // dev_count print_info("batch_size_per_dev: {}".format(batch_size_per_dev)) - py_reader, avg_loss, lr, pred, grts, masks = build_model( + data_loader, avg_loss, lr, pred, grts, masks = build_model( train_prog, startup_prog, phase=ModelPhase.TRAIN) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -386,7 +386,7 @@ def train(cfg): print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: if args.debug: @@ -454,16 +454,16 @@ def train(cfg): sys.stdout.flush() avg_loss = 0.0 timer.restart() - + # NOTE : used for benchmark, profiler tools - if args.is_profiler and epoch == 1 and global_step == args.log_steps: + if args.is_profiler and epoch == 1 and global_step == args.log_steps: profiler.start_profiler("All") elif args.is_profiler and epoch == 1 and global_step == args.log_steps + 5: profiler.stop_profiler("total", args.profiler_path) return except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) diff --git a/slim/distillation/README.md b/slim/distillation/README.md index 2bd772a1001e11efa89324315fa32d44032ade05..d7af90beb3a7fd4fa6bb3775d45b0fd6aadc0133 100644 --- a/slim/distillation/README.md +++ b/slim/distillation/README.md @@ -89,7 +89,6 @@ python -m paddle.distributed.launch ./slim/distillation/train_distill.py \ --log_steps 10 --cfg ./slim/distillation/cityscape.yaml \ --teacher_cfg ./slim/distillation/cityscape_teacher.yaml \ --use_gpu \ ---use_mpio \ --do_eval ``` diff --git a/slim/distillation/model_builder.py b/slim/distillation/model_builder.py index f903b8dd2b635fa10070dcc3da488be66746d539..90f53992478e27c94fc8a7817931d3a46e0bb108 100644 --- a/slim/distillation/model_builder.py +++ b/slim/distillation/model_builder.py @@ -156,7 +156,10 @@ def export_preprocess(image): return image, valid_shape, origin_shape -def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwargs): +def build_model(main_prog=None, + start_prog=None, + phase=ModelPhase.TRAIN, + **kwargs): if not ModelPhase.is_valid_phase(phase): raise ValueError("ModelPhase {} is not valid!".format(phase)) @@ -167,8 +170,8 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg width = cfg.EVAL_CROP_SIZE[0] height = cfg.EVAL_CROP_SIZE[1] - image_shape = [cfg.DATASET.DATA_DIM, height, width] - grt_shape = [1, height, width] + image_shape = [-1, cfg.DATASET.DATA_DIM, height, width] + grt_shape = [-1, 1, height, width] class_num = cfg.DATASET.NUM_CLASSES #with fluid.program_guard(main_prog, start_prog): @@ -176,36 +179,30 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg # 在导出模型的时候,增加图像标准化预处理,减小预测部署时图像的处理流程 # 预测部署时只须对输入图像增加batch_size维度即可 if cfg.SLIM.KNOWLEDGE_DISTILL_IS_TEACHER: - image = main_prog.global_block()._clone_variable(kwargs['image'], - force_persistable=False) - label = main_prog.global_block()._clone_variable(kwargs['label'], - force_persistable=False) - mask = main_prog.global_block()._clone_variable(kwargs['mask'], - force_persistable=False) + image = main_prog.global_block()._clone_variable( + kwargs['image'], force_persistable=False) + label = main_prog.global_block()._clone_variable( + kwargs['label'], force_persistable=False) + mask = main_prog.global_block()._clone_variable( + kwargs['mask'], force_persistable=False) else: if ModelPhase.is_predict(phase): - origin_image = fluid.layers.data( + origin_image = fluid.data( name='image', shape=[-1, -1, -1, cfg.DATASET.DATA_DIM], - dtype='float32', - append_batch_size=False) - image, valid_shape, origin_shape = export_preprocess( - origin_image) + dtype='float32') + image, valid_shape, origin_shape = export_preprocess(origin_image) else: - image = fluid.layers.data( - name='image', shape=image_shape, dtype='float32') - label = fluid.layers.data( - name='label', shape=grt_shape, dtype='int32') - mask = fluid.layers.data( - name='mask', shape=grt_shape, dtype='int32') + image = fluid.data(name='image', shape=image_shape, dtype='float32') + label = fluid.data(name='label', shape=grt_shape, dtype='int32') + mask = fluid.data(name='mask', shape=grt_shape, dtype='int32') - - # use PyReader when doing traning and evaluation + # use DataLoader.from_generator when doing traning and evaluation if ModelPhase.is_train(phase) or ModelPhase.is_eval(phase): - py_reader = None + data_loader = None if not cfg.SLIM.KNOWLEDGE_DISTILL_IS_TEACHER: - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[image, label, mask], capacity=cfg.DATALOADER.BUF_SIZE, iterable=False, @@ -219,16 +216,14 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg if class_num > 2 and (("dice_loss" in loss_type) or ("bce_loss" in loss_type)): raise Exception( - "dice loss and bce loss is only applicable to binary classfication" - ) + "dice loss and bce loss is only applicable to binary classfication") # 在两类分割情况下,当loss函数选择dice_loss或bce_loss的时候,最后logit输出通道数设置为1 if ("dice_loss" in loss_type) or ("bce_loss" in loss_type): class_num = 1 if "softmax_loss" in loss_type: raise Exception( - "softmax loss can not combine with dice loss or bce loss" - ) + "softmax loss can not combine with dice loss or bce loss") logits = seg_model(image, class_num) # 根据选择的loss函数计算相应的损失函数 @@ -289,10 +284,7 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg logit, axes=[2, 3], starts=[0, 0], ends=valid_shape) logit = fluid.layers.resize_bilinear( - logit, - out_shape=origin_shape, - align_corners=False, - align_mode=0) + logit, out_shape=origin_shape, align_corners=False, align_mode=0) logit = fluid.layers.argmax(logit, axis=1) return origin_image, logit @@ -312,7 +304,7 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg return pred, logit if ModelPhase.is_eval(phase): - return py_reader, avg_loss, pred, label, mask + return data_loader, avg_loss, pred, label, mask if ModelPhase.is_train(phase): decayed_lr = None @@ -321,7 +313,7 @@ def build_model(main_prog=None, start_prog=None, phase=ModelPhase.TRAIN, **kwarg decayed_lr = optimizer.optimise(avg_loss) # optimizer = solver.Solver(main_prog, start_prog) # decayed_lr = optimizer.optimise(avg_loss) - return py_reader, avg_loss, decayed_lr, pred, label, mask, image + return data_loader, avg_loss, decayed_lr, pred, label, mask, image def to_int(string, dest="I"): diff --git a/slim/distillation/train_distill.py b/slim/distillation/train_distill.py index c1e23253ffcde9eea034bd7f67906ca9e534d2e2..e354107f173eea203d9df3f01f93fae62f41eabc 100644 --- a/slim/distillation/train_distill.py +++ b/slim/distillation/train_distill.py @@ -48,6 +48,7 @@ from utils import dist_utils import solver from paddleslim.dist.single_distiller import merge, l2_loss + def parse_args(): parser = argparse.ArgumentParser(description='PaddleSeg training') parser.add_argument( @@ -260,8 +261,9 @@ def train(cfg): batch_size_per_dev = cfg.BATCH_SIZE // dev_count print_info("batch_size_per_dev: {}".format(batch_size_per_dev)) - py_reader, loss, lr, pred, grts, masks, image = build_model(phase=ModelPhase.TRAIN) - py_reader.decorate_sample_generator( + data_loader, loss, lr, pred, grts, masks, image = build_model( + phase=ModelPhase.TRAIN) + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -274,8 +276,12 @@ def train(cfg): with fluid.program_guard(teacher_program, teacher_startup_program): with fluid.unique_name.guard(): _, teacher_loss, _, _, _, _, _ = build_model( - teacher_program, teacher_startup_program, phase=ModelPhase.TRAIN, image=image, - label=grts, mask=masks) + teacher_program, + teacher_startup_program, + phase=ModelPhase.TRAIN, + image=image, + label=grts, + mask=masks) exe.run(teacher_startup_program) @@ -293,7 +299,9 @@ def train(cfg): 'mask': 'mask', } merge(teacher_program, fluid.default_main_program(), data_name_map, place) - distill_pairs = [['teacher_bilinear_interp_2.tmp_0', 'bilinear_interp_0.tmp_0']] + distill_pairs = [[ + 'teacher_bilinear_interp_2.tmp_0', 'bilinear_interp_0.tmp_0' + ]] def distill(pairs, weight): """ @@ -322,7 +330,8 @@ def train(cfg): build_strategy.fuse_all_optimizer_ops = False build_strategy.fuse_elewise_add_act_ops = True if cfg.NUM_TRAINERS > 1 and args.use_gpu: - dist_utils.prepare_for_multi_process(exe, build_strategy, fluid.default_main_program()) + dist_utils.prepare_for_multi_process(exe, build_strategy, + fluid.default_main_program()) exec_strategy.num_threads = 1 if cfg.TRAIN.SYNC_BATCH_NORM and args.use_gpu: @@ -334,10 +343,11 @@ def train(cfg): print_info( "Sync BatchNorm strategy will not be effective if GPU device" " count <= 1") - compiled_train_prog = fluid.CompiledProgram(fluid.default_main_program()).with_data_parallel( - loss_name=all_loss.name, - exec_strategy=exec_strategy, - build_strategy=build_strategy) + compiled_train_prog = fluid.CompiledProgram( + fluid.default_main_program()).with_data_parallel( + loss_name=all_loss.name, + exec_strategy=exec_strategy, + build_strategy=build_strategy) # Resume training begin_epoch = cfg.SOLVER.BEGIN_EPOCH @@ -387,7 +397,9 @@ def train(cfg): format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) #fetch_list = [avg_loss.name, lr.name] - fetch_list = [loss.name, 'teacher_' + teacher_loss.name, distill_loss.name, lr.name] + fetch_list = [ + loss.name, 'teacher_' + teacher_loss.name, distill_loss.name, lr.name + ] if args.debug: # Fetch more variable info and use streaming confusion matrix to @@ -431,7 +443,7 @@ def train(cfg): print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: if args.debug: @@ -491,7 +503,8 @@ def train(cfg): speed = args.log_steps / timer.elapsed_time() print(( "epoch={} step={} lr={:.5f} loss={:.4f} teacher loss={:.4f} distill loss={:.4f} step/sec={:.3f} | ETA {}" - ).format(epoch, global_step, lr[0], avg_loss, avg_t_loss, avg_d_loss, speed, + ).format(epoch, global_step, lr[0], avg_loss, + avg_t_loss, avg_d_loss, speed, calculate_eta(all_step - global_step, speed))) if args.use_tb: log_writer.add_scalar('Train/loss', avg_loss, @@ -507,7 +520,7 @@ def train(cfg): timer.restart() except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) diff --git a/slim/nas/README.md b/slim/nas/README.md index cddfc5a82f07ab0b3f2e2acad6a4c0f7b2ed650c..31e8f93f608002504cdaeaed940e4b41c138e00c 100644 --- a/slim/nas/README.md +++ b/slim/nas/README.md @@ -46,7 +46,7 @@ SLIM: ## 训练与评估 执行以下命令,边训练边评估 ```shell -CUDA_VISIBLE_DEVICES=0 python -u ./slim/nas/train_nas.py --log_steps 10 --cfg configs/deeplabv3p_mobilenetv2_cityscapes.yaml --use_gpu --use_mpio \ +CUDA_VISIBLE_DEVICES=0 python -u ./slim/nas/train_nas.py --log_steps 10 --cfg configs/deeplabv3p_mobilenetv2_cityscapes.yaml --use_gpu \ SLIM.NAS_PORT 23333 \ SLIM.NAS_ADDRESS "" \ SLIM.NAS_SEARCH_STEPS 2 \ diff --git a/slim/nas/eval_nas.py b/slim/nas/eval_nas.py index 08f75f5d8ee8d6afbcf9b038e4f8dcf0237a5b56..7f8663dffafb49d7c372f3eeaf0d3ed074f7ce9b 100644 --- a/slim/nas/eval_nas.py +++ b/slim/nas/eval_nas.py @@ -45,6 +45,7 @@ from metrics import ConfusionMatrix from mobilenetv2_search_space import MobileNetV2SpaceSeg + def parse_args(): parser = argparse.ArgumentParser(description='PaddleSeg model evalution') parser.add_argument( @@ -98,10 +99,10 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): for b in data_gen: yield b[0], b[1], b[2] - py_reader, avg_loss, pred, grts, masks = build_model( + data_loader, avg_loss, pred, grts, masks = build_model( test_prog, startup_prog, phase=ModelPhase.EVAL, arch=kwargs['arch']) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, drop_last=False, batch_size=cfg.BATCH_SIZE) # Get device environment @@ -134,7 +135,7 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): all_step = cfg.DATASET.TEST_TOTAL_IMAGES // cfg.BATCH_SIZE + 1 timer = Timer() timer.start() - py_reader.start() + data_loader.start() while True: try: step += 1 diff --git a/slim/nas/model_builder.py b/slim/nas/model_builder.py index 3dfbacb0cd41a14bb81c6f6c82b81479fb1c30c8..27a14fa77970cad18e017dc825f1708ceb2c9c75 100644 --- a/slim/nas/model_builder.py +++ b/slim/nas/model_builder.py @@ -74,9 +74,7 @@ def seg_model(image, class_num, arch): if model_name == 'deeplabv3p': logits = deeplab.deeplabv3p_nas(image, class_num, arch) else: - raise Exception( - "unknow model name, only support deeplabv3p" - ) + raise Exception("unknow model name, only support deeplabv3p") return logits @@ -156,8 +154,8 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN, arch=None): width = cfg.EVAL_CROP_SIZE[0] height = cfg.EVAL_CROP_SIZE[1] - image_shape = [cfg.DATASET.DATA_DIM, height, width] - grt_shape = [1, height, width] + image_shape = [-1, cfg.DATASET.DATA_DIM, height, width] + grt_shape = [-1, 1, height, width] class_num = cfg.DATASET.NUM_CLASSES with fluid.program_guard(main_prog, start_prog): @@ -165,25 +163,22 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN, arch=None): # 在导出模型的时候,增加图像标准化预处理,减小预测部署时图像的处理流程 # 预测部署时只须对输入图像增加batch_size维度即可 if ModelPhase.is_predict(phase): - origin_image = fluid.layers.data( + origin_image = fluid.data( name='image', shape=[-1, -1, -1, cfg.DATASET.DATA_DIM], - dtype='float32', - append_batch_size=False) + dtype='float32') image, valid_shape, origin_shape = export_preprocess( origin_image) else: - image = fluid.layers.data( + image = fluid.data( name='image', shape=image_shape, dtype='float32') - label = fluid.layers.data( - name='label', shape=grt_shape, dtype='int32') - mask = fluid.layers.data( - name='mask', shape=grt_shape, dtype='int32') + label = fluid.data(name='label', shape=grt_shape, dtype='int32') + mask = fluid.data(name='mask', shape=grt_shape, dtype='int32') - # use PyReader when doing traning and evaluation + # use DataLoader.from_generator when doing traning and evaluation if ModelPhase.is_train(phase) or ModelPhase.is_eval(phase): - py_reader = fluid.io.PyReader( + data_loader = fluid.io.DataLoader.from_generator( feed_list=[image, label, mask], capacity=cfg.DATALOADER.BUF_SIZE, iterable=False, @@ -217,7 +212,8 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN, arch=None): if "softmax_loss" in loss_type: weight = cfg.SOLVER.CROSS_ENTROPY_WEIGHT avg_loss_list.append( - multi_softmax_with_loss(logits, label, mask, class_num, weight)) + multi_softmax_with_loss(logits, label, mask, class_num, + weight)) loss_valid = True valid_loss.append("softmax_loss") if "dice_loss" in loss_type: @@ -290,12 +286,12 @@ def build_model(main_prog, start_prog, phase=ModelPhase.TRAIN, arch=None): return pred, logit if ModelPhase.is_eval(phase): - return py_reader, avg_loss, pred, label, mask + return data_loader, avg_loss, pred, label, mask if ModelPhase.is_train(phase): optimizer = solver.Solver(main_prog, start_prog) decayed_lr = optimizer.optimise(avg_loss) - return py_reader, avg_loss, decayed_lr, pred, label, mask + return data_loader, avg_loss, decayed_lr, pred, label, mask def to_int(string, dest="I"): diff --git a/slim/nas/train_nas.py b/slim/nas/train_nas.py index 7822657fa264d053360199d5691098ae85fcd12c..6ab4d899dc2406275daf3fecd3738fb4b3b82c49 100644 --- a/slim/nas/train_nas.py +++ b/slim/nas/train_nas.py @@ -54,6 +54,7 @@ from paddleslim.analysis import flops from paddleslim.nas.sa_nas import SANAS from paddleslim.nas import search_space + def parse_args(): parser = argparse.ArgumentParser(description='PaddleSeg training') parser.add_argument( @@ -269,21 +270,24 @@ def train(cfg): port = cfg.SLIM.NAS_PORT server_address = (cfg.SLIM.NAS_ADDRESS, port) - sa_nas = SANAS(config, server_addr=server_address, search_steps=cfg.SLIM.NAS_SEARCH_STEPS, - is_server=cfg.SLIM.NAS_IS_SERVER) + sa_nas = SANAS( + config, + server_addr=server_address, + search_steps=cfg.SLIM.NAS_SEARCH_STEPS, + is_server=cfg.SLIM.NAS_IS_SERVER) for step in range(cfg.SLIM.NAS_SEARCH_STEPS): arch = sa_nas.next_archs()[0] start_prog = fluid.Program() train_prog = fluid.Program() - py_reader, avg_loss, lr, pred, grts, masks = build_model( + data_loader, avg_loss, lr, pred, grts, masks = build_model( train_prog, start_prog, arch=arch, phase=ModelPhase.TRAIN) cur_flops = flops(train_prog) print('current step:', step, 'flops:', cur_flops) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -297,7 +301,8 @@ def train(cfg): build_strategy = fluid.BuildStrategy() if cfg.NUM_TRAINERS > 1 and args.use_gpu: - dist_utils.prepare_for_multi_process(exe, build_strategy, train_prog) + dist_utils.prepare_for_multi_process(exe, build_strategy, + train_prog) exec_strategy.num_threads = 1 if cfg.TRAIN.SYNC_BATCH_NORM and args.use_gpu: @@ -309,10 +314,11 @@ def train(cfg): print_info( "Sync BatchNorm strategy will not be effective if GPU device" " count <= 1") - compiled_train_prog = fluid.CompiledProgram(train_prog).with_data_parallel( - loss_name=avg_loss.name, - exec_strategy=exec_strategy, - build_strategy=build_strategy) + compiled_train_prog = fluid.CompiledProgram( + train_prog).with_data_parallel( + loss_name=avg_loss.name, + exec_strategy=exec_strategy, + build_strategy=build_strategy) # Resume training begin_epoch = cfg.SOLVER.BEGIN_EPOCH @@ -353,13 +359,14 @@ def train(cfg): print_info( "Parameter[{}] don't exist or shape does not match current network, skip" " to load it.".format(var.name)) - print_info("{}/{} pretrained parameters loaded successfully!".format( - len(load_vars), - len(load_vars) + len(load_fail_vars))) + print_info( + "{}/{} pretrained parameters loaded successfully!".format( + len(load_vars), + len(load_vars) + len(load_fail_vars))) else: print_info( 'Pretrained model dir {} not exists, training from scratch...'. - format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) + format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) fetch_list = [avg_loss.name, lr.name] @@ -374,8 +381,8 @@ def train(cfg): timer.start() if begin_epoch > cfg.SOLVER.NUM_EPOCHS: raise ValueError( - ("begin epoch[{}] is larger than cfg.SOLVER.NUM_EPOCHS[{}]").format( - begin_epoch, cfg.SOLVER.NUM_EPOCHS)) + ("begin epoch[{}] is larger than cfg.SOLVER.NUM_EPOCHS[{}]" + ).format(begin_epoch, cfg.SOLVER.NUM_EPOCHS)) if args.use_mpio: print_info("Use multiprocess reader") @@ -384,7 +391,7 @@ def train(cfg): best_miou = 0.0 for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: loss, lr = exe.run( @@ -398,21 +405,22 @@ def train(cfg): avg_loss /= args.log_steps speed = args.log_steps / timer.elapsed_time() print(( - "epoch={} step={} lr={:.5f} loss={:.4f} step/sec={:.3f} | ETA {}" - ).format(epoch, global_step, lr[0], avg_loss, speed, - calculate_eta(all_step - global_step, speed))) + "epoch={} step={} lr={:.5f} loss={:.4f} step/sec={:.3f} | ETA {}" + ).format(epoch, global_step, lr[0], avg_loss, speed, + calculate_eta(all_step - global_step, speed))) sys.stdout.flush() avg_loss = 0.0 timer.restart() except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) if epoch > cfg.SLIM.NAS_START_EVAL_EPOCH: - ckpt_dir = save_checkpoint(exe, train_prog, '{}_tmp'.format(port)) + ckpt_dir = save_checkpoint(exe, train_prog, + '{}_tmp'.format(port)) _, mean_iou, _, mean_acc = evaluate( cfg=cfg, arch=arch, @@ -420,7 +428,8 @@ def train(cfg): use_gpu=args.use_gpu, use_mpio=args.use_mpio) if best_miou < mean_iou: - print('search step {}, epoch {} best iou {}'.format(step, epoch, mean_iou)) + print('search step {}, epoch {} best iou {}'.format( + step, epoch, mean_iou)) best_miou = mean_iou sa_nas.reward(float(best_miou)) diff --git a/slim/prune/README.md b/slim/prune/README.md index b6a45238938567a845b44ff768db6982bfeab55c..25505606e3fcc8c8e7c6beba68cdb8d39c1c56b1 100644 --- a/slim/prune/README.md +++ b/slim/prune/README.md @@ -46,7 +46,7 @@ SLIM.PRUNE_RATIOS '[0.1,0.1,0.1]' ```shell CUDA_VISIBLE_DEVICES=0 -python -u ./slim/prune/eval_prune.py --cfg configs/cityscape_fast_scnn.yaml --use_gpu --use_mpio \ +python -u ./slim/prune/eval_prune.py --cfg configs/cityscape_fast_scnn.yaml --use_gpu \ TEST.TEST_MODEL your_trained_model \ ``` diff --git a/slim/prune/eval_prune.py b/slim/prune/eval_prune.py index b8275d03475b8fea67d73682b54a38172fbc25e2..3bfb4f4cf2772da0e6122ec6f6660d90a23c71e2 100644 --- a/slim/prune/eval_prune.py +++ b/slim/prune/eval_prune.py @@ -45,6 +45,7 @@ from metrics import ConfusionMatrix from paddleslim.prune import load_model + def parse_args(): parser = argparse.ArgumentParser(description='PaddleSeg model evalution') parser.add_argument( @@ -98,10 +99,10 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): for b in data_gen: yield b[0], b[1], b[2] - py_reader, avg_loss, pred, grts, masks = build_model( + data_loader, avg_loss, pred, grts, masks = build_model( test_prog, startup_prog, phase=ModelPhase.EVAL) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, drop_last=False, batch_size=cfg.BATCH_SIZE) # Get device environment @@ -134,7 +135,7 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): all_step = cfg.DATASET.TEST_TOTAL_IMAGES // cfg.BATCH_SIZE + 1 timer = Timer() timer.start() - py_reader.start() + data_loader.start() while True: try: step += 1 diff --git a/slim/prune/train_prune.py b/slim/prune/train_prune.py index 06e1658f1a3f721842fbe780820103aceac87a16..05c599e3327728ee1ef5e3f2dea359ab9dab5834 100644 --- a/slim/prune/train_prune.py +++ b/slim/prune/train_prune.py @@ -50,6 +50,7 @@ from utils import dist_utils from paddleslim.prune import Pruner, save_model from paddleslim.analysis import flops + def parse_args(): parser = argparse.ArgumentParser(description='PaddleSeg training') parser.add_argument( @@ -181,10 +182,12 @@ def load_checkpoint(exe, program): return begin_epoch + def print_info(*msg): if cfg.TRAINER_ID == 0: print(*msg) + def train(cfg): startup_prog = fluid.Program() train_prog = fluid.Program() @@ -236,9 +239,9 @@ def train(cfg): batch_size_per_dev = cfg.BATCH_SIZE // dev_count print_info("batch_size_per_dev: {}".format(batch_size_per_dev)) - py_reader, avg_loss, lr, pred, grts, masks = build_model( + data_loader, avg_loss, lr, pred, grts, masks = build_model( train_prog, startup_prog, phase=ModelPhase.TRAIN) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -261,8 +264,9 @@ def train(cfg): print_info("Sync BatchNorm strategy is effective.") build_strategy.sync_batch_norm = True else: - print_info("Sync BatchNorm strategy will not be effective if GPU device" - " count <= 1") + print_info( + "Sync BatchNorm strategy will not be effective if GPU device" + " count <= 1") pruned_params = cfg.SLIM.PRUNE_PARAMS.strip().split(',') pruned_ratios = cfg.SLIM.PRUNE_RATIOS @@ -311,14 +315,16 @@ def train(cfg): for var in load_vars: print_info("Parameter[{}] loaded sucessfully!".format(var.name)) for var in load_fail_vars: - print_info("Parameter[{}] don't exist or shape does not match current network, skip" - " to load it.".format(var.name)) + print_info( + "Parameter[{}] don't exist or shape does not match current network, skip" + " to load it.".format(var.name)) print_info("{}/{} pretrained parameters loaded successfully!".format( len(load_vars), len(load_vars) + len(load_fail_vars))) else: - print_info('Pretrained model dir {} not exists, training from scratch...'. - format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) + print_info( + 'Pretrained model dir {} not exists, training from scratch...'. + format(cfg.TRAIN.PRETRAINED_MODEL_DIR)) fetch_list = [avg_loss.name, lr.name] if args.debug: @@ -371,7 +377,7 @@ def train(cfg): print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: if args.debug: @@ -441,7 +447,7 @@ def train(cfg): timer.restart() except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) @@ -477,6 +483,7 @@ def train(cfg): if cfg.TRAINER_ID == 0: save_prune_checkpoint(exe, train_prog, 'final') + def main(args): if args.cfg_file is not None: cfg.update_from_file(args.cfg_file) diff --git a/slim/quantization/eval_quant.py b/slim/quantization/eval_quant.py index f40021df10ac5cabee789ca4de04b7489b37f182..fdf6f3ce18444f85c157a301334aabfdf47869e7 100644 --- a/slim/quantization/eval_quant.py +++ b/slim/quantization/eval_quant.py @@ -105,10 +105,10 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): for b in data_gen: yield b[0], b[1], b[2] - py_reader, avg_loss, pred, grts, masks = build_model( + data_loader, avg_loss, pred, grts, masks = build_model( test_prog, startup_prog, phase=ModelPhase.EVAL) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, drop_last=False, batch_size=cfg.BATCH_SIZE) # Get device environment @@ -152,7 +152,7 @@ def evaluate(cfg, ckpt_dir=None, use_gpu=False, use_mpio=False, **kwargs): all_step = cfg.DATASET.TEST_TOTAL_IMAGES // cfg.BATCH_SIZE + 1 timer = Timer() timer.start() - py_reader.start() + data_loader.start() while True: try: step += 1 diff --git a/slim/quantization/train_quant.py b/slim/quantization/train_quant.py index 6a29dccdbaeda54b06c11299fb37e979cec6e401..1034b7234d73f21c41085d5a04d74069b04de7ca 100644 --- a/slim/quantization/train_quant.py +++ b/slim/quantization/train_quant.py @@ -157,9 +157,9 @@ def train_quant(cfg): batch_size_per_dev = cfg.BATCH_SIZE // dev_count print_info("batch_size_per_dev: {}".format(batch_size_per_dev)) - py_reader, avg_loss, lr, pred, grts, masks = build_model( + data_loader, avg_loss, lr, pred, grts, masks = build_model( train_prog, startup_prog, phase=ModelPhase.TRAIN) - py_reader.decorate_sample_generator( + data_loader.set_sample_generator( data_generator, batch_size=batch_size_per_dev, drop_last=drop_last) exe = fluid.Executor(place) @@ -274,7 +274,7 @@ def train_quant(cfg): print_info("Use multi-thread reader") for epoch in range(begin_epoch, cfg.SOLVER.NUM_EPOCHS + 1): - py_reader.start() + data_loader.start() while True: try: if args.debug: @@ -326,7 +326,7 @@ def train_quant(cfg): timer.restart() except fluid.core.EOFException: - py_reader.reset() + data_loader.reset() break except Exception as e: print(e) diff --git a/turtorial/finetune_fast_scnn.md b/turtorial/finetune_fast_scnn.md index 188a51edf9d138bb6832849c9ab2ad8afbcd3cd4..31541b796849277085104abf1df13284e264fae8 100644 --- a/turtorial/finetune_fast_scnn.md +++ b/turtorial/finetune_fast_scnn.md @@ -114,6 +114,6 @@ python pdseg/eval.py --use_gpu --cfg ./configs/fast_scnn_pet.yaml | ICNet/bn |(1024, 2048) |8.76ms| 0.6831 | | Fast-SCNN/bn | (1024, 2048) |6.28ms| 0.6964 | -上述测试环境为v100. 测试使用paddle的推理接口[zero_copy](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/advanced_usage/deploy/inference/python_infer_cn.html#id8)的方式,模型输出是类别,即argmax后的值。 +上述测试环境为v100. 测试使用paddle的推理接口[zero_copy](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/advanced_guide/inference_deployment/inference/python_infer_cn.html#id8)的方式,模型输出是类别,即argmax后的值。