From: @caojian05 Reviewed-by: @wuxuejian,@oacjiewen Signed-off-by: @wuxuejiantags/v1.2.0-rc1
| @@ -50,6 +50,8 @@ JPEGImages/00004.jpg SegmentationClassGray/00004.png | |||||
| ...... | ...... | ||||
| ``` | ``` | ||||
| You can also generate the list file automatically by run script: `python get_dataset_lst.py --data_root=/PATH/TO/DATA` | |||||
| - Configure and run build_data.sh to convert dataset to mindrecords. Arguments in scripts/build_data.sh: | - Configure and run build_data.sh to convert dataset to mindrecords. Arguments in scripts/build_data.sh: | ||||
| ```shell | ```shell | ||||
| @@ -164,10 +166,12 @@ run_eval_s8_multiscale_flip.sh | |||||
| ├── run_eval_s8_multiscale.sh # launch ascend evaluation with multiscale in s8 structure | ├── run_eval_s8_multiscale.sh # launch ascend evaluation with multiscale in s8 structure | ||||
| ├── run_eval_s8_multiscale_filp.sh # launch ascend evaluation with multiscale and filp in s8 structure | ├── run_eval_s8_multiscale_filp.sh # launch ascend evaluation with multiscale and filp in s8 structure | ||||
| ├── run_standalone_train.sh # launch ascend standalone training(1 pc) | ├── run_standalone_train.sh # launch ascend standalone training(1 pc) | ||||
| ├── run_standalone_train_cpu.sh # launch CPU standalone training | |||||
| ├── src | ├── src | ||||
| ├── data | ├── data | ||||
| ├── dataset.py # mindrecord data generator | ├── dataset.py # mindrecord data generator | ||||
| ├── build_seg_data.py # data preprocessing | ├── build_seg_data.py # data preprocessing | ||||
| ├── get_dataset_lst.py # dataset list file generator | |||||
| ├── loss | ├── loss | ||||
| ├── loss.py # loss definition for deeplabv3 | ├── loss.py # loss definition for deeplabv3 | ||||
| ├── nets | ├── nets | ||||
| @@ -189,6 +193,7 @@ Default configuration | |||||
| ```shell | ```shell | ||||
| "data_file":"/PATH/TO/MINDRECORD_NAME" # dataset path | "data_file":"/PATH/TO/MINDRECORD_NAME" # dataset path | ||||
| "device_target":Ascend # device target | |||||
| "train_epochs":300 # total epochs | "train_epochs":300 # total epochs | ||||
| "batch_size":32 # batch size of input tensor | "batch_size":32 # batch size of input tensor | ||||
| "crop_size":513 # crop size | "crop_size":513 # crop size | ||||
| @@ -238,7 +243,7 @@ For 8 devices training, training steps are as follows: | |||||
| 1. Train s16 with vocaug dataset, finetuning from resnet101 pretrained model, script is as follows: | 1. Train s16 with vocaug dataset, finetuning from resnet101 pretrained model, script is as follows: | ||||
| ```python | |||||
| ```shell | |||||
| # run_distribute_train_s16_r1.sh | # run_distribute_train_s16_r1.sh | ||||
| for((i=0;i<=$RANK_SIZE-1;i++)); | for((i=0;i<=$RANK_SIZE-1;i++)); | ||||
| do | do | ||||
| @@ -328,8 +333,34 @@ do | |||||
| done | done | ||||
| ``` | ``` | ||||
| #### Running on CPU | |||||
| For CPU training, please config parameters, training script is as follows: | |||||
| ```shell | |||||
| # run_standalone_train_cpu.sh | |||||
| python ${train_code_path}/train.py --data_file=/PATH/TO/MINDRECORD_NAME \ | |||||
| --device_target=CPU \ | |||||
| --train_dir=${train_path}/ckpt \ | |||||
| --train_epochs=200 \ | |||||
| --batch_size=32 \ | |||||
| --crop_size=513 \ | |||||
| --base_lr=0.015 \ | |||||
| --lr_type=cos \ | |||||
| --min_scale=0.5 \ | |||||
| --max_scale=2.0 \ | |||||
| --ignore_label=255 \ | |||||
| --num_classes=21 \ | |||||
| --model=deeplab_v3_s16 \ | |||||
| --ckpt_pre_trained=/PATH/TO/PRETRAIN_MODEL \ | |||||
| --save_steps=1500 \ | |||||
| --keep_checkpoint_max=200 >log 2>&1 & | |||||
| ``` | |||||
| ### Result | ### Result | ||||
| #### Running on Ascend | |||||
| - Training vocaug in s16 structure | - Training vocaug in s16 structure | ||||
| ```shell | ```shell | ||||
| @@ -386,6 +417,17 @@ epoch time: 5962.164 ms, per step time: 542.015 ms | |||||
| ... | ... | ||||
| ``` | ``` | ||||
| #### Running on CPU | |||||
| - Training voctrain in s16 structure | |||||
| ```bash | |||||
| epoch: 1 step: 1, loss is 3.655448 | |||||
| epoch: 2 step: 1, loss is 1.5531876 | |||||
| epoch: 3 step: 1, loss is 1.5099041 | |||||
| ... | |||||
| ``` | |||||
| ## [Evaluation Process](#contents) | ## [Evaluation Process](#contents) | ||||
| ### Usage | ### Usage | ||||
| @@ -438,7 +480,7 @@ Note: There OS is output stride, and MS is multiscale. | |||||
| # [Model Description](#contents) | # [Model Description](#contents) | ||||
| ## [Performance](#contents | |||||
| ## [Performance](#contents) | |||||
| ### Evaluation Performance | ### Evaluation Performance | ||||
| @@ -63,6 +63,8 @@ Pascal VOC数据集和语义边界数据集(Semantic Boundaries Dataset,SBD | |||||
| ...... | ...... | ||||
| ``` | ``` | ||||
| 你也可以通过运行脚本:`python get_dataset_lst.py --data_root=/PATH/TO/DATA` 来自动生成数据清单文件。 | |||||
| - 配置并运行build_data.sh,将数据集转换为MindRecords。scripts/build_data.sh中的参数: | - 配置并运行build_data.sh,将数据集转换为MindRecords。scripts/build_data.sh中的参数: | ||||
| ``` | ``` | ||||
| @@ -177,10 +179,12 @@ run_eval_s8_multiscale_flip.sh | |||||
| ├── run_eval_s8_multiscale.sh # 使用多尺度s8结构启动Ascend评估 | ├── run_eval_s8_multiscale.sh # 使用多尺度s8结构启动Ascend评估 | ||||
| ├── run_eval_s8_multiscale_filp.sh # 使用多尺度和翻转s8结构启动Ascend评估 | ├── run_eval_s8_multiscale_filp.sh # 使用多尺度和翻转s8结构启动Ascend评估 | ||||
| ├── run_standalone_train.sh # 启动Ascend单机训练(单卡) | ├── run_standalone_train.sh # 启动Ascend单机训练(单卡) | ||||
| ├── run_standalone_train_cpu.sh # 启动CPU单机训练 | |||||
| ├── src | ├── src | ||||
| ├── data | ├── data | ||||
| ├── dataset.py # 生成MindRecord数据 | ├── dataset.py # 生成MindRecord数据 | ||||
| ├── build_seg_data.py # 数据预处理 | ├── build_seg_data.py # 数据预处理 | ||||
| ├── get_dataset_lst.py # 生成数据清单文件 | |||||
| ├── loss | ├── loss | ||||
| ├── loss.py # DeepLabV3的损失定义 | ├── loss.py # DeepLabV3的损失定义 | ||||
| ├── nets | ├── nets | ||||
| @@ -202,6 +206,7 @@ run_eval_s8_multiscale_flip.sh | |||||
| ```bash | ```bash | ||||
| "data_file":"/PATH/TO/MINDRECORD_NAME" # 数据集路径 | "data_file":"/PATH/TO/MINDRECORD_NAME" # 数据集路径 | ||||
| "device_target":Ascend # 训练后端类型 | |||||
| "train_epochs":300 # 总轮次数 | "train_epochs":300 # 总轮次数 | ||||
| "batch_size":32 # 输入张量的批次大小 | "batch_size":32 # 输入张量的批次大小 | ||||
| "crop_size":513 # 裁剪大小 | "crop_size":513 # 裁剪大小 | ||||
| @@ -342,8 +347,34 @@ do | |||||
| done | done | ||||
| ``` | ``` | ||||
| #### CPU环境运行 | |||||
| 按以下样例配置训练参数,运行CPU训练脚本: | |||||
| ```shell | |||||
| # run_standalone_train_cpu.sh | |||||
| python ${train_code_path}/train.py --data_file=/PATH/TO/MINDRECORD_NAME \ | |||||
| --device_target=CPU \ | |||||
| --train_dir=${train_path}/ckpt \ | |||||
| --train_epochs=200 \ | |||||
| --batch_size=32 \ | |||||
| --crop_size=513 \ | |||||
| --base_lr=0.015 \ | |||||
| --lr_type=cos \ | |||||
| --min_scale=0.5 \ | |||||
| --max_scale=2.0 \ | |||||
| --ignore_label=255 \ | |||||
| --num_classes=21 \ | |||||
| --model=deeplab_v3_s16 \ | |||||
| --ckpt_pre_trained=/PATH/TO/PRETRAIN_MODEL \ | |||||
| --save_steps=1500 \ | |||||
| --keep_checkpoint_max=200 >log 2>&1 & | |||||
| ``` | |||||
| ### 结果 | ### 结果 | ||||
| #### Ascend处理器环境运行 | |||||
| - 使用s16结构训练VOCaug | - 使用s16结构训练VOCaug | ||||
| ```bash | ```bash | ||||
| @@ -400,6 +431,17 @@ Epoch time: 5962.164, per step time: 542.015 | |||||
| ... | ... | ||||
| ``` | ``` | ||||
| #### CPU环境运行 | |||||
| - 使用s16结构训练VOCtrain | |||||
| ```bash | |||||
| epoch: 1 step: 1, loss is 3.655448 | |||||
| epoch: 2 step: 1, loss is 1.5531876 | |||||
| epoch: 3 step: 1, loss is 1.5099041 | |||||
| ... | |||||
| ``` | |||||
| ## 评估过程 | ## 评估过程 | ||||
| ### 用法 | ### 用法 | ||||
| @@ -470,7 +512,7 @@ python ${train_code_path}/eval.py --data_root=/PATH/TO/DATA \ | |||||
| | 损失 | 0.0065883575 | | | 损失 | 0.0065883575 | | ||||
| | 速度 | 31毫秒/步(单卡,s8)<br> 234毫秒/步(8卡,s8) | | | 速度 | 31毫秒/步(单卡,s8)<br> 234毫秒/步(8卡,s8) | | ||||
| | 微调检查点 | 443M (.ckpt文件) | | | 微调检查点 | 443M (.ckpt文件) | | ||||
| | 脚本 | [链接](https://gitee.com/mindspore/mindspore/tree/master/model_zoo/office/cv/deeplabv3) | | |||||
| | 脚本 | [链接](https://gitee.com/mindspore/mindspore/tree/master/model_zoo/official/cv/deeplabv3) | | |||||
| # 随机情况说明 | # 随机情况说明 | ||||
| @@ -0,0 +1,142 @@ | |||||
| import argparse | |||||
| import os | |||||
| import numpy as np | |||||
| import scipy.io | |||||
| from PIL import Image | |||||
| parser = argparse.ArgumentParser('dataset list generator') | |||||
| parser.add_argument("--data_dir", type=str, default='./', help='where dataset stored.') | |||||
| args, _ = parser.parse_known_args() | |||||
| data_dir = args.data_dir | |||||
| print("Data dir is:", data_dir) | |||||
| # | |||||
| VOC_IMG_DIR = os.path.join(data_dir, 'VOCdevkit/VOC2012/JPEGImages') | |||||
| VOC_ANNO_DIR = os.path.join(data_dir, 'VOCdevkit/VOC2012/SegmentationClass') | |||||
| VOC_ANNO_GRAY_DIR = os.path.join(data_dir, 'VOCdevkit/VOC2012/SegmentationClassGray') | |||||
| VOC_TRAIN_TXT = os.path.join(data_dir, 'VOCdevkit/VOC2012/ImageSets/Segmentation/train.txt') | |||||
| VOC_VAL_TXT = os.path.join(data_dir, 'VOCdevkit/VOC2012/ImageSets/Segmentation/val.txt') | |||||
| SBD_ANNO_DIR = os.path.join(data_dir, 'benchmark_RELEASE/dataset/cls') | |||||
| SBD_IMG_DIR = os.path.join(data_dir, 'benchmark_RELEASE/dataset/img') | |||||
| SBD_ANNO_PNG_DIR = os.path.join(data_dir, 'benchmark_RELEASE/dataset/cls_png') | |||||
| SBD_ANNO_GRAY_DIR = os.path.join(data_dir, 'benchmark_RELEASE/dataset/cls_png_gray') | |||||
| SBD_TRAIN_TXT = os.path.join(data_dir, 'benchmark_RELEASE/dataset/train.txt') | |||||
| SBD_VAL_TXT = os.path.join(data_dir, 'benchmark_RELEASE/dataset/val.txt') | |||||
| VOC_TRAIN_LST_TXT = os.path.join(data_dir, 'voc_train_lst.txt') | |||||
| VOC_VAL_LST_TXT = os.path.join(data_dir, 'voc_val_lst.txt') | |||||
| VOC_AUG_TRAIN_LST_TXT = os.path.join(data_dir, 'vocaug_train_lst.txt') | |||||
| def __get_data_list(data_list_file): | |||||
| with open(data_list_file, mode='r') as f: | |||||
| return f.readlines() | |||||
| def conv_voc_colorpng_to_graypng(): | |||||
| if not os.path.exists(VOC_ANNO_GRAY_DIR): | |||||
| os.makedirs(VOC_ANNO_GRAY_DIR) | |||||
| for ann in os.listdir(VOC_ANNO_DIR): | |||||
| ann_im = Image.open(os.path.join(VOC_ANNO_DIR, ann)) | |||||
| ann_im = Image.fromarray(np.array(ann_im)) | |||||
| ann_im.save(os.path.join(VOC_ANNO_GRAY_DIR, ann)) | |||||
| def __gen_palette(cls_nums=256): | |||||
| palette = np.zeros((cls_nums, 3), dtype=np.uint8) | |||||
| for i in range(cls_nums): | |||||
| lbl = i | |||||
| j = 0 | |||||
| while lbl: | |||||
| palette[i, 0] |= (((lbl >> 0) & 1) << (7 - j)) | |||||
| palette[i, 1] |= (((lbl >> 1) & 1) << (7 - j)) | |||||
| palette[i, 2] |= (((lbl >> 2) & 1) << (7 - j)) | |||||
| lbl >>= 3 | |||||
| j += 1 | |||||
| return palette.flatten() | |||||
| def conv_sbd_mat_to_png(): | |||||
| if not os.path.exists(SBD_ANNO_PNG_DIR): | |||||
| os.makedirs(SBD_ANNO_PNG_DIR) | |||||
| if not os.path.exists(SBD_ANNO_GRAY_DIR): | |||||
| os.makedirs(SBD_ANNO_GRAY_DIR) | |||||
| palette = __gen_palette() | |||||
| for an in os.listdir(SBD_ANNO_DIR): | |||||
| img_id = an[:-4] | |||||
| mat = scipy.io.loadmat(os.path.join(SBD_ANNO_DIR, an)) | |||||
| anno = mat['GTcls'][0]['Segmentation'][0].astype(np.uint8) | |||||
| anno_png = Image.fromarray(anno) | |||||
| # save to gray png | |||||
| anno_png.save(os.path.join(SBD_ANNO_GRAY_DIR, img_id + '.png')) | |||||
| # save to color png use palette | |||||
| anno_png.putpalette(palette) | |||||
| anno_png.save(os.path.join(SBD_ANNO_PNG_DIR, img_id + '.png')) | |||||
| def create_voc_train_lst_txt(): | |||||
| voc_train_data_lst = __get_data_list(VOC_TRAIN_TXT) | |||||
| with open(VOC_TRAIN_LST_TXT, mode='w') as f: | |||||
| for id_ in voc_train_data_lst: | |||||
| id_ = id_.strip() | |||||
| img_ = os.path.join(VOC_IMG_DIR, id_ + '.jpg') | |||||
| anno_ = os.path.join(VOC_ANNO_GRAY_DIR, id_ + '.png') | |||||
| f.write(img_ + ' ' + anno_ + '\n') | |||||
| def create_voc_val_lst_txt(): | |||||
| voc_val_data_lst = __get_data_list(VOC_VAL_TXT) | |||||
| with open(VOC_VAL_LST_TXT, mode='w') as f: | |||||
| for id_ in voc_val_data_lst: | |||||
| id_ = id_.strip() | |||||
| img_ = os.path.join(VOC_IMG_DIR, id_ + '.jpg') | |||||
| anno_ = os.path.join(VOC_ANNO_GRAY_DIR, id_ + '.png') | |||||
| f.write(img_ + ' ' + anno_ + '\n') | |||||
| def create_voc_train_aug_lst_txt(): | |||||
| voc_train_data_lst = __get_data_list(VOC_TRAIN_TXT) | |||||
| voc_val_data_lst = __get_data_list(VOC_VAL_TXT) | |||||
| sbd_train_data_lst = __get_data_list(SBD_TRAIN_TXT) | |||||
| sbd_val_data_lst = __get_data_list(SBD_VAL_TXT) | |||||
| with open(VOC_AUG_TRAIN_LST_TXT, mode='w') as f: | |||||
| for id_ in sbd_train_data_lst + sbd_val_data_lst: | |||||
| if id_ in voc_train_data_lst + voc_val_data_lst: | |||||
| continue | |||||
| id_ = id_.strip() | |||||
| img_ = os.path.join(SBD_ANNO_DIR, id_ + '.jpg') | |||||
| anno_ = os.path.join(SBD_ANNO_GRAY_DIR, id_ + '.png') | |||||
| f.write(img_ + ' ' + anno_ + '\n') | |||||
| for id_ in voc_train_data_lst: | |||||
| id_ = id_.strip() | |||||
| img_ = os.path.join(VOC_IMG_DIR, id_ + '.jpg') | |||||
| anno_ = os.path.join(VOC_ANNO_GRAY_DIR, id_ + '.png') | |||||
| f.write(img_ + ' ' + anno_ + '\n') | |||||
| if __name__ == '__main__': | |||||
| print('converting voc color png to gray png ...') | |||||
| conv_voc_colorpng_to_graypng() | |||||
| print('converting done.') | |||||
| create_voc_train_lst_txt() | |||||
| print('generating voc train list success.') | |||||
| create_voc_val_lst_txt() | |||||
| print('generating voc val list success.') | |||||
| print('converting sbd annotations to png ...') | |||||
| conv_sbd_mat_to_png() | |||||
| print('converting done') | |||||
| create_voc_train_aug_lst_txt() | |||||
| print('generating voc train aug list success.') | |||||