├── .DS_Store ├── LICENSE ├── README.assets └── framework.png ├── README.md ├── __init__.py ├── config ├── .DS_Store ├── cityscapes │ ├── .DS_Store │ ├── gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round1.yaml │ ├── gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round2.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round1.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round2.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round1.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round2.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round1.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round2.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round1.yaml │ ├── gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round2.yaml │ ├── train_deeplabv2_cityscapes_split8_crop361_round0.yaml │ ├── train_deeplabv2_cityscapes_split8_crop361_round1.yaml │ ├── train_deeplabv2_cityscapes_split8_crop361_round2.yaml │ ├── train_psp50_cityscapes_split4_crop361_round0.yaml │ ├── train_psp50_cityscapes_split4_crop361_round1.yaml │ ├── train_psp50_cityscapes_split4_crop361_round2.yaml │ ├── train_psp50_cityscapes_split4_crop713_round0.yaml │ ├── train_psp50_cityscapes_split4_crop713_round1.yaml │ ├── train_psp50_cityscapes_split4_crop713_round2.yaml │ ├── train_psp50_cityscapes_split8_crop361_round0.yaml │ ├── train_psp50_cityscapes_split8_crop361_round1.yaml │ ├── train_psp50_cityscapes_split8_crop361_round2.yaml │ ├── train_psp50_cityscapes_split8_crop713_round0.yaml │ ├── train_psp50_cityscapes_split8_crop713_round1.yaml │ └── train_psp50_cityscapes_split8_crop713_round2.yaml └── voc2012 │ ├── gen_pseudo_label_psp50_voc_split1464_crop321_for_round1.yaml │ ├── gen_pseudo_label_psp50_voc_split1464_crop321_for_round2.yaml │ ├── train_psp50_voc_split1464_crop321_round0.yaml │ ├── train_psp50_voc_split1464_crop321_round1.yaml │ └── train_psp50_voc_split1464_crop321_round2.yaml ├── data ├── cityscapes │ ├── cityscapes_colors.txt │ └── cityscapes_names.txt └── voc2012 │ ├── changelist_voc2012_aug.py │ ├── voc2012_colors.txt │ └── voc2012_names.txt ├── data_split ├── cs_split4_labeled.txt ├── cs_split4_labeled_match_len.txt ├── cs_split4_unlabeled.txt ├── cs_split8_labeled.txt ├── cs_split8_labeled_match_len.txt ├── cs_split8_unlabeled.txt ├── cs_val.txt ├── voc_1464_labeled.txt ├── voc_1464_labeled_match_len.txt ├── voc_1464_unlabeled.txt └── voc_val.txt ├── lib ├── psa │ ├── functional.py │ ├── functions │ │ ├── __init__.py │ │ └── psamask.py │ ├── modules │ │ ├── __init__.py │ │ └── psamask.py │ └── src │ │ ├── __init__.py │ │ ├── cpu │ │ ├── operator.cpp │ │ ├── operator.h │ │ └── psamask.cpp │ │ └── gpu │ │ ├── operator.cpp │ │ ├── operator.h │ │ └── psamask_cuda.cu └── sync_bn │ ├── functions │ ├── __init__.py │ └── sync_bn.py │ ├── modules │ ├── __init__.py │ └── sync_bn.py │ └── src │ ├── __init__.py │ ├── cpu │ ├── operator.cpp │ ├── operator.h │ └── sync_bn.cpp │ └── gpu │ ├── common.h │ ├── device_tensor.h │ ├── operator.cpp │ ├── operator.h │ └── sync_bn_cuda.cu ├── model ├── .DS_Store ├── deeplabv2.py ├── psanet.py ├── pspnet.py └── resnet.py ├── tool ├── .DS_Store ├── __init__.py ├── gen_pseudo_label.py ├── gen_pseudo_label.sh ├── gen_pseudo_label_utils.py ├── scripts │ ├── .DS_Store │ ├── train_deeplabv2_cityscapes_split8_crop361.sh │ ├── train_psp50_cityscapes_split4_crop361.sh │ ├── train_psp50_cityscapes_split4_crop713.sh │ ├── train_psp50_cityscapes_split8_crop361.sh │ ├── train_psp50_cityscapes_split8_crop713.sh │ └── train_psp50_voc_split1464_crop321.sh ├── test.py ├── test.sh ├── train.py ├── train.sh └── train_func.py └── util ├── __init__.py ├── __pycache__ ├── __init__.cpython-35.pyc ├── __init__.cpython-36.pyc ├── augmentation.cpython-36.pyc ├── config.cpython-35.pyc ├── config.cpython-36.pyc ├── dataset.cpython-35.pyc ├── dataset.cpython-36.pyc ├── ramps.cpython-36.pyc ├── reader.cpython-36.pyc ├── transform.cpython-35.pyc ├── transform.cpython-36.pyc ├── util.cpython-35.pyc ├── util.cpython-36.pyc └── validate_full_size.cpython-36.pyc ├── augmentation.py ├── config.py ├── dataset.py ├── lovasz_softmax.py ├── my_loss.py ├── ramps.py ├── reader.py ├── transform.py ├── util.py └── validate_full_size.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/.DS_Store -------------------------------------------------------------------------------- /README.assets/framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/README.assets/framework.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DARS 2 | 3 | Code release for the paper "Re-distributing Biased Pseudo Labels for Semi-supervised Semantic Segmentation: A Baseline Investigation", ICCV 2021 (oral). 4 | 5 | ![framework](README.assets/framework.png) 6 | 7 | **Authors**: Ruifei He\*, Jihan Yang\*, Xiaojuan Qi (\*equal contribution) 8 | 9 | [arxiv](https://arxiv.org/abs/2107.11279) 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ### Install 16 | 17 | - Clone this repo: 18 | 19 | ``` 20 | git clone https://https://github.com/CVMI-Lab/DARS.git 21 | cd DARS 22 | ``` 23 | 24 | - Create a conda virtual environment and activate it: 25 | 26 | ``` 27 | conda create -n DARS python=3.7 -y 28 | conda activate DARS 29 | ``` 30 | 31 | - Install `CUDA==10.1` with `cudnn7` following the [official installation instructions](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html) 32 | - Install `PyTorch==1.7.1` and `torchvision==0.8.2` with `CUDA==10.1`: 33 | 34 | ``` 35 | conda install pytorch==1.7.1 torchvision==0.8.2 cudatoolkit=10.1 -c pytorch 36 | ``` 37 | 38 | - Install `Apex`: 39 | 40 | ``` 41 | git clone https://github.com/NVIDIA/apex 42 | cd apex 43 | pip install -v --disable-pip-version-check --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./ 44 | ``` 45 | 46 | - Install other requirements: 47 | 48 | ``` 49 | pip install opencv-python==4.4.0.46 tensorboardX pyyaml 50 | ``` 51 | 52 | 53 | 54 | ### Initialization weights 55 | 56 | For PSPNet50, we follow [PyTorch Semantic Segmentation](https://github.com/hszhao/semseg) and use Imagenet pre-trained weights, which could be found [here](https://drive.google.com/drive/folders/1Hrz1wOxOZm4nIIS7UMJeL79AQrdvpj6v). 57 | 58 | For Deeplabv2, we follow the exact same settings in [semisup-semseg](https://github.com/sud0301/semisup-semseg), [AdvSemiSeg](https://github.com/hfslyc/AdvSemiSeg) and use [Imagenet pre-trained weights](https://download.pytorch.org/models/resnet101-5d3b4d8f.pth). 59 | 60 | ``` 61 | mkdir initmodel 62 | # Put the initialization weights under this folder. 63 | # You can check model/pspnet.py or model/deeplabv2.py. 64 | ``` 65 | 66 | 67 | 68 | ### Data preparation 69 | 70 | ``` 71 | mkdir dataset # put the datasets under this folder. You can verify the data path in config files. 72 | ``` 73 | 74 | #### Cityscapes 75 | 76 | Download the dataset from the Cityscapes dataset server([Link](https://www.cityscapes-dataset.com/)). Download the files named 'gtFine_trainvaltest.zip', 'leftImg8bit_trainvaltest.zip' and extract in `dataset/cityscapes/`. 77 | 78 | For data split, we randomly split the 2975 training samples into 1/8, 7/8 and 1/4 and 3/4. The generated lists are provided in the `data_split` folder. 79 | 80 | Note that since we define an epoch as going through all the samples in the unlabeled data and a batch consists of half labeled and half unlabeled, we repeat the shorter list (labeled list) to the length of the corresponding unlabeled list for convenience. 81 | 82 | You can generate random split lists by yourself or use the ones that we provided. You should put them under `dataset/cityscapes/list/`. 83 | 84 | #### PASCAL VOC 2012 85 | 86 | The PASCAL VOC 2012 dataset we used is the commonly used 10582 training set version. If you are unfamiliar with it, please refer to this [blog](https://www.sun11.me/blog/2018/how-to-use-10582-trainaug-images-on-DeeplabV3-code/). 87 | 88 | For data split, we use the official 1464 training images as labeled data and the 9k augmented set as unlabeled data. We also repeat the labeled list to match that of the unlabeled list. 89 | 90 | You should also put the lists under `dataset/voc2012/list/`. 91 | 92 | 93 | 94 | ### Training 95 | 96 | The config files are located within `config` folder. 97 | 98 | For PSPNet50, crop size 713 requires at least 4*16G GPUs or 8\*10G GPUs, and crop size 361 requires at least 1\*16G GPU or 2\*10G GPUs. 99 | 100 | For Deeplabv2, crop size 361 requires at least 1\*16G GPU or 2\*10G GPUs. 101 | 102 | Please adjust the GPU settings in the config files ('train_gpu' and 'test_gpu') according to your machine setup. 103 | 104 | The generation of pseudo labels would require 200G usage of disk space, reducing to only 600M after they are generated. 105 | 106 | All training scripts for pspnet50 and deeplabv2 are in the `tool/scripts` folder. For example, to train PSPNet50 for the Cityscapes 1/8 split setting with crop size 713x713, use the following command: 107 | 108 | ``` 109 | sh tool/scripts/train_psp50_cityscapes_split8_crop713.sh 110 | ``` 111 | 112 | 113 | 114 | ## Acknowledgement 115 | 116 | Our code is largely based on [PyTorch Semantic Segmentation](https://github.com/hszhao/semseg), and we thank the authors for their wonderful implementation. 117 | 118 | We also thank the open-source code from [semisup-semseg](https://github.com/sud0301/semisup-semseg), [AdvSemiSeg](https://github.com/hfslyc/AdvSemiSeg), [DST-CBC](https://github.com/voldemortX/DST-CBC/). 119 | 120 | 121 | 122 | ## Citation 123 | 124 | If you find this project useful in your research, please consider cite: 125 | 126 | ``` 127 | @inproceedings{he2021re, 128 | title={Re-distributing Biased Pseudo Labels for Semi-supervised Semantic Segmentation: A Baseline Investigation}, 129 | author={He, Ruifei and Yang, Jihan and Qi, Xiaojuan}, 130 | booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision}, 131 | pages={6930--6940}, 132 | year={2021} 133 | } 134 | ``` 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/__init__.py -------------------------------------------------------------------------------- /config/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/config/.DS_Store -------------------------------------------------------------------------------- /config/cityscapes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/config/cityscapes/.DS_Store -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: deeplabv2 13 | layers: 101 14 | pretrain_data: imagenet 15 | sync_bn: True # adopt syncbn or not 16 | train_h: 361 17 | train_w: 361 18 | scale_min: 0.25 # minimum random scale 19 | scale_max: 1.0 # maximum random scale 20 | rotate_min: -10 # minimum random rotate 21 | rotate_max: 10 # maximum random rotate 22 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 23 | ignore_label: 255 24 | aux_weight: 0.4 25 | train_gpu: [4] 26 | workers: 0 # data loader workers 27 | batch_size: 1 # batch size for training 28 | unlabelled_batch_size: 4 29 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 30 | base_lr: 0.01 31 | epochs: 1 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 1 38 | save_freq: 1 39 | save_path: exp/ 40 | weight: initmodel/train_deeplabv2_cityscapes_split8_crop361_round0.pth # path to initial weight (default: none) 41 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 42 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 0 44 | evaluate_freq: 20 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.63 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | 51 | save_pseudo_label_path: cityscapes/pseudo_labels/deeplabv2_cityscapes_split8_crop361_for_round1/ 52 | npy_describ: 'npy_deeplabv2_cityscapes_split8_crop361_for_round1' 53 | global_num: 2603 54 | semi_split: '8' 55 | pseudo_data: cityscapes 56 | update_pseudo_label: True 57 | update_pseudo_start: 0 58 | update_pseudo_freq: 1 59 | labeling_ratio: 0.2 60 | thresholds_method: 'DARS' # cbst or DARS 61 | save_npy_or_png: 'npy' 62 | list_write: 'img_pse' #'pse_gt' # 63 | diagram_T: 1.0 64 | temp_scaling: False 65 | ###------------------------------------------------ my added config 66 | 67 | Distributed: 68 | dist_url: tcp://127.0.0.1:6787 69 | dist_backend: 'nccl' 70 | multiprocessing_distributed: True 71 | world_size: 1 72 | rank: 0 73 | use_apex: True 74 | opt_level: 'O0' 75 | keep_batchnorm_fp32: 76 | loss_scale: 77 | 78 | TEST: 79 | split: val # split in [train, val and test] 80 | # split: test # split in [train, val and test] 81 | base_size: 1024 # based size for scaling 82 | # base_size: 2048 # based size for scaling 83 | # test_h: 713 84 | test_h: 361 85 | # test_w: 713 86 | test_w: 361 87 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 89 | has_prediction: False # has prediction already or not 90 | index_start: 0 # evaluation start index in list 91 | index_step: 0 # evaluation step index in list, 0 means to end 92 | test_gpu: [0] 93 | test_adabn: False 94 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 95 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: deeplabv2 13 | layers: 101 14 | pretrain_data: imagenet 15 | sync_bn: True # adopt syncbn or not 16 | train_h: 361 17 | train_w: 361 18 | scale_min: 0.25 # minimum random scale 19 | scale_max: 1.0 # maximum random scale 20 | rotate_min: -10 # minimum random rotate 21 | rotate_max: 10 # maximum random rotate 22 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 23 | ignore_label: 255 24 | aux_weight: 0.4 25 | train_gpu: [0] 26 | workers: 0 # data loader workers 27 | batch_size: 1 # batch size for training 28 | unlabelled_batch_size: 4 29 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 30 | base_lr: 0.01 31 | epochs: 1 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 1 38 | save_freq: 1 39 | save_path: exp/ 40 | weight: initmodel/train_deeplabv2_cityscapes_split8_crop361_round1.pth # path to initial weight (default: none) 41 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 42 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 0 44 | evaluate_freq: 20 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.63 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | 51 | save_pseudo_label_path: cityscapes/pseudo_labels/deeplabv2_cityscapes_split8_crop361_for_round2/ 52 | npy_describ: 'npy_deeplabv2_cityscapes_split8_crop361_for_round2' 53 | global_num: 2603 54 | semi_split: '8' 55 | pseudo_data: cityscapes 56 | update_pseudo_label: True 57 | update_pseudo_start: 0 58 | update_pseudo_freq: 1 59 | labeling_ratio: 0.45 60 | thresholds_method: 'DARS' # cbst or DARS 61 | save_npy_or_png: 'npy' 62 | list_write: 'img_pse' #'pse_gt' # 63 | diagram_T: 1.0 64 | temp_scaling: False 65 | ###------------------------------------------------ my added config 66 | 67 | Distributed: 68 | dist_url: tcp://127.0.0.1:6787 69 | dist_backend: 'nccl' 70 | multiprocessing_distributed: True 71 | world_size: 1 72 | rank: 0 73 | use_apex: True 74 | opt_level: 'O0' 75 | keep_batchnorm_fp32: 76 | loss_scale: 77 | 78 | TEST: 79 | split: val # split in [train, val and test] 80 | # split: test # split in [train, val and test] 81 | base_size: 1024 # based size for scaling 82 | # base_size: 2048 # based size for scaling 83 | # test_h: 713 84 | test_h: 361 85 | # test_w: 713 86 | test_w: 361 87 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 89 | has_prediction: False # has prediction already or not 90 | index_start: 0 # evaluation start index in list 91 | index_step: 0 # evaluation step index in list, 0 means to end 92 | test_gpu: [0] 93 | test_adabn: False 94 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 95 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split4_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 361 16 | train_w: 361 17 | scale_min: 0.25 # minimum random scale 18 | scale_max: 1.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [0] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split4_crop361_round0.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split4_crop361_for_round1/ 51 | npy_describ: 'npy_psp50_cityscapes_split4_crop361_for_round1' 52 | global_num: 2231 # number of unlabeled images to pseudo-label 53 | semi_split: '4' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.4 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | base_size: 1024 # based size for scaling 81 | # base_size: 2048 # based size for scaling 82 | # test_h: 713 83 | test_h: 361 84 | # test_w: 713 85 | test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [0] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split4_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 361 16 | train_w: 361 17 | scale_min: 0.25 # minimum random scale 18 | scale_max: 1.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split4_crop361_round1.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split4_crop361_for_round2/ 51 | npy_describ: 'npy_psp50_cityscapes_split4_crop361_for_round2' 52 | global_num: 2231 53 | semi_split: '4' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.6 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | base_size: 1024 # based size for scaling 81 | # base_size: 2048 # based size for scaling 82 | # test_h: 713 83 | test_h: 361 84 | # test_w: 713 85 | test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [0] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split4_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | train_w: 713 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 2.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split4_crop713_round0.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split4_crop713_for_round1/ 51 | npy_describ: 'npy_psp50_cityscapes_split4_crop713_for_round1' 52 | global_num: 2231 53 | semi_split: '4' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.4 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | # base_size: 1024 # based size for scaling 81 | base_size: 2048 # based size for scaling 82 | test_h: 713 83 | # test_h: 361 84 | test_w: 713 85 | # test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [4] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split4_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | train_w: 713 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 2.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split4_crop713_round1.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split4_crop713_for_round2/ 51 | npy_describ: 'npy_psp50_cityscapes_split4_crop713_for_round2' 52 | global_num: 2231 53 | semi_split: '4' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.65 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | # base_size: 1024 # based size for scaling 81 | base_size: 2048 # based size for scaling 82 | test_h: 713 83 | # test_h: 361 84 | test_w: 713 85 | # test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [4] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 361 16 | train_w: 361 17 | scale_min: 0.25 # minimum random scale 18 | scale_max: 1.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split8_crop361_round0.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split8_crop361_for_round1/ 51 | npy_describ: 'npy_psp50_cityscapes_split8_crop361_for_round1' 52 | global_num: 2603 53 | semi_split: '8' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.2 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | base_size: 1024 # based size for scaling 81 | # base_size: 2048 # based size for scaling 82 | # test_h: 713 83 | test_h: 361 84 | # test_w: 713 85 | test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [0] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 361 16 | train_w: 361 17 | scale_min: 0.25 # minimum random scale 18 | scale_max: 1.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split8_crop361_round1.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split8_crop361_for_round2/ 51 | npy_describ: 'npy_psp50_cityscapes_split8_crop361_for_round2' 52 | global_num: 2603 53 | semi_split: '8' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.5 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | base_size: 1024 # based size for scaling 81 | # base_size: 2048 # based size for scaling 82 | # test_h: 713 83 | test_h: 361 84 | # test_w: 713 85 | test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [0] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | train_w: 713 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 2.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split8_crop713_round0.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split8_crop713_for_round1/ 51 | npy_describ: 'npy_psp50_cityscapes_split8_crop713_for_round1' 52 | global_num: 2603 53 | semi_split: '8' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.4 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | # base_size: 1024 # based size for scaling 81 | base_size: 2048 # based size for scaling 82 | test_h: 713 83 | # test_h: 361 84 | test_w: 713 85 | # test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [4] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled.txt 6 | prediction_list: cityscapes/list/cs_split8_unlabeled.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | train_w: 713 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 2.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 1 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 1 37 | save_freq: 1 38 | save_path: exp/ 39 | weight: initmodel/train_psp50_cityscapes_split8_crop713_round1.pth # path to initial weight (default: none) 40 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 41 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 42 | evaluate_start: 0 43 | evaluate_freq: 20 44 | evaluate_full_size: True 45 | evaluate_previous_best_val_mIou: 0.63 46 | 47 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 48 | consistency_lambda: 1.0 49 | 50 | save_pseudo_label_path: cityscapes/pseudo_labels/psp50_cityscapes_split8_crop713_for_round2/ 51 | npy_describ: 'npy_psp50_cityscapes_split8_crop713_for_round2' 52 | global_num: 2603 53 | semi_split: '8' 54 | pseudo_data: cityscapes 55 | update_pseudo_label: True 56 | update_pseudo_start: 0 57 | update_pseudo_freq: 1 58 | labeling_ratio: 0.65 59 | thresholds_method: 'DARS' # cbst or DARS 60 | save_npy_or_png: 'npy' 61 | list_write: 'img_pse' #'pse_gt' # 62 | diagram_T: 1.0 63 | temp_scaling: False 64 | ###------------------------------------------------ my added config 65 | 66 | Distributed: 67 | dist_url: tcp://127.0.0.1:6787 68 | dist_backend: 'nccl' 69 | multiprocessing_distributed: True 70 | world_size: 1 71 | rank: 0 72 | use_apex: True 73 | opt_level: 'O0' 74 | keep_batchnorm_fp32: 75 | loss_scale: 76 | 77 | TEST: 78 | split: val # split in [train, val and test] 79 | # split: test # split in [train, val and test] 80 | # base_size: 1024 # based size for scaling 81 | base_size: 2048 # based size for scaling 82 | test_h: 713 83 | # test_h: 361 84 | test_w: 713 85 | # test_w: 361 86 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 87 | # scales: [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 88 | has_prediction: False # has prediction already or not 89 | index_start: 0 # evaluation start index in list 90 | index_step: 0 # evaluation step index in list, 0 means to end 91 | test_gpu: [4] 92 | test_adabn: False 93 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 94 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names -------------------------------------------------------------------------------- /config/cityscapes/train_deeplabv2_cityscapes_split8_crop361_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: deeplabv2 13 | layers: 101 14 | pretrain_data: imagenet 15 | sync_bn: True # adopt syncbn or not 16 | train_h: 361 17 | train_w: 361 18 | scale_min: 0.25 # minimum random scale 19 | scale_max: 1.0 # maximum random scale 20 | rotate_min: -10 # minimum random rotate 21 | rotate_max: 10 # maximum random rotate 22 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 23 | ignore_label: 255 24 | aux_weight: 0.0 25 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 26 | greedytrain_gpu: [2] 27 | workers: 16 # data loader workers 28 | batch_size: 16 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.002 32 | epochs: 200 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: # path to initial weight (default: none) 43 | resume: # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 80 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: True 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_deeplabv2_cityscapes_split8_crop361_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_deeplabv2_cityscapes_split8_crop361_for_round1_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: deeplabv2 13 | layers: 101 14 | pretrain_data: imagenet 15 | sync_bn: True # adopt syncbn or not 16 | train_h: 361 17 | train_w: 361 18 | scale_min: 0.25 # minimum random scale 19 | scale_max: 1.0 # maximum random scale 20 | rotate_min: -10 # minimum random rotate 21 | rotate_max: 10 # maximum random rotate 22 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 23 | ignore_label: 255 24 | aux_weight: 0.0 25 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 26 | workers: 8 # data loader workers 27 | batch_size: 4 # batch size for labeled data 28 | unlabelled_batch_size: 4 # batch size for unlabeled data 29 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 30 | base_lr: 0.002 31 | epochs: 400 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 10 38 | save_freq: 20 39 | save_path: exp/ 40 | exp_name: str 41 | weight: # path to initial weight (default: none) 42 | resume: initmodel/train_deeplabv2_cityscapes_split8_crop361_round0.pth # path to latest checkpoint (default: none) 43 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 44 | evaluate_start: 280 45 | evaluate_freq: 20 46 | evaluate_full_size: True 47 | evaluate_previous_best_val_mIou: 0.0 48 | 49 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 50 | consistency_lambda: 1.0 51 | only_label: False 52 | 53 | 54 | Distributed: 55 | dist_url: tcp://127.0.0.1:6788 56 | dist_backend: 'nccl' 57 | multiprocessing_distributed: True 58 | world_size: 1 59 | rank: 0 60 | use_apex: True 61 | opt_level: 'O0' 62 | keep_batchnorm_fp32: 63 | loss_scale: 64 | 65 | TEST: 66 | split: val # split in [train, val and test] 67 | base_size: 1024 # based size for scaling 68 | # test_h: 713 69 | test_h: 361 70 | # test_w: 713 71 | test_w: 361 72 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 73 | has_prediction: False # has prediction already or not 74 | index_start: 0 # evaluation start index in list 75 | index_step: 0 # evaluation step index in list, 0 means to end 76 | test_gpu: [0] 77 | save_folder: exp/ 78 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 79 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 80 | -------------------------------------------------------------------------------- /config/cityscapes/train_deeplabv2_cityscapes_split8_crop361_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_deeplabv2_cityscapes_split8_crop361_for_round2_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: deeplabv2 13 | layers: 101 14 | pretrain_data: imagenet 15 | sync_bn: True # adopt syncbn or not 16 | train_h: 361 17 | train_w: 361 18 | scale_min: 0.25 # minimum random scale 19 | scale_max: 1.0 # maximum random scale 20 | rotate_min: -10 # minimum random rotate 21 | rotate_max: 10 # maximum random rotate 22 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 23 | ignore_label: 255 24 | aux_weight: 0.0 25 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 26 | workers: 8 # data loader workers 27 | batch_size: 4 # batch size for labeled data 28 | unlabelled_batch_size: 4 # batch size for unlabeled data 29 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 30 | base_lr: 0.002 31 | epochs: 600 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 10 38 | save_freq: 20 39 | save_path: exp/ 40 | exp_name: str 41 | weight: # path to initial weight (default: none) 42 | resume: initmodel/train_deeplabv2_cityscapes_split8_crop361_round1.pth # path to latest checkpoint (default: none) 43 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 44 | evaluate_start: 480 45 | evaluate_freq: 20 46 | evaluate_full_size: True 47 | evaluate_previous_best_val_mIou: 0.0 48 | 49 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 50 | consistency_lambda: 1.0 51 | only_label: False 52 | 53 | 54 | Distributed: 55 | dist_url: tcp://127.0.0.1:6788 56 | dist_backend: 'nccl' 57 | multiprocessing_distributed: True 58 | world_size: 1 59 | rank: 0 60 | use_apex: True 61 | opt_level: 'O0' 62 | keep_batchnorm_fp32: 63 | loss_scale: 64 | 65 | TEST: 66 | split: val # split in [train, val and test] 67 | base_size: 1024 # based size for scaling 68 | # test_h: 713 69 | test_h: 361 70 | # test_w: 713 71 | test_w: 361 72 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 73 | has_prediction: False # has prediction already or not 74 | index_start: 0 # evaluation start index in list 75 | index_step: 0 # evaluation step index in list, 0 means to end 76 | test_gpu: [0] 77 | save_folder: exp/ 78 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 79 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 80 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop361_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_labeled.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.25 # minimum random scale 20 | scale_max: 1.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 16 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 200 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: # path to initial weight (default: none) 43 | resume: # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 80 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: True 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 79 | save_folder: exp/ 80 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 81 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 82 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop361_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled_psp50_cityscapes_split4_crop361_for_round1_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.25 # minimum random scale 20 | scale_max: 1.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1,2,3] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 400 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split4_crop361_round0.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 280 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | # model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 79 | save_folder: exp/ 80 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 81 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 82 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop361_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled_psp50_cityscapes_split4_crop361_for_round2_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.2 # minimum random scale 20 | scale_max: 1.5 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 600 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split4_crop361_round1.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 480 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop713_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_labeled.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.5 # minimum random scale 20 | scale_max: 2.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1,2,3,4,5,6,7] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 16 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 200 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: # path to initial weight (default: none) 43 | resume: # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 80 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: True 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [4] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop713_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled_psp50_cityscapes_split4_crop713_for_round1_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.5 # minimum random scale 20 | scale_max: 2.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1,2,3,4,5,6,7] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 16 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 400 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split4_crop713_round0.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 280 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split4_crop713_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split4_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split4_unlabeled_psp50_cityscapes_split4_crop713_for_round2_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.4 # minimum random scale 20 | scale_max: 2.5 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1,2,3,4,5,6,7] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 16 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 600 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split4_crop713_round1.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 400 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop361_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_labeled.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.25 # minimum random scale 20 | scale_max: 1.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 16 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 200 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: # path to initial weight (default: none) 43 | resume: # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 80 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: True 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 79 | save_folder: exp/ 80 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 81 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 82 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop361_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_psp50_cityscapes_split8_crop361_for_round1_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.25 # minimum random scale 20 | scale_max: 1.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 400 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split8_crop361_round0.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 280 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop361_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_psp50_cityscapes_split8_crop361_for_round2_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | # train_h: 713 16 | train_h: 361 17 | # train_w: 713 18 | train_w: 361 19 | scale_min: 0.2 # minimum random scale 20 | scale_max: 1.5 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 600 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split8_crop361_round1.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 480 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 1024 # based size for scaling 69 | # test_h: 713 70 | test_h: 361 71 | # test_w: 713 72 | test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 79 | save_folder: exp/ 80 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 81 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 82 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop713_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_labeled.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.5 # minimum random scale 20 | scale_max: 2.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [4,5,6,7] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 16 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 200 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: # path to initial weight (default: none) 43 | resume: # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 80 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: True 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [4] 78 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 79 | save_folder: exp/ 80 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 81 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 82 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop713_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_psp50_cityscapes_split8_crop713_for_round1_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.5 # minimum random scale 20 | scale_max: 2.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [4,5,6,7] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 400 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split8_crop713_round0.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 280 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/cityscapes/train_psp50_cityscapes_split8_crop713_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: cityscapes 4 | train_labeled_list: cityscapes/list/cs_split8_labeled_match_len.txt 5 | train_unlabeled_list: cityscapes/list/cs_split8_unlabeled_psp50_cityscapes_split8_crop713_for_round2_DARS.txt 6 | prediction_list: cityscapes/list/cs_val.txt 7 | val_list: cityscapes/list/cs_val.txt 8 | test_list: cityscapes/list/cs_val.txt 9 | classes: 19 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 713 16 | # train_h: 361 17 | train_w: 713 18 | # train_w: 361 19 | scale_min: 0.5 # minimum random scale 20 | scale_max: 3.0 # maximum random scale 21 | rotate_min: -10 # minimum random rotate 22 | rotate_max: 10 # maximum random rotate 23 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 24 | ignore_label: 255 25 | aux_weight: 0.4 26 | train_gpu: [0,1,2,3] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 27 | workers: 8 # data loader workers 28 | batch_size: 8 # batch size for labeled data 29 | unlabelled_batch_size: 8 # batch size for unlabeled data 30 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 31 | base_lr: 0.01 32 | epochs: 600 # resume from 200 epoch ckpt, this round actually has 200 epochs. 33 | start_epoch: 0 34 | power: 0.9 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | manual_seed: 1 38 | print_freq: 10 39 | save_freq: 20 40 | save_path: exp/ 41 | exp_name: str 42 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 43 | resume: initmodel/train_psp50_cityscapes_split8_crop713_round1.pth # path to latest checkpoint (default: none) 44 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 45 | evaluate_start: 400 46 | evaluate_freq: 20 47 | evaluate_full_size: True 48 | evaluate_previous_best_val_mIou: 0.0 49 | 50 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 51 | consistency_lambda: 1.0 52 | only_label: False 53 | 54 | 55 | Distributed: 56 | dist_url: tcp://127.0.0.1:6788 57 | dist_backend: 'nccl' 58 | multiprocessing_distributed: True 59 | world_size: 1 60 | rank: 0 61 | use_apex: True 62 | opt_level: 'O0' 63 | keep_batchnorm_fp32: 64 | loss_scale: 65 | 66 | TEST: 67 | split: val # split in [train, val and test] 68 | base_size: 2048 # based size for scaling 69 | test_h: 713 70 | # test_h: 361 71 | test_w: 713 72 | # test_w: 361 73 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 74 | has_prediction: False # has prediction already or not 75 | index_start: 0 # evaluation start index in list 76 | index_step: 0 # evaluation step index in list, 0 means to end 77 | test_gpu: [0] 78 | save_folder: exp/ 79 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 80 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 81 | -------------------------------------------------------------------------------- /config/voc2012/gen_pseudo_label_psp50_voc_split1464_crop321_for_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: voc2012 4 | train_labeled_list: voc2012/list/voc_1464_labeled.txt 5 | train_unlabeled_list: voc2012/list/voc_1464_unlabeled.txt 6 | prediction_list: voc2012/list/voc_val.txt 7 | val_list: voc2012/list/voc_val.txt 8 | test_list: voc2012/list/voc_val.txt 9 | classes: 21 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 321 16 | train_w: 321 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 1.5 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | # base_lr: 0.04 31 | epochs: 1 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 1 38 | save_freq: 1 39 | save_path: exp/ 40 | weight: initmodel/train_psp50_voc_split1464_crop321_round0.pth # path to initial weight (default: none) 41 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 42 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 0 44 | evaluate_freq: 20 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.0 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | 51 | save_pseudo_label_path: voc2012/pseudo_labels/psp50_voc_split1464_crop321_for_round1/ 52 | npy_describ: 'npy_psp50_voc_split1464_crop321_for_round1' 53 | global_num: 9118 54 | semi_split: '1.4k' 55 | pseudo_data: voc2012 56 | update_pseudo_label: True 57 | update_pseudo_start: 0 58 | update_pseudo_freq: 1 59 | labeling_ratio: 0.4 60 | thresholds_method: 'DARS' # cbst or DARS 61 | save_npy_or_png: 'npy' 62 | list_write: 'img_pse' #'pse_gt' # 63 | diagram_T: 1.0 64 | temp_scaling: False 65 | ###------------------------------------------------ my added config 66 | 67 | Distributed: 68 | dist_url: tcp://127.0.0.1:6787 69 | dist_backend: 'nccl' 70 | multiprocessing_distributed: True 71 | world_size: 1 72 | rank: 0 73 | use_apex: True 74 | opt_level: 'O0' 75 | keep_batchnorm_fp32: 76 | loss_scale: 77 | 78 | TEST: 79 | split: val # split in [train, val and test] 80 | base_size: 400 # based size for scaling 81 | test_h: 321 82 | test_w: 321 83 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 84 | has_prediction: False # has prediction already or not 85 | index_start: 0 # evaluation start index in list 86 | index_step: 0 # evaluation step index in list, 0 means to end 87 | test_gpu: [0] 88 | test_adabn: False 89 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 90 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 91 | -------------------------------------------------------------------------------- /config/voc2012/gen_pseudo_label_psp50_voc_split1464_crop321_for_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: voc2012 4 | train_labeled_list: voc2012/list/voc_1464_labeled.txt 5 | train_unlabeled_list: voc2012/list/voc_1464_unlabeled.txt 6 | prediction_list: voc2012/list/voc_val.txt 7 | val_list: voc2012/list/voc_val.txt 8 | test_list: voc2012/list/voc_val.txt 9 | classes: 21 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 321 16 | train_w: 321 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 1.5 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [4] 25 | workers: 0 # data loader workers 26 | batch_size: 1 # batch size for training 27 | unlabelled_batch_size: 4 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | # base_lr: 0.04 31 | epochs: 1 32 | start_epoch: 0 33 | power: 0.9 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | manual_seed: 1 37 | print_freq: 1 38 | save_freq: 1 39 | save_path: exp/ 40 | weight: initmodel/train_psp50_voc_split1464_crop321_round1.pth # path to initial weight (default: none) 41 | resume: #exp/ex_test/model/train_epoch_280.pth # path to latest checkpoint (default: none) 42 | evaluate: False # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 0 44 | evaluate_freq: 20 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.0 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | 51 | save_pseudo_label_path: voc2012/pseudo_labels/psp50_voc_split1464_crop321_for_round2/ 52 | npy_describ: 'npy_psp50_voc_split1464_crop321_for_round2' 53 | global_num: 9118 54 | semi_split: '1.4k' 55 | pseudo_data: voc2012 56 | update_pseudo_label: True 57 | update_pseudo_start: 0 58 | update_pseudo_freq: 1 59 | labeling_ratio: 0.5 60 | thresholds_method: 'DARS' # cbst or DARS 61 | save_npy_or_png: 'npy' 62 | list_write: 'img_pse' #'pse_gt' # 63 | diagram_T: 1.0 64 | temp_scaling: False 65 | ###------------------------------------------------ my added config 66 | 67 | Distributed: 68 | dist_url: tcp://127.0.0.1:6787 69 | dist_backend: 'nccl' 70 | multiprocessing_distributed: True 71 | world_size: 1 72 | rank: 0 73 | use_apex: True 74 | opt_level: 'O0' 75 | keep_batchnorm_fp32: 76 | loss_scale: 77 | 78 | TEST: 79 | split: val # split in [train, val and test] 80 | base_size: 400 # based size for scaling 81 | test_h: 321 82 | test_w: 321 83 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 84 | has_prediction: False # has prediction already or not 85 | index_start: 0 # evaluation start index in list 86 | index_step: 0 # evaluation step index in list, 0 means to end 87 | test_gpu: [0] 88 | test_adabn: False 89 | colors_path: data/cityscapes/cityscapes_colors.txt # path of dataset colors 90 | names_path: data/cityscapes/cityscapes_names.txt # path of dataset category names 91 | -------------------------------------------------------------------------------- /config/voc2012/train_psp50_voc_split1464_crop321_round0.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: voc2012 4 | train_labeled_list: voc2012/list/voc_1464_labeled.txt 5 | train_unlabeled_list: voc2012/list/voc_1464_labeled.txt 6 | prediction_list: voc2012/list/voc_val.txt 7 | val_list: voc2012/list/voc_val.txt 8 | test_list: voc2012/list/voc_val.txt 9 | classes: 21 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 321 16 | train_w: 321 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 1.5 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [0,1,2,3] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 25 | workers: 8 # data loader workers 26 | batch_size: 16 # batch size for labeled data 27 | unlabelled_batch_size: 8 # batch size for unlabeled data 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 50 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 10 37 | save_freq: 10 38 | save_path: exp/ 39 | exp_name: str 40 | weight: #initmodel/ex60.5.1_0.68_train_epoch_400.pth #initmodel/greedy_train_epoch_200.pth # path to initial weight (default: none) 41 | resume: #initmodel/ST_iter0_0.6546_ex35.10_cf0.96_train_epoch_400.pth # path to latest checkpoint (default: none) 42 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 44 44 | evaluate_freq: 2 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.0 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | only_label: True 51 | 52 | 53 | Distributed: 54 | dist_url: tcp://127.0.0.1:6788 55 | dist_backend: 'nccl' 56 | multiprocessing_distributed: True 57 | world_size: 1 58 | rank: 0 59 | use_apex: True 60 | opt_level: 'O0' 61 | keep_batchnorm_fp32: 62 | loss_scale: 63 | 64 | TEST: 65 | split: val # split in [train, val and test] 66 | base_size: 400 # based size for scaling 67 | test_h: 321 68 | test_w: 321 69 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 70 | has_prediction: False # has prediction already or not 71 | index_start: 0 # evaluation start index in list 72 | index_step: 0 # evaluation step index in list, 0 means to end 73 | test_gpu: [0] 74 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 75 | save_folder: exp/ 76 | colors_path: data/voc2012/voc2012_colors.txt # path of dataset colors 77 | names_path: data/voc2012/voc2012_names.txt # path of dataset category names 78 | -------------------------------------------------------------------------------- /config/voc2012/train_psp50_voc_split1464_crop321_round1.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: voc2012 4 | train_labeled_list: voc2012/list/voc_1464_labeled_match_len.txt 5 | train_unlabeled_list: voc2012/list/voc_1464_unlabeled_psp50_voc_split1464_crop321_for_round1_DARS.txt 6 | prediction_list: voc2012/list/voc_val.txt 7 | val_list: voc2012/list/voc_val.txt 8 | test_list: voc2012/list/voc_val.txt 9 | classes: 21 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 321 16 | train_w: 321 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 1.5 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [0,1,2,3] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 25 | workers: 8 # data loader workers 26 | batch_size: 8 # batch size for labeled data 27 | unlabelled_batch_size: 8 # batch size for unlabeled data 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 100 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 10 37 | save_freq: 10 38 | save_path: exp/ 39 | exp_name: str 40 | weight: # path to initial weight (default: none) 41 | resume: initmodel/train_psp50_voc_split1464_crop321_round0.pth # path to latest checkpoint (default: none) 42 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 94 44 | evaluate_freq: 2 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.0 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | only_label: False 51 | 52 | 53 | Distributed: 54 | dist_url: tcp://127.0.0.1:6788 55 | dist_backend: 'nccl' 56 | multiprocessing_distributed: True 57 | world_size: 1 58 | rank: 0 59 | use_apex: True 60 | opt_level: 'O0' 61 | keep_batchnorm_fp32: 62 | loss_scale: 63 | 64 | TEST: 65 | split: val # split in [train, val and test] 66 | base_size: 400 # based size for scaling 67 | test_h: 321 68 | test_w: 321 69 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 70 | has_prediction: False # has prediction already or not 71 | index_start: 0 # evaluation start index in list 72 | index_step: 0 # evaluation step index in list, 0 means to end 73 | test_gpu: [0] 74 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 75 | save_folder: exp/ 76 | colors_path: data/voc2012/voc2012_colors.txt # path of dataset colors 77 | names_path: data/voc2012/voc2012_names.txt # path of dataset category names 78 | -------------------------------------------------------------------------------- /config/voc2012/train_psp50_voc_split1464_crop321_round2.yaml: -------------------------------------------------------------------------------- 1 | DATA: 2 | local_prefix: dataset/ # data_root prefix 3 | data_root: voc2012 4 | train_labeled_list: voc2012/list/voc_1464_labeled_match_len.txt 5 | train_unlabeled_list: voc2012/list/voc_1464_unlabeled_psp50_voc_split1464_crop321_for_round2_DARS.txt 6 | prediction_list: voc2012/list/voc_val.txt 7 | val_list: voc2012/list/voc_val.txt 8 | test_list: voc2012/list/voc_val.txt 9 | classes: 21 10 | 11 | TRAIN: 12 | arch: psp 13 | layers: 50 14 | sync_bn: True # adopt syncbn or not 15 | train_h: 321 16 | train_w: 321 17 | scale_min: 0.5 # minimum random scale 18 | scale_max: 2.0 # maximum random scale 19 | rotate_min: -10 # minimum random rotate 20 | rotate_max: 10 # maximum random rotate 21 | zoom_factor: 8 # zoom factor for final prediction during training, be in [1, 2, 4, 8] 22 | ignore_label: 255 23 | aux_weight: 0.4 24 | train_gpu: [0,1,2,3] # gpu id, change to [0,1,2,3,4,5,6,7] for 8-gpu 25 | workers: 8 # data loader workers 26 | batch_size: 8 # batch size for labeled data 27 | unlabelled_batch_size: 8 # batch size for unlabeled data 28 | batch_size_val: 8 # batch size for validation during training, memory and speed tradeoff 29 | base_lr: 0.01 30 | epochs: 150 31 | start_epoch: 0 32 | power: 0.9 33 | momentum: 0.9 34 | weight_decay: 0.0001 35 | manual_seed: 1 36 | print_freq: 10 37 | save_freq: 10 38 | save_path: exp/ 39 | exp_name: str 40 | weight: # path to initial weight (default: none) 41 | resume: initmodel/train_psp50_voc_split1464_crop321_round1.pth # path to latest checkpoint (default: none) 42 | evaluate: True # evaluate on validation set, extra gpu memory needed and small batch_size_val is recommend 43 | evaluate_start: 120 44 | evaluate_freq: 5 45 | evaluate_full_size: True 46 | evaluate_previous_best_val_mIou: 0.0 47 | 48 | sup_loss_method: 'CE' # 'MSE' 'CE' 'lovasz' 49 | consistency_lambda: 1.0 50 | only_label: False 51 | 52 | 53 | Distributed: 54 | dist_url: tcp://127.0.0.1:6788 55 | dist_backend: 'nccl' 56 | multiprocessing_distributed: True 57 | world_size: 1 58 | rank: 0 59 | use_apex: True 60 | opt_level: 'O0' 61 | keep_batchnorm_fp32: 62 | loss_scale: 63 | 64 | TEST: 65 | split: val # split in [train, val and test] 66 | base_size: 400 # based size for scaling 67 | test_h: 321 68 | test_w: 321 69 | scales: [1.0] # evaluation scales, ms as [0.5, 0.75, 1.0, 1.25, 1.5, 1.75] 70 | has_prediction: False # has prediction already or not 71 | index_start: 0 # evaluation start index in list 72 | index_step: 0 # evaluation step index in list, 0 means to end 73 | test_gpu: [0] 74 | model_path: exp/ex36.7/model/train_epoch_400.pth # evaluation model path 75 | save_folder: exp/ 76 | colors_path: data/voc2012/voc2012_colors.txt # path of dataset colors 77 | names_path: data/voc2012/voc2012_names.txt # path of dataset category names 78 | -------------------------------------------------------------------------------- /data/cityscapes/cityscapes_colors.txt: -------------------------------------------------------------------------------- 1 | 128 64 128 2 | 244 35 232 3 | 70 70 70 4 | 102 102 156 5 | 190 153 153 6 | 153 153 153 7 | 250 170 30 8 | 220 220 0 9 | 107 142 35 10 | 152 251 152 11 | 70 130 180 12 | 220 20 60 13 | 255 0 0 14 | 0 0 142 15 | 0 0 70 16 | 0 60 100 17 | 0 80 100 18 | 0 0 230 19 | 119 11 32 20 | -------------------------------------------------------------------------------- /data/cityscapes/cityscapes_names.txt: -------------------------------------------------------------------------------- 1 | road 2 | sidewalk 3 | building 4 | wall 5 | fence 6 | pole 7 | traffic light 8 | traffic sign 9 | vegetation 10 | terrain 11 | sky 12 | person 13 | rider 14 | car 15 | truck 16 | bus 17 | train 18 | motorcycle 19 | bicycle 20 | -------------------------------------------------------------------------------- /data/voc2012/changelist_voc2012_aug.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | read_filepath = '/public/home/rfhe/data/voc2012/list/test.txt' 5 | save_filepath = '/public/home/rfhe/data/voc2012/list/test_our.txt' 6 | 7 | with open(read_filepath, 'r') as f: 8 | for line in f.readlines(): 9 | line = line.strip() 10 | w1= open(save_filepath, 'a') 11 | # w1.write('JPEGImages/'+line+'.jpg SegmentationClassAug/'+line+'.png \n') 12 | w1.write('test/JPEGImages/'+line+'.jpg \n') 13 | # w1.write(line) 14 | 15 | -------------------------------------------------------------------------------- /data/voc2012/voc2012_colors.txt: -------------------------------------------------------------------------------- 1 | 0 0 0 2 | 128 0 0 3 | 0 128 0 4 | 128 128 0 5 | 0 0 128 6 | 128 0 128 7 | 0 128 128 8 | 128 128 128 9 | 64 0 0 10 | 192 0 0 11 | 64 128 0 12 | 192 128 0 13 | 64 0 128 14 | 192 0 128 15 | 64 128 128 16 | 192 128 128 17 | 0 64 0 18 | 128 64 0 19 | 0 192 0 20 | 128 192 0 21 | 0 64 128 22 | -------------------------------------------------------------------------------- /data/voc2012/voc2012_names.txt: -------------------------------------------------------------------------------- 1 | background 2 | aeroplane 3 | bicycle 4 | bird 5 | boat 6 | bottle 7 | bus 8 | car 9 | cat 10 | chair 11 | cow 12 | diningtable 13 | dog 14 | horse 15 | motorbike 16 | person 17 | pottedplant 18 | sheep 19 | sofa 20 | train 21 | tvmonitor 22 | -------------------------------------------------------------------------------- /lib/psa/functional.py: -------------------------------------------------------------------------------- 1 | """Functional interface""" 2 | 3 | from . import functions 4 | 5 | 6 | def psa_mask(input, psa_type=0, mask_H_=None, mask_W_=None): 7 | return functions.PSAMask(psa_type, mask_H_, mask_W_)(input) 8 | -------------------------------------------------------------------------------- /lib/psa/functions/__init__.py: -------------------------------------------------------------------------------- 1 | from .psamask import * 2 | -------------------------------------------------------------------------------- /lib/psa/functions/psamask.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Function 3 | from .. import src 4 | 5 | 6 | class PSAMask(Function): 7 | def __init__(self, psa_type=0, mask_H_=None, mask_W_=None): 8 | super(PSAMask, self).__init__() 9 | assert psa_type in [0, 1] # 0-col, 1-dis 10 | self.psa_type = psa_type 11 | assert (mask_H_ is None and mask_W_ is None) or (mask_H_ is not None and mask_W_ is not None) 12 | self.mask_H_ = mask_H_ 13 | self.mask_W_ = mask_W_ 14 | 15 | def forward(self, input): 16 | num_, channels_, feature_H_, feature_W_ = input.size() 17 | if self.mask_H_ is not None and self.mask_W_ is not None: 18 | mask_H_ = self.mask_H_ 19 | mask_W_ = self.mask_W_ 20 | assert mask_H_ % 2 == 1 21 | assert mask_W_ % 2 == 1 22 | else: 23 | mask_H_ = 2 * feature_H_ - 1 24 | mask_W_ = 2 * feature_W_ - 1 25 | assert channels_ == mask_H_ * mask_W_ 26 | half_mask_H_ = (mask_H_ - 1) // 2 27 | half_mask_W_ = (mask_W_ - 1) // 2 28 | output = torch.zeros([num_, feature_H_ * feature_W_, feature_H_, feature_W_], dtype=input.dtype, device=input.device) 29 | ''' python implementation - slow 30 | for n in range(num_): 31 | for h in range(feature_H_): 32 | for w in range(feature_W_): 33 | hstart = max(0, half_mask_H_ - h) 34 | hend = min(mask_H_, feature_H_ + half_mask_H_ - h) 35 | wstart = max(0, half_mask_W_ - w) 36 | wend = min(mask_W_, feature_W_ + half_mask_W_ - w) 37 | hstart_com = max(0, h - half_mask_H_) 38 | hend_com = min(feature_H_, h + half_mask_H_ + 1) 39 | wstart_com = max(0, w - half_mask_W_) 40 | wend_com = min(feature_W_, w + half_mask_W_ + 1) 41 | mask_ori = input[n, :, h, w].view(mask_H_, mask_W_) 42 | mask_com = torch.zeros(feature_H_, feature_W_, dtype=input.dtype, device=input.device) 43 | mask_com[hstart_com:hend_com, wstart_com:wend_com] = mask_ori[hstart:hend, wstart:wend] 44 | if self.psa_type == 0: # col 45 | output[n, :, h, w] = mask_com.view(-1) 46 | else: # dis 47 | c = h * feature_W_ + w 48 | output[n, c, :, :] = mask_com.view(feature_H_, feature_W_) 49 | if self.psa_type == 1: # dis 50 | output = output.view(num_, feature_H_ * feature_W_, feature_H_ * feature_W_).transpose(1, 2).view(num_, feature_H_ * feature_W_, feature_H_, feature_W_) 51 | ''' 52 | # c/cuda implementation 53 | if not input.is_cuda: 54 | src.cpu.psamask_forward(self.psa_type, input, output, num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_) 55 | else: 56 | output = output.cuda() 57 | src.gpu.psamask_forward(self.psa_type, input, output, num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_) 58 | self.num_, self.channels_, self.feature_H_, self.feature_W_, self.mask_H_, self.mask_W_, self.half_mask_H_, self.half_mask_W_ = num_, channels_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_ 59 | return output 60 | 61 | def backward(self, grad_output): 62 | num_, channels_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_ = self.num_, self.channels_, self.feature_H_, self.feature_W_, self.mask_H_, self.mask_W_, self.half_mask_H_, self.half_mask_W_ 63 | grad_input = torch.zeros([num_, channels_, feature_H_, feature_W_], dtype=grad_output.dtype, device=grad_output.device) 64 | ''' python implementation - slow 65 | if self.psa_type == 1: # dis 66 | grad_output = grad_output.view(num_, feature_H_ * feature_W_, feature_H_ * feature_W_).transpose(1, 2).view(num_, feature_H_ * feature_W_, feature_H_, feature_W_) 67 | for n in range(num_): 68 | for h in range(feature_H_): 69 | for w in range(feature_W_): 70 | hstart = max(0, half_mask_H_ - h) 71 | hend = min(mask_H_, feature_H_ + half_mask_H_ - h) 72 | wstart = max(0, half_mask_W_ - w) 73 | wend = min(mask_W_, feature_W_ + half_mask_W_ - w) 74 | hstart_com = max(0, h - half_mask_H_) 75 | hend_com = min(feature_H_, h + half_mask_H_ + 1) 76 | wstart_com = max(0, w - half_mask_W_) 77 | wend_com = min(feature_W_, w + half_mask_W_ + 1) 78 | if self.psa_type == 0: # col 79 | grad_mask_com = grad_output[n, :, h, w].view(feature_H_, feature_W_) 80 | else: # dis 81 | c = h * feature_W_ + w 82 | grad_mask_com = grad_output[n, c, :, :].view(feature_H_, feature_W_) 83 | grad_mask_ori = torch.zeros(mask_H_, mask_W_, dtype=grad_output.dtype, device=grad_output.device) 84 | grad_mask_ori[hstart:hend, wstart:wend] = grad_mask_com[hstart_com:hend_com, wstart_com:wend_com] 85 | grad_input[n, :, h, w] = grad_mask_ori.view(-1) 86 | ''' 87 | # c/cuda implementation 88 | if not grad_output.is_cuda: 89 | src.cpu.psamask_backward(self.psa_type, grad_output, grad_input, num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_) 90 | else: 91 | src.gpu.psamask_backward(self.psa_type, grad_output, grad_input, num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_) 92 | return grad_input 93 | -------------------------------------------------------------------------------- /lib/psa/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .psamask import * 2 | -------------------------------------------------------------------------------- /lib/psa/modules/psamask.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | from .. import functional as F 3 | 4 | 5 | class PSAMask(nn.Module): 6 | def __init__(self, psa_type=0, mask_H_=None, mask_W_=None): 7 | super(PSAMask, self).__init__() 8 | assert psa_type in [0, 1] # 0-col, 1-dis 9 | assert (mask_H_ in None and mask_W_ is None) or (mask_H_ is not None and mask_W_ is not None) 10 | self.psa_type = psa_type 11 | self.mask_H_ = mask_H_ 12 | self.mask_W_ = mask_W_ 13 | 14 | def forward(self, input): 15 | return F.psa_mask(input, self.psa_type, self.mask_H_, self.mask_W_) 16 | -------------------------------------------------------------------------------- /lib/psa/src/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | from torch.utils.cpp_extension import load 4 | 5 | cwd = os.path.dirname(os.path.realpath(__file__)) 6 | cpu_path = os.path.join(cwd, 'cpu') 7 | gpu_path = os.path.join(cwd, 'gpu') 8 | 9 | cpu = load('psamask_cpu', [ 10 | os.path.join(cpu_path, 'operator.cpp'), 11 | os.path.join(cpu_path, 'psamask.cpp'), 12 | ], build_directory=cpu_path, verbose=False) 13 | 14 | if torch.cuda.is_available(): 15 | gpu = load('psamask_gpu', [ 16 | os.path.join(gpu_path, 'operator.cpp'), 17 | os.path.join(gpu_path, 'psamask_cuda.cu'), 18 | ], build_directory=gpu_path, verbose=False) -------------------------------------------------------------------------------- /lib/psa/src/cpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("psamask_forward", &psamask_forward_cpu, "PSAMASK forward (CPU)"); 5 | m.def("psamask_backward", &psamask_backward_cpu, "PSAMASK backward (CPU)"); 6 | } 7 | -------------------------------------------------------------------------------- /lib/psa/src/cpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void psamask_forward_cpu(const int psa_type, const at::Tensor& input, at::Tensor& output, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_); 4 | void psamask_backward_cpu(const int psa_type, const at::Tensor& grad_output, at::Tensor& grad_input, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_); -------------------------------------------------------------------------------- /lib/psa/src/cpu/psamask.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef min 4 | #define min(a,b) (((a) < (b)) ? (a) : (b)) 5 | #endif 6 | 7 | #ifndef max 8 | #define max(a,b) (((a) > (b)) ? (a) : (b)) 9 | #endif 10 | 11 | void psamask_collect_forward(const int num_, 12 | const int feature_H_, const int feature_W_, 13 | const int mask_H_, const int mask_W_, 14 | const int half_mask_H_, const int half_mask_W_, 15 | const float* mask_data, float* buffer_data) { 16 | for(int n = 0; n < num_; n++) { 17 | for(int h = 0; h < feature_H_; h++) { 18 | for(int w = 0; w < feature_W_; w++) { 19 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 20 | const int hstart = max(0, half_mask_H_ - h); 21 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 22 | const int wstart = max(0, half_mask_W_ - w); 23 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 24 | // (hidx, widx ) with mask-indexed 25 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 26 | for (int hidx = hstart; hidx < hend; hidx++) { 27 | for (int widx = wstart; widx < wend; widx++) { 28 | buffer_data[(n * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)) * feature_H_ * feature_W_ + h * feature_W_ + w] = 29 | mask_data[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w]; 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | void psamask_distribute_forward(const int num_, 38 | const int feature_H_, const int feature_W_, 39 | const int mask_H_, const int mask_W_, 40 | const int half_mask_H_, const int half_mask_W_, 41 | const float* mask_data, float* buffer_data) { 42 | for(int n = 0; n < num_; n++) { 43 | for(int h = 0; h < feature_H_; h++) { 44 | for(int w = 0; w < feature_W_; w++) { 45 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 46 | const int hstart = max(0, half_mask_H_ - h); 47 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 48 | const int wstart = max(0, half_mask_W_ - w); 49 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 50 | // (hidx, widx ) with mask-indexed 51 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 52 | for (int hidx = hstart; hidx < hend; hidx++) { 53 | for (int widx = wstart; widx < wend; widx++) { 54 | buffer_data[(n * feature_H_ * feature_W_ + h * feature_W_ + w) * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)] = 55 | mask_data[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w]; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | void psamask_collect_backward(const int num_, 64 | const int feature_H_, const int feature_W_, 65 | const int mask_H_, const int mask_W_, 66 | const int half_mask_H_, const int half_mask_W_, 67 | const float* buffer_diff, float* mask_diff) { 68 | for(int n = 0; n < num_; n++) { 69 | for(int h = 0; h < feature_H_; h++) { 70 | for(int w = 0; w < feature_W_; w++) { 71 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 72 | const int hstart = max(0, half_mask_H_ - h); 73 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 74 | const int wstart = max(0, half_mask_W_ - w); 75 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 76 | // (hidx, widx ) with mask-indexed 77 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 78 | for (int hidx = hstart; hidx < hend; hidx++) { 79 | for (int widx = wstart; widx < wend; widx++) { 80 | mask_diff[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w] = 81 | buffer_diff[(n * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)) * feature_H_ * feature_W_ + h * feature_W_ + w]; 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | void psamask_distribute_backward(const int num_, 90 | const int feature_H_, const int feature_W_, 91 | const int mask_H_, const int mask_W_, 92 | const int half_mask_H_, const int half_mask_W_, 93 | const float* buffer_diff, float* mask_diff) { 94 | for(int n = 0; n < num_; n++) { 95 | for(int h = 0; h < feature_H_; h++) { 96 | for(int w = 0; w < feature_W_; w++) { 97 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 98 | const int hstart = max(0, half_mask_H_ - h); 99 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 100 | const int wstart = max(0, half_mask_W_ - w); 101 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 102 | // (hidx, widx ) with mask-indexed 103 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 104 | for (int hidx = hstart; hidx < hend; hidx++) { 105 | for (int widx = wstart; widx < wend; widx++) { 106 | mask_diff[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w] = 107 | buffer_diff[(n * feature_H_ * feature_W_ + h * feature_W_ + w) * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)]; 108 | } 109 | } 110 | } 111 | } 112 | } 113 | } 114 | 115 | void psamask_forward_cpu(const int psa_type, const at::Tensor& input, at::Tensor& output, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_) 116 | { 117 | const float* input_data = input.data(); 118 | float* output_data = output.data(); 119 | if(psa_type == 0) 120 | psamask_collect_forward(num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, input_data, output_data); 121 | else 122 | psamask_distribute_forward(num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, input_data, output_data); 123 | } 124 | 125 | void psamask_backward_cpu(const int psa_type, const at::Tensor& grad_output, at::Tensor& grad_input, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_) 126 | { 127 | const float* grad_output_data = grad_output.data(); 128 | float* grad_input_data = grad_input.data(); 129 | if(psa_type == 0) 130 | psamask_collect_backward(num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, grad_output_data, grad_input_data); 131 | else 132 | psamask_distribute_backward(num_, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, grad_output_data, grad_input_data); 133 | } 134 | -------------------------------------------------------------------------------- /lib/psa/src/gpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("psamask_forward", &psamask_forward_cuda, "PSAMASK forward (GPU)"); 5 | m.def("psamask_backward", &psamask_backward_cuda, "PSAMASK backward (GPU)"); 6 | } 7 | -------------------------------------------------------------------------------- /lib/psa/src/gpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void psamask_forward_cuda(const int psa_type, const at::Tensor& input, at::Tensor& output, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_); 4 | void psamask_backward_cuda(const int psa_type, const at::Tensor& grad_output, at::Tensor& grad_input, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_); 5 | -------------------------------------------------------------------------------- /lib/psa/src/gpu/psamask_cuda.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // CUDA: grid stride looping 4 | #ifndef CUDA_KERNEL_LOOP 5 | #define CUDA_KERNEL_LOOP(i, n) for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < (n); i += blockDim.x * gridDim.x) 6 | #endif 7 | 8 | __global__ void psamask_collect_forward_cuda(const int nthreads, 9 | const int feature_H_, const int feature_W_, 10 | const int mask_H_, const int mask_W_, 11 | const int half_mask_H_, const int half_mask_W_, 12 | const float* mask_data, float* buffer_data) { 13 | CUDA_KERNEL_LOOP(index, nthreads) { 14 | const int w = index % feature_W_; 15 | const int h = (index / feature_W_) % feature_H_; 16 | const int n = index / feature_W_ / feature_H_; 17 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 18 | const int hstart = max(0, half_mask_H_ - h); 19 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 20 | const int wstart = max(0, half_mask_W_ - w); 21 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 22 | // (hidx, widx ) with mask-indexed 23 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 24 | for (int hidx = hstart; hidx < hend; hidx++) { 25 | for (int widx = wstart; widx < wend; widx++) { 26 | buffer_data[(n * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)) * feature_H_ * feature_W_ + h * feature_W_ + w] = 27 | mask_data[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w]; 28 | } 29 | } 30 | } 31 | } 32 | 33 | __global__ void psamask_distribute_forward_cuda(const int nthreads, 34 | const int feature_H_, const int feature_W_, 35 | const int mask_H_, const int mask_W_, 36 | const int half_mask_H_, const int half_mask_W_, 37 | const float* mask_data, float* buffer_data) { 38 | CUDA_KERNEL_LOOP(index, nthreads) { 39 | const int w = index % feature_W_; 40 | const int h = (index / feature_W_) % feature_H_; 41 | const int n = index / feature_W_ / feature_H_; 42 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 43 | const int hstart = max(0, half_mask_H_ - h); 44 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 45 | const int wstart = max(0, half_mask_W_ - w); 46 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 47 | // (hidx, widx ) with mask-indexed 48 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 49 | for (int hidx = hstart; hidx < hend; hidx++) { 50 | for (int widx = wstart; widx < wend; widx++) { 51 | buffer_data[(n * feature_H_ * feature_W_ + h * feature_W_ + w) * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)] = 52 | mask_data[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w]; 53 | } 54 | } 55 | } 56 | } 57 | 58 | __global__ void psamask_collect_backward_cuda(const int nthreads, 59 | const int feature_H_, const int feature_W_, 60 | const int mask_H_, const int mask_W_, 61 | const int half_mask_H_, const int half_mask_W_, 62 | const float* buffer_diff, float* mask_diff) { 63 | CUDA_KERNEL_LOOP(index, nthreads) { 64 | const int w = index % feature_W_; 65 | const int h = (index / feature_W_) % feature_H_; 66 | const int n = index / feature_W_ / feature_H_; 67 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 68 | const int hstart = max(0, half_mask_H_ - h); 69 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 70 | const int wstart = max(0, half_mask_W_ - w); 71 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 72 | // (hidx, widx ) with mask-indexed 73 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 74 | for (int hidx = hstart; hidx < hend; hidx++) { 75 | for (int widx = wstart; widx < wend; widx++) { 76 | mask_diff[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w] = 77 | buffer_diff[(n * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)) * feature_H_ * feature_W_ + h * feature_W_ + w]; 78 | } 79 | } 80 | } 81 | } 82 | 83 | __global__ void psamask_distribute_backward_cuda(const int nthreads, 84 | const int feature_H_, const int feature_W_, 85 | const int mask_H_, const int mask_W_, 86 | const int half_mask_H_, const int half_mask_W_, 87 | const float* buffer_diff, float* mask_diff) { 88 | CUDA_KERNEL_LOOP(index, nthreads) { 89 | const int w = index % feature_W_; 90 | const int h = (index / feature_W_) % feature_H_; 91 | const int n = index / feature_W_ / feature_H_; 92 | // effective mask region : [hstart, hend) x [wstart, wend) with mask-indexed 93 | const int hstart = max(0, half_mask_H_ - h); 94 | const int hend = min(mask_H_, feature_H_ + half_mask_H_ - h); 95 | const int wstart = max(0, half_mask_W_ - w); 96 | const int wend = min(mask_W_, feature_W_ + half_mask_W_ - w); 97 | // (hidx, widx ) with mask-indexed 98 | // (hidx + h - half_mask_H_, widx + w - half_mask_W_) with feature-indexed 99 | for (int hidx = hstart; hidx < hend; hidx++) { 100 | for (int widx = wstart; widx < wend; widx++) { 101 | mask_diff[((n * mask_H_ * mask_W_ + hidx * mask_W_ + widx) * feature_H_ + h) * feature_W_ + w] = 102 | buffer_diff[(n * feature_H_ * feature_W_ + h * feature_W_ + w) * feature_H_ * feature_W_ + (hidx + h - half_mask_H_) * feature_W_ + (widx + w - half_mask_W_)]; 103 | } 104 | } 105 | } 106 | } 107 | 108 | void psamask_forward_cuda(const int psa_type, const at::Tensor& input, at::Tensor& output, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_) 109 | { 110 | int nthreads = num_ * feature_H_ * feature_W_; 111 | const float* input_data = input.data(); 112 | float* output_data = output.data(); 113 | if(psa_type == 0) 114 | psamask_collect_forward_cuda<<>>(nthreads, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, input_data, output_data); 115 | else 116 | psamask_distribute_forward_cuda<<>>(nthreads, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, input_data, output_data); 117 | } 118 | 119 | void psamask_backward_cuda(const int psa_type, const at::Tensor& grad_output, at::Tensor& grad_input, const int num_, const int feature_H_, const int feature_W_, const int mask_H_, const int mask_W_, const int half_mask_H_, const int half_mask_W_) 120 | { 121 | int nthreads = num_ * feature_H_ * feature_W_; 122 | const float* grad_output_data = grad_output.data(); 123 | float* grad_input_data = grad_input.data(); 124 | if(psa_type == 0) 125 | psamask_collect_backward_cuda<<>>(nthreads, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, grad_output_data, grad_input_data); 126 | else 127 | psamask_distribute_backward_cuda<<>>(nthreads, feature_H_, feature_W_, mask_H_, mask_W_, half_mask_H_, half_mask_W_, grad_output_data, grad_input_data); 128 | } 129 | -------------------------------------------------------------------------------- /lib/sync_bn/functions/__init__.py: -------------------------------------------------------------------------------- 1 | from .sync_bn import * 2 | -------------------------------------------------------------------------------- /lib/sync_bn/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .sync_bn import * 2 | -------------------------------------------------------------------------------- /lib/sync_bn/modules/sync_bn.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Hang Zhang 3 | ## ECE Department, Rutgers University 4 | ## Email: zhang.hang@rutgers.edu 5 | ## Copyright (c) 2017 6 | ## 7 | ## This source code is licensed under the MIT-style license found in the 8 | ## LICENSE file in the root directory of this source tree 9 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 | 11 | """Synchronized Cross-GPU Batch Normalization Module""" 12 | import warnings 13 | try: 14 | from queue import Queue 15 | except ImportError: 16 | from Queue import Queue 17 | 18 | import torch 19 | from torch.nn.modules.batchnorm import _BatchNorm 20 | 21 | from ..functions import * 22 | 23 | 24 | __all__ = ['SyncBatchNorm', 'BatchNorm1d', 'BatchNorm2d', 'BatchNorm3d'] 25 | 26 | 27 | class SyncBatchNorm(_BatchNorm): 28 | r"""Cross-GPU Synchronized Batch normalization (SyncBN) 29 | 30 | Standard BN [1]_ implementation only normalize the data within each device (GPU). 31 | SyncBN normalizes the input within the whole mini-batch. 32 | We follow the sync-onece implmentation described in the paper [2]_ . 33 | Please see the design idea in the `notes <./notes/syncbn.html>`_. 34 | 35 | .. math:: 36 | 37 | y = \frac{x - mean[x]}{ \sqrt{Var[x] + \epsilon}} * gamma + beta 38 | 39 | The mean and standard-deviation are calculated per-channel over 40 | the mini-batches and gamma and beta are learnable parameter vectors 41 | of size C (where C is the input size). 42 | 43 | During training, this layer keeps a running estimate of its computed mean 44 | and variance. The running sum is kept with a default momentum of 0.1. 45 | 46 | During evaluation, this running mean/variance is used for normalization. 47 | 48 | Because the BatchNorm is done over the `C` dimension, computing statistics 49 | on `(N, H, W)` slices, it's common terminology to call this Spatial BatchNorm 50 | 51 | Args: 52 | num_features: num_features from an expected input of 53 | size batch_size x num_features x height x width 54 | eps: a value added to the denominator for numerical stability. 55 | Default: 1e-5 56 | momentum: the value used for the running_mean and running_var 57 | computation. Default: 0.1 58 | sync: a boolean value that when set to ``True``, synchronize across 59 | different gpus. Default: ``True`` 60 | activation : str 61 | Name of the activation functions, one of: `leaky_relu` or `none`. 62 | slope : float 63 | Negative slope for the `leaky_relu` activation. 64 | 65 | Shape: 66 | - Input: :math:`(N, C, H, W)` 67 | - Output: :math:`(N, C, H, W)` (same shape as input) 68 | 69 | Reference: 70 | .. [1] Ioffe, Sergey, and Christian Szegedy. "Batch normalization: Accelerating deep network training by reducing internal covariate shift." *ICML 2015* 71 | .. [2] Hang Zhang, Kristin Dana, Jianping Shi, Zhongyue Zhang, Xiaogang Wang, Ambrish Tyagi, and Amit Agrawal. "Context Encoding for Semantic Segmentation." *CVPR 2018* 72 | 73 | Examples: 74 | >>> m = SyncBatchNorm(100) 75 | >>> net = torch.nn.DataParallel(m) 76 | >>> output = net(input) 77 | """ 78 | 79 | def __init__(self, num_features, eps=1e-5, momentum=0.1, sync=True, activation="none", slope=0.01, 80 | inplace=True): 81 | super(SyncBatchNorm, self).__init__(num_features, eps=eps, momentum=momentum, affine=True) 82 | self.activation = activation 83 | self.inplace = False if activation == 'none' else inplace 84 | #self.inplace = inplace 85 | self.slope = slope 86 | self.devices = list(range(torch.cuda.device_count())) 87 | self.sync = sync if len(self.devices) > 1 else False 88 | # Initialize queues 89 | self.worker_ids = self.devices[1:] 90 | self.master_queue = Queue(len(self.worker_ids)) 91 | self.worker_queues = [Queue(1) for _ in self.worker_ids] 92 | # running_exs 93 | #self.register_buffer('running_exs', torch.ones(num_features)) 94 | 95 | def forward(self, x): 96 | # Resize the input to (B, C, -1). 97 | input_shape = x.size() 98 | x = x.view(input_shape[0], self.num_features, -1) 99 | if x.get_device() == self.devices[0]: 100 | # Master mode 101 | extra = { 102 | "is_master": True, 103 | "master_queue": self.master_queue, 104 | "worker_queues": self.worker_queues, 105 | "worker_ids": self.worker_ids 106 | } 107 | else: 108 | # Worker mode 109 | extra = { 110 | "is_master": False, 111 | "master_queue": self.master_queue, 112 | "worker_queue": self.worker_queues[self.worker_ids.index(x.get_device())] 113 | } 114 | if self.inplace: 115 | return inp_syncbatchnorm(x, self.weight, self.bias, self.running_mean, self.running_var, 116 | extra, self.sync, self.training, self.momentum, self.eps, 117 | self.activation, self.slope).view(input_shape) 118 | else: 119 | return syncbatchnorm(x, self.weight, self.bias, self.running_mean, self.running_var, 120 | extra, self.sync, self.training, self.momentum, self.eps, 121 | self.activation, self.slope).view(input_shape) 122 | 123 | def extra_repr(self): 124 | if self.activation == 'none': 125 | return 'sync={}'.format(self.sync) 126 | else: 127 | return 'sync={}, act={}, slope={}, inplace={}'.format( 128 | self.sync, self.activation, self.slope, self.inplace 129 | ) 130 | 131 | class BatchNorm1d(SyncBatchNorm): 132 | r""" 133 | .. warning:: 134 | BatchNorm1d is deprecated in favor of :class:`encoding.nn.SyncBatchNorm`. 135 | """ 136 | def __init__(self, *args, **kwargs): 137 | super(BatchNorm1d, self).__init__(*args, **kwargs) 138 | 139 | class BatchNorm2d(SyncBatchNorm): 140 | r""" 141 | .. warning:: 142 | BatchNorm2d is deprecated in favor of :class:`encoding.nn.SyncBatchNorm`. 143 | """ 144 | def __init__(self, *args, **kwargs): 145 | super(BatchNorm2d, self).__init__(*args, **kwargs) 146 | 147 | class BatchNorm3d(SyncBatchNorm): 148 | r""" 149 | .. warning:: 150 | BatchNorm3d is deprecated in favor of :class:`encoding.nn.SyncBatchNorm`. 151 | """ 152 | def __init__(self, *args, **kwargs): 153 | super(BatchNorm3d, self).__init__(*args, **kwargs) 154 | -------------------------------------------------------------------------------- /lib/sync_bn/src/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | from torch.utils.cpp_extension import load 4 | 5 | cwd = os.path.dirname(os.path.realpath(__file__)) 6 | cpu_path = os.path.join(cwd, 'cpu') 7 | gpu_path = os.path.join(cwd, 'gpu') 8 | 9 | cpu = load('sync_bn_cpu', [ 10 | os.path.join(cpu_path, 'operator.cpp'), 11 | os.path.join(cpu_path, 'sync_bn.cpp'), 12 | ], build_directory=cpu_path, verbose=False) 13 | 14 | if torch.cuda.is_available(): 15 | gpu = load('sync_bn_gpu', [ 16 | os.path.join(gpu_path, 'operator.cpp'), 17 | os.path.join(gpu_path, 'sync_bn_cuda.cu'), 18 | ], build_directory=gpu_path, verbose=False) 19 | -------------------------------------------------------------------------------- /lib/sync_bn/src/cpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("batchnorm_forward", &BatchNorm_Forward_CPU, "BatchNorm forward (CPU)"); 5 | m.def("batchnorm_backward", &BatchNorm_Backward_CPU, "BatchNorm backward (CPU)"); 6 | m.def("sumsquare_forward", &Sum_Square_Forward_CPU, "SumSqu forward (CPU)"); 7 | m.def("sumsquare_backward", &Sum_Square_Backward_CPU, "SumSqu backward (CPU)"); 8 | } 9 | -------------------------------------------------------------------------------- /lib/sync_bn/src/cpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | at::Tensor BatchNorm_Forward_CPU( 5 | const at::Tensor input_, 6 | const at::Tensor mean_, 7 | const at::Tensor std_, 8 | const at::Tensor gamma_, 9 | const at::Tensor beta_); 10 | 11 | std::vector BatchNorm_Backward_CPU( 12 | const at::Tensor gradoutput_, 13 | const at::Tensor input_, 14 | const at::Tensor mean_, 15 | const at::Tensor std_, 16 | const at::Tensor gamma_, 17 | const at::Tensor beta_, 18 | bool train); 19 | 20 | std::vector Sum_Square_Forward_CPU( 21 | const at::Tensor input_); 22 | 23 | at::Tensor Sum_Square_Backward_CPU( 24 | const at::Tensor input_, 25 | const at::Tensor gradSum_, 26 | const at::Tensor gradSquare_); 27 | -------------------------------------------------------------------------------- /lib/sync_bn/src/cpu/sync_bn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 6 | if (x.ndimension() == 2) { 7 | return v; 8 | } else { 9 | std::vector broadcast_size = {1, -1}; 10 | for (int64_t i = 2; i < x.ndimension(); ++i) 11 | broadcast_size.push_back(1); 12 | 13 | return v.view(broadcast_size); 14 | } 15 | } 16 | 17 | at::Tensor BatchNorm_Forward_CPU( 18 | const at::Tensor input, 19 | const at::Tensor mean, 20 | const at::Tensor std, 21 | const at::Tensor gamma, 22 | const at::Tensor beta) { 23 | auto output = (input - broadcast_to(mean, input)) / broadcast_to(std, input); 24 | output = output * broadcast_to(gamma, input) + broadcast_to(beta, input); 25 | return output; 26 | } 27 | 28 | // Not implementing CPU backward for now 29 | std::vector BatchNorm_Backward_CPU( 30 | const at::Tensor gradoutput, 31 | const at::Tensor input, 32 | const at::Tensor mean, 33 | const at::Tensor std, 34 | const at::Tensor gamma, 35 | const at::Tensor beta, 36 | bool train) { 37 | /* outputs*/ 38 | at::Tensor gradinput = at::zeros_like(input); 39 | at::Tensor gradgamma = at::zeros_like(gamma); 40 | at::Tensor gradbeta = at::zeros_like(beta); 41 | at::Tensor gradMean = at::zeros_like(mean); 42 | at::Tensor gradStd = at::zeros_like(std); 43 | return {gradinput, gradMean, gradStd, gradgamma, gradbeta}; 44 | } 45 | 46 | std::vector Sum_Square_Forward_CPU( 47 | const at::Tensor input) { 48 | /* outputs */ 49 | at::Tensor sum = torch::zeros({input.size(1)}, input.options()); 50 | at::Tensor square = torch::zeros({input.size(1)}, input.options()); 51 | return {sum, square}; 52 | } 53 | 54 | at::Tensor Sum_Square_Backward_CPU( 55 | const at::Tensor input, 56 | const at::Tensor gradSum, 57 | const at::Tensor gradSquare) { 58 | /* outputs */ 59 | at::Tensor gradInput = at::zeros_like(input); 60 | return gradInput; 61 | } 62 | -------------------------------------------------------------------------------- /lib/sync_bn/src/gpu/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static const unsigned WARP_SIZE = 32; 5 | 6 | // The maximum number of threads in a block 7 | static const unsigned MAX_BLOCK_SIZE = 512U; 8 | 9 | template 10 | struct ScalarConvert { 11 | static __host__ __device__ __forceinline__ Out to(const In v) { return (Out) v; } 12 | }; 13 | 14 | // Number of threads in a block given an input size up to MAX_BLOCK_SIZE 15 | static int getNumThreads(int nElem) { 16 | int threadSizes[5] = { 32, 64, 128, 256, MAX_BLOCK_SIZE }; 17 | for (int i = 0; i != 5; ++i) { 18 | if (nElem <= threadSizes[i]) { 19 | return threadSizes[i]; 20 | } 21 | } 22 | return MAX_BLOCK_SIZE; 23 | } 24 | 25 | // Returns the index of the most significant 1 bit in `val`. 26 | __device__ __forceinline__ int getMSB(int val) { 27 | return 31 - __clz(val); 28 | } 29 | 30 | template 31 | __device__ __forceinline__ T WARP_SHFL_XOR(T value, int laneMask, int width = warpSize, unsigned int mask = 0xffffffff) 32 | { 33 | #if CUDA_VERSION >= 9000 34 | return __shfl_xor_sync(mask, value, laneMask, width); 35 | #else 36 | return __shfl_xor(value, laneMask, width); 37 | #endif 38 | } 39 | 40 | // Sum across all threads within a warp 41 | template 42 | static __device__ __forceinline__ T warpSum(T val) { 43 | #if __CUDA_ARCH__ >= 300 44 | for (int i = 0; i < getMSB(WARP_SIZE); ++i) { 45 | val += WARP_SHFL_XOR(val, 1 << i, WARP_SIZE); 46 | } 47 | #else 48 | __shared__ T values[MAX_BLOCK_SIZE]; 49 | values[threadIdx.x] = val; 50 | __threadfence_block(); 51 | const int base = (threadIdx.x / WARP_SIZE) * WARP_SIZE; 52 | for (int i = 1; i < WARP_SIZE; i++) { 53 | val += values[base + ((i + threadIdx.x) % WARP_SIZE)]; 54 | } 55 | #endif 56 | return val; 57 | } 58 | 59 | template 60 | struct Float2 { 61 | Acctype v1, v2; 62 | __device__ Float2() {} 63 | __device__ Float2(DType v1, DType v2) : v1(ScalarConvert::to(v1)), v2(ScalarConvert::to(v2)) {} 64 | __device__ Float2(DType v) : v1(ScalarConvert::to(v)), v2(ScalarConvert::to(v)) {} 65 | __device__ Float2(int v) : v1(ScalarConvert::to(v)), v2(ScalarConvert::to(v)) {} 66 | __device__ Float2& operator+=(const Float2& a) { 67 | v1 += a.v1; 68 | v2 += a.v2; 69 | return *this; 70 | } 71 | }; 72 | 73 | template 74 | static __device__ __forceinline__ Float2 warpSum(Float2 value) { 75 | value.v1 = warpSum(value.v1); 76 | value.v2 = warpSum(value.v2); 77 | return value; 78 | } 79 | 80 | template 81 | __device__ T reduceD( 82 | Op op, int b, int i, int k, int D) { 83 | T sum = 0; 84 | for (int x = threadIdx.x; x < D; x += blockDim.x) { 85 | sum += op(b,i,k,x); 86 | } 87 | // sum over NumThreads within a warp 88 | sum = warpSum(sum); 89 | 90 | // 'transpose', and reduce within warp again 91 | __shared__ T shared[32]; 92 | 93 | __syncthreads(); 94 | if (threadIdx.x % WARP_SIZE == 0) { 95 | if (threadIdx.x / WARP_SIZE < 32) { 96 | shared[threadIdx.x / WARP_SIZE] = sum; 97 | } 98 | } 99 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 100 | // zero out the other entries in shared 101 | shared[threadIdx.x] = (T) 0; 102 | } 103 | __syncthreads(); 104 | if (threadIdx.x / WARP_SIZE == 0) { 105 | sum = warpSum(shared[threadIdx.x]); 106 | if (threadIdx.x == 0) { 107 | shared[0] = sum; 108 | } 109 | } 110 | __syncthreads(); 111 | 112 | // Everyone picks it up, should be broadcast into the whole gradInput 113 | return shared[0]; 114 | } 115 | 116 | template 117 | __device__ T reduceN( 118 | Op op, int b, int k, int d, int N) { 119 | T sum = 0; 120 | for (int x = threadIdx.x; x < N; x += blockDim.x) { 121 | sum += op(b,x,k,d); 122 | } 123 | // sum over NumThreads within a warp 124 | sum = warpSum(sum); 125 | 126 | // 'transpose', and reduce within warp again 127 | __shared__ T shared[32]; 128 | 129 | __syncthreads(); 130 | if (threadIdx.x % WARP_SIZE == 0) { 131 | if (threadIdx.x / WARP_SIZE < 32) { 132 | shared[threadIdx.x / WARP_SIZE] = sum; 133 | } 134 | } 135 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 136 | // zero out the other entries in shared 137 | shared[threadIdx.x] = (T) 0; 138 | } 139 | __syncthreads(); 140 | if (threadIdx.x / WARP_SIZE == 0) { 141 | sum = warpSum(shared[threadIdx.x]); 142 | if (threadIdx.x == 0) { 143 | shared[0] = sum; 144 | } 145 | } 146 | __syncthreads(); 147 | 148 | // Everyone picks it up, should be broadcast into the whole gradInput 149 | return shared[0]; 150 | } 151 | 152 | template 153 | __device__ T reduceK( 154 | Op op, int b, int i, int d, int K) { 155 | T sum = 0; 156 | for (int x = threadIdx.x; x < K; x += blockDim.x) { 157 | sum += op(b,i,x,d); 158 | } 159 | // sum over NumThreads within a warp 160 | sum = warpSum(sum); 161 | 162 | // 'transpose', and reduce within warp again 163 | __shared__ T shared[32]; 164 | 165 | __syncthreads(); 166 | if (threadIdx.x % WARP_SIZE == 0) { 167 | if (threadIdx.x / WARP_SIZE < 32) { 168 | shared[threadIdx.x / WARP_SIZE] = sum; 169 | } 170 | } 171 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 172 | // zero out the other entries in shared 173 | shared[threadIdx.x] = (T) 0; 174 | } 175 | __syncthreads(); 176 | if (threadIdx.x / WARP_SIZE == 0) { 177 | sum = warpSum(shared[threadIdx.x]); 178 | if (threadIdx.x == 0) { 179 | shared[0] = sum; 180 | } 181 | } 182 | __syncthreads(); 183 | 184 | // Everyone picks it up, should be broadcast into the whole gradInput 185 | return shared[0]; 186 | } 187 | 188 | template 189 | __device__ T reduceBN( 190 | Op op, 191 | int k, int d, int B, int N) { 192 | T sum = 0; 193 | for (int batch = 0; batch < B; ++batch) { 194 | for (int x = threadIdx.x; x < N; x += blockDim.x) { 195 | sum += op(batch,x,k,d); 196 | } 197 | } 198 | // sum over NumThreads within a warp 199 | sum = warpSum(sum); 200 | // 'transpose', and reduce within warp again 201 | __shared__ T shared[32]; 202 | 203 | __syncthreads(); 204 | if (threadIdx.x % WARP_SIZE == 0) { 205 | if (threadIdx.x / WARP_SIZE < 32) { 206 | shared[threadIdx.x / WARP_SIZE] = sum; 207 | } 208 | } 209 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 210 | // zero out the other entries in shared 211 | shared[threadIdx.x] = (T) 0; 212 | } 213 | __syncthreads(); 214 | if (threadIdx.x / WARP_SIZE == 0) { 215 | sum = warpSum(shared[threadIdx.x]); 216 | if (threadIdx.x == 0) { 217 | shared[0] = sum; 218 | } 219 | } 220 | __syncthreads(); 221 | 222 | // Everyone picks it up, should be broadcast into the whole gradInput 223 | return shared[0]; 224 | } 225 | -------------------------------------------------------------------------------- /lib/sync_bn/src/gpu/device_tensor.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct DeviceTensor { 5 | public: 6 | inline __device__ __host__ DeviceTensor(DType *p, const int *size) 7 | : dptr_(p) { 8 | for (int i = 0; i < Dim; ++i) { 9 | size_[i] = size ? size[i] : 0; 10 | } 11 | } 12 | 13 | inline __device__ __host__ unsigned getSize(const int i) const { 14 | assert(i < Dim); 15 | return size_[i]; 16 | } 17 | 18 | inline __device__ __host__ int numElements() const { 19 | int n = 1; 20 | for (int i = 0; i < Dim; ++i) { 21 | n *= size_[i]; 22 | } 23 | return n; 24 | } 25 | 26 | inline __device__ __host__ DeviceTensor select(const size_t x) const { 27 | assert(Dim > 1); 28 | int offset = x; 29 | for (int i = 1; i < Dim; ++i) { 30 | offset *= size_[i]; 31 | } 32 | DeviceTensor tensor(dptr_ + offset, nullptr); 33 | for (int i = 0; i < Dim - 1; ++i) { 34 | tensor.size_[i] = this->size_[i+1]; 35 | } 36 | return tensor; 37 | } 38 | 39 | inline __device__ __host__ DeviceTensor operator[](const size_t x) const { 40 | assert(Dim > 1); 41 | int offset = x; 42 | for (int i = 1; i < Dim; ++i) { 43 | offset *= size_[i]; 44 | } 45 | DeviceTensor tensor(dptr_ + offset, nullptr); 46 | for (int i = 0; i < Dim - 1; ++i) { 47 | tensor.size_[i] = this->size_[i+1]; 48 | } 49 | return tensor; 50 | } 51 | 52 | inline __device__ __host__ size_t InnerSize() const { 53 | assert(Dim >= 3); 54 | size_t sz = 1; 55 | for (size_t i = 2; i < Dim; ++i) { 56 | sz *= size_[i]; 57 | } 58 | return sz; 59 | } 60 | 61 | inline __device__ __host__ size_t ChannelCount() const { 62 | assert(Dim >= 3); 63 | return size_[1]; 64 | } 65 | 66 | inline __device__ __host__ DType* data_ptr() const { 67 | return dptr_; 68 | } 69 | 70 | DType *dptr_; 71 | int size_[Dim]; 72 | }; 73 | 74 | template 75 | struct DeviceTensor { 76 | inline __device__ __host__ DeviceTensor(DType *p, const int *size) 77 | : dptr_(p) { 78 | size_[0] = size ? size[0] : 0; 79 | } 80 | 81 | inline __device__ __host__ unsigned getSize(const int i) const { 82 | assert(i == 0); 83 | return size_[0]; 84 | } 85 | 86 | inline __device__ __host__ int numElements() const { 87 | return size_[0]; 88 | } 89 | 90 | inline __device__ __host__ DType &operator[](const size_t x) const { 91 | return *(dptr_ + x); 92 | } 93 | 94 | inline __device__ __host__ DType* data_ptr() const { 95 | return dptr_; 96 | } 97 | 98 | DType *dptr_; 99 | int size_[1]; 100 | }; 101 | 102 | template 103 | static DeviceTensor devicetensor(const at::Tensor &blob) { 104 | DType *data = blob.data(); 105 | DeviceTensor tensor(data, nullptr); 106 | for (int i = 0; i < Dim; ++i) { 107 | tensor.size_[i] = blob.size(i); 108 | } 109 | return tensor; 110 | } 111 | -------------------------------------------------------------------------------- /lib/sync_bn/src/gpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("batchnorm_forward", &BatchNorm_Forward_CUDA, "BatchNorm forward (CUDA)"); 5 | m.def("batchnorm_inp_forward", &BatchNorm_Forward_Inp_CUDA, "BatchNorm forward (CUDA)"); 6 | m.def("batchnorm_backward", &BatchNorm_Backward_CUDA, "BatchNorm backward (CUDA)"); 7 | m.def("batchnorm_inp_backward", &BatchNorm_Inp_Backward_CUDA, "BatchNorm backward (CUDA)"); 8 | m.def("expectation_forward", &Expectation_Forward_CUDA, "Expectation forward (CUDA)"); 9 | m.def("expectation_backward", &Expectation_Backward_CUDA, "Expectation backward (CUDA)"); 10 | m.def("expectation_inp_backward", &Expectation_Inp_Backward_CUDA, 11 | "Inplace Expectation backward (CUDA)"); 12 | } 13 | -------------------------------------------------------------------------------- /lib/sync_bn/src/gpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | at::Tensor BatchNorm_Forward_CUDA( 5 | const at::Tensor input_, 6 | const at::Tensor mean_, 7 | const at::Tensor std_, 8 | const at::Tensor gamma_, 9 | const at::Tensor beta_, 10 | float eps); 11 | 12 | at::Tensor BatchNorm_Forward_Inp_CUDA( 13 | const at::Tensor input_, 14 | const at::Tensor ex_, 15 | const at::Tensor exs_, 16 | const at::Tensor gamma_, 17 | const at::Tensor beta_, 18 | float eps); 19 | 20 | std::vector BatchNorm_Backward_CUDA( 21 | const at::Tensor gradoutput_, 22 | const at::Tensor input_, 23 | const at::Tensor ex_, 24 | const at::Tensor exs_, 25 | const at::Tensor gamma_, 26 | const at::Tensor beta_, 27 | float eps); 28 | 29 | std::vector BatchNorm_Inp_Backward_CUDA( 30 | const at::Tensor gradoutput_, 31 | const at::Tensor output_, 32 | const at::Tensor ex_, 33 | const at::Tensor exs_, 34 | const at::Tensor gamma_, 35 | const at::Tensor beta_, 36 | float eps); 37 | 38 | std::vector Expectation_Forward_CUDA( 39 | const at::Tensor input_); 40 | 41 | at::Tensor Expectation_Backward_CUDA( 42 | const at::Tensor input_, 43 | const at::Tensor gradEx_, 44 | const at::Tensor gradExs_); 45 | 46 | at::Tensor Expectation_Inp_Backward_CUDA( 47 | const at::Tensor gradInput_, 48 | const at::Tensor output_, 49 | const at::Tensor gradEx_, 50 | const at::Tensor gradExs_, 51 | const at::Tensor ex_, 52 | const at::Tensor exs_, 53 | const at::Tensor gamma_, 54 | const at::Tensor beta_, 55 | float eps); 56 | -------------------------------------------------------------------------------- /model/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/model/.DS_Store -------------------------------------------------------------------------------- /model/psanet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | import torch.nn.functional as F 4 | 5 | import lib.psa.functional as PF 6 | import model.resnet as models 7 | 8 | 9 | class PSA(nn.Module): 10 | def __init__(self, in_channels=2048, mid_channels=512, psa_type=2, compact=False, shrink_factor=2, mask_h=59, 11 | mask_w=59, normalization_factor=1.0, psa_softmax=True, BatchNorm=nn.BatchNorm2d): 12 | super(PSA, self).__init__() 13 | assert psa_type in [0, 1, 2] 14 | self.psa_type = psa_type 15 | self.compact = compact 16 | self.shrink_factor = shrink_factor 17 | self.mask_h = mask_h 18 | self.mask_w = mask_w 19 | self.psa_softmax = psa_softmax 20 | if normalization_factor is None: 21 | normalization_factor = mask_h * mask_w 22 | self.normalization_factor = normalization_factor 23 | 24 | self.reduce = nn.Sequential( 25 | nn.Conv2d(in_channels, mid_channels, kernel_size=1, bias=False), 26 | BatchNorm(mid_channels), 27 | nn.ReLU(inplace=True) 28 | ) 29 | self.attention = nn.Sequential( 30 | nn.Conv2d(mid_channels, mid_channels, kernel_size=1, bias=False), 31 | BatchNorm(mid_channels), 32 | nn.ReLU(inplace=True), 33 | nn.Conv2d(mid_channels, mask_h*mask_w, kernel_size=1, bias=False), 34 | ) 35 | if psa_type == 2: 36 | self.reduce_p = nn.Sequential( 37 | nn.Conv2d(in_channels, mid_channels, kernel_size=1, bias=False), 38 | BatchNorm(mid_channels), 39 | nn.ReLU(inplace=True) 40 | ) 41 | self.attention_p = nn.Sequential( 42 | nn.Conv2d(mid_channels, mid_channels, kernel_size=1, bias=False), 43 | BatchNorm(mid_channels), 44 | nn.ReLU(inplace=True), 45 | nn.Conv2d(mid_channels, mask_h*mask_w, kernel_size=1, bias=False), 46 | ) 47 | self.proj = nn.Sequential( 48 | nn.Conv2d(mid_channels * (2 if psa_type == 2 else 1), in_channels, kernel_size=1, bias=False), 49 | BatchNorm(in_channels), 50 | nn.ReLU(inplace=True) 51 | ) 52 | 53 | def forward(self, x): 54 | out = x 55 | if self.psa_type in [0, 1]: 56 | x = self.reduce(x) 57 | n, c, h, w = x.size() 58 | if self.shrink_factor != 1: 59 | h = (h - 1) // self.shrink_factor + 1 60 | w = (w - 1) // self.shrink_factor + 1 61 | x = F.interpolate(x, size=(h, w), mode='bilinear', align_corners=True) 62 | y = self.attention(x) 63 | if self.compact: 64 | if self.psa_type == 1: 65 | y = y.view(n, h * w, h * w).transpose(1, 2).view(n, h * w, h, w) 66 | else: 67 | y = PF.psa_mask(y, self.psa_type, self.mask_h, self.mask_w) 68 | if self.psa_softmax: 69 | y = F.softmax(y, dim=1) 70 | x = torch.bmm(x.view(n, c, h * w), y.view(n, h * w, h * w)).view(n, c, h, w) * (1.0 / self.normalization_factor) 71 | elif self.psa_type == 2: 72 | x_col = self.reduce(x) 73 | x_dis = self.reduce_p(x) 74 | n, c, h, w = x_col.size() 75 | if self.shrink_factor != 1: 76 | h = (h - 1) // self.shrink_factor + 1 77 | w = (w - 1) // self.shrink_factor + 1 78 | x_col = F.interpolate(x_col, size=(h, w), mode='bilinear', align_corners=True) 79 | x_dis = F.interpolate(x_dis, size=(h, w), mode='bilinear', align_corners=True) 80 | y_col = self.attention(x_col) 81 | y_dis = self.attention_p(x_dis) 82 | if self.compact: 83 | y_dis = y_dis.view(n, h * w, h * w).transpose(1, 2).view(n, h * w, h, w) 84 | else: 85 | y_col = PF.psa_mask(y_col, 0, self.mask_h, self.mask_w) 86 | y_dis = PF.psa_mask(y_dis, 1, self.mask_h, self.mask_w) 87 | if self.psa_softmax: 88 | y_col = F.softmax(y_col, dim=1) 89 | y_dis = F.softmax(y_dis, dim=1) 90 | x_col = torch.bmm(x_col.view(n, c, h * w), y_col.view(n, h * w, h * w)).view(n, c, h, w) * (1.0 / self.normalization_factor) 91 | x_dis = torch.bmm(x_dis.view(n, c, h * w), y_dis.view(n, h * w, h * w)).view(n, c, h, w) * (1.0 / self.normalization_factor) 92 | x = torch.cat([x_col, x_dis], 1) 93 | x = self.proj(x) 94 | if self.shrink_factor != 1: 95 | h = (h - 1) * self.shrink_factor + 1 96 | w = (w - 1) * self.shrink_factor + 1 97 | x = F.interpolate(x, size=(h, w), mode='bilinear', align_corners=True) 98 | return torch.cat((out, x), 1) 99 | 100 | 101 | class PSANet(nn.Module): 102 | def __init__(self, layers=50, dropout=0.1, classes=2, zoom_factor=8, use_psa=True, psa_type=2, compact=False, 103 | shrink_factor=2, mask_h=59, mask_w=59, normalization_factor=1.0, psa_softmax=True, 104 | criterion=nn.CrossEntropyLoss(ignore_index=255), BatchNorm=nn.BatchNorm2d, pretrained=True): 105 | super(PSANet, self).__init__() 106 | assert layers in [50, 101, 152] 107 | assert classes > 1 108 | assert zoom_factor in [1, 2, 4, 8] 109 | assert psa_type in [0, 1, 2] 110 | self.zoom_factor = zoom_factor 111 | self.use_psa = use_psa 112 | self.criterion = criterion 113 | models.BatchNorm = BatchNorm 114 | 115 | if layers == 50: 116 | resnet = models.resnet50(pretrained=pretrained) 117 | elif layers == 101: 118 | resnet = models.resnet101(pretrained=pretrained) 119 | else: 120 | resnet = models.resnet152(pretrained=pretrained) 121 | self.layer0 = nn.Sequential(resnet.conv1, resnet.bn1, resnet.relu, resnet.conv2, resnet.bn2, resnet.relu, resnet.conv3, resnet.bn3, resnet.relu, resnet.maxpool) 122 | self.layer1, self.layer2, self.layer3, self.layer4 = resnet.layer1, resnet.layer2, resnet.layer3, resnet.layer4 123 | 124 | for n, m in self.layer3.named_modules(): 125 | if 'conv2' in n: 126 | m.dilation, m.padding, m.stride = (2, 2), (2, 2), (1, 1) 127 | elif 'downsample.0' in n: 128 | m.stride = (1, 1) 129 | for n, m in self.layer4.named_modules(): 130 | if 'conv2' in n: 131 | m.dilation, m.padding, m.stride = (4, 4), (4, 4), (1, 1) 132 | elif 'downsample.0' in n: 133 | m.stride = (1, 1) 134 | 135 | fea_dim = 2048 136 | if use_psa: 137 | self.psa = PSA(fea_dim, 512, psa_type, compact, shrink_factor, mask_h, mask_w, normalization_factor, psa_softmax, BatchNorm) 138 | fea_dim *= 2 139 | self.cls = nn.Sequential( 140 | nn.Conv2d(fea_dim, 512, kernel_size=3, padding=1, bias=False), 141 | BatchNorm(512), 142 | nn.ReLU(inplace=True), 143 | nn.Dropout2d(p=dropout), 144 | nn.Conv2d(512, classes, kernel_size=1) 145 | ) 146 | if self.training: 147 | self.aux = nn.Sequential( 148 | nn.Conv2d(1024, 256, kernel_size=3, padding=1, bias=False), 149 | BatchNorm(256), 150 | nn.ReLU(inplace=True), 151 | nn.Dropout2d(p=dropout), 152 | nn.Conv2d(256, classes, kernel_size=1) 153 | ) 154 | 155 | def forward(self, x, y=None): 156 | x_size = x.size() 157 | assert (x_size[2] - 1) % 8 == 0 and (x_size[3] - 1) % 8 == 0 158 | h = int((x_size[2] - 1) / 8 * self.zoom_factor + 1) 159 | w = int((x_size[3] - 1) / 8 * self.zoom_factor + 1) 160 | 161 | x = self.layer0(x) 162 | x = self.layer1(x) 163 | x = self.layer2(x) 164 | x_tmp = self.layer3(x) 165 | x = self.layer4(x_tmp) 166 | if self.use_psa: 167 | x = self.psa(x) 168 | x = self.cls(x) 169 | if self.zoom_factor != 1: 170 | x = F.interpolate(x, size=(h, w), mode='bilinear', align_corners=True) 171 | 172 | if self.training: 173 | aux = self.aux(x_tmp) 174 | if self.zoom_factor != 1: 175 | aux = F.interpolate(aux, size=(h, w), mode='bilinear', align_corners=True) 176 | main_loss = self.criterion(x, y) 177 | aux_loss = self.criterion(aux, y) 178 | return x.max(1)[1], main_loss, aux_loss 179 | else: 180 | return x 181 | 182 | 183 | if __name__ == '__main__': 184 | import os 185 | os.environ["CUDA_VISIBLE_DEVICES"] = '0, 1' 186 | crop_h = crop_w = 465 187 | input = torch.rand(4, 3, crop_h, crop_w).cuda() 188 | compact = False 189 | mask_h, mask_w = None, None 190 | shrink_factor = 2 191 | if compact: 192 | mask_h = (crop_h - 1) // (8 * shrink_factor) + 1 193 | mask_w = (crop_w - 1) // (8 * shrink_factor) + 1 194 | else: 195 | assert (mask_h is None and mask_w is None) or (mask_h is not None and mask_w is not None) 196 | if mask_h is None and mask_w is None: 197 | mask_h = 2 * ((crop_h - 1) // (8 * shrink_factor) + 1) - 1 198 | mask_w = 2 * ((crop_w - 1) // (8 * shrink_factor) + 1) - 1 199 | else: 200 | assert (mask_h % 2 == 1) and (mask_h >= 3) and (mask_h <= 2 * ((crop_h - 1) // (8 * shrink_factor) + 1) - 1) 201 | assert (mask_w % 2 == 1) and (mask_w >= 3) and (mask_w <= 2 * ((crop_h - 1) // (8 * shrink_factor) + 1) - 1) 202 | 203 | model = PSANet(layers=50, dropout=0.1, classes=21, zoom_factor=8, use_psa=True, psa_type=2, compact=compact, 204 | shrink_factor=shrink_factor, mask_h=mask_h, mask_w=mask_w, psa_softmax=True, pretrained=True).cuda() 205 | print(model) 206 | model.eval() 207 | output = model(input) 208 | print('PSANet', output.size()) 209 | -------------------------------------------------------------------------------- /model/pspnet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | import torch.nn.functional as F 4 | 5 | import model.resnet as models 6 | import util.lovasz_softmax as L 7 | 8 | class PPM(nn.Module): 9 | def __init__(self, in_dim, reduction_dim, bins, BatchNorm): 10 | super(PPM, self).__init__() 11 | self.features = [] 12 | for bin in bins: 13 | self.features.append(nn.Sequential( 14 | nn.AdaptiveAvgPool2d(bin), 15 | nn.Conv2d(in_dim, reduction_dim, kernel_size=1, bias=False), 16 | BatchNorm(reduction_dim), 17 | nn.ReLU(inplace=True) 18 | )) 19 | self.features = nn.ModuleList(self.features) 20 | 21 | def forward(self, x): 22 | x_size = x.size() 23 | out = [x] 24 | for f in self.features: 25 | out.append(F.interpolate(f(x), x_size[2:], mode='bilinear', align_corners=True)) 26 | return torch.cat(out, 1) 27 | 28 | 29 | class PSPNet(nn.Module): 30 | def __init__(self, layers=50, bins=(1, 2, 3, 6), dropout=0.1, classes=2, zoom_factor=8, use_ppm=True, criterion=nn.CrossEntropyLoss(ignore_index=255), BatchNorm=nn.BatchNorm2d, pretrained=True): 31 | super(PSPNet, self).__init__() 32 | assert layers in [50, 101, 152] 33 | assert 2048 % len(bins) == 0 34 | assert classes > 1 35 | assert zoom_factor in [1, 2, 4, 8] 36 | self.zoom_factor = zoom_factor 37 | self.use_ppm = use_ppm 38 | self.criterion = criterion 39 | self.debug_gradient_norm = False 40 | models.BatchNorm = BatchNorm 41 | 42 | if layers == 50: 43 | resnet = models.resnet50(pretrained=pretrained) 44 | elif layers == 101: 45 | resnet = models.resnet101(pretrained=pretrained) 46 | else: 47 | resnet = models.resnet152(pretrained=pretrained) 48 | self.layer0 = nn.Sequential(resnet.conv1, resnet.bn1, resnet.relu, resnet.conv2, resnet.bn2, resnet.relu, resnet.conv3, resnet.bn3, resnet.relu, resnet.maxpool) 49 | self.layer1, self.layer2, self.layer3, self.layer4 = resnet.layer1, resnet.layer2, resnet.layer3, resnet.layer4 50 | 51 | for n, m in self.layer3.named_modules(): 52 | if 'conv2' in n: 53 | m.dilation, m.padding, m.stride = (2, 2), (2, 2), (1, 1) 54 | elif 'downsample.0' in n: 55 | m.stride = (1, 1) 56 | for n, m in self.layer4.named_modules(): 57 | if 'conv2' in n: 58 | m.dilation, m.padding, m.stride = (4, 4), (4, 4), (1, 1) 59 | elif 'downsample.0' in n: 60 | m.stride = (1, 1) 61 | 62 | fea_dim = 2048 63 | if use_ppm: 64 | self.ppm = PPM(fea_dim, int(fea_dim/len(bins)), bins, BatchNorm) 65 | fea_dim *= 2 66 | self.cls = nn.Sequential( 67 | nn.Conv2d(fea_dim, 512, kernel_size=3, padding=1, bias=False), 68 | BatchNorm(512), 69 | nn.ReLU(inplace=True), 70 | nn.Dropout2d(p=dropout), 71 | nn.Conv2d(512, classes, kernel_size=1) 72 | ) 73 | if self.training: 74 | self.aux = nn.Sequential( 75 | nn.Conv2d(1024, 256, kernel_size=3, padding=1, bias=False), 76 | BatchNorm(256), 77 | nn.ReLU(inplace=True), 78 | nn.Dropout2d(p=dropout), 79 | nn.Conv2d(256, classes, kernel_size=1) 80 | ) 81 | 82 | 83 | def criterion_lovasz(self,x,y,ignore=255): 84 | out = F.softmax(x, dim=1) 85 | loss = L.lovasz_softmax(out, y, ignore=ignore) 86 | return loss 87 | 88 | def criterion_focal_loss(self,x,y,ignore=255): 89 | 90 | cross_entropy_loss = nn.CrossEntropyLoss(ignore_index=255,reduce=False) 91 | gamma = 2 92 | logpt = cross_entropy_loss(x,y) 93 | pt = torch.exp(-logpt) 94 | 95 | loss = ((1-pt)**gamma) * logpt 96 | loss = loss.mean() 97 | return loss 98 | 99 | 100 | def forward(self, x, y=None, sup_loss_method='CE'): 101 | 102 | x_size = x.size() 103 | assert (x_size[2]-1) % 8 == 0 and (x_size[3]-1) % 8 == 0 104 | h = int((x_size[2] - 1) / 8 * self.zoom_factor + 1) 105 | w = int((x_size[3] - 1) / 8 * self.zoom_factor + 1) 106 | 107 | x = self.layer0(x) 108 | x = self.layer1(x) 109 | x = self.layer2(x) 110 | x_tmp = self.layer3(x) 111 | x = self.layer4(x_tmp) 112 | if self.use_ppm: 113 | x = self.ppm(x) 114 | x = self.cls(x) 115 | if self.zoom_factor != 1: 116 | x = F.interpolate(x, size=(h, w), mode='bilinear', align_corners=True) 117 | 118 | if self.training: 119 | aux = self.aux(x_tmp) 120 | if self.zoom_factor != 1: 121 | aux = F.interpolate(aux, size=(h, w), mode='bilinear', align_corners=True) 122 | if y is not None: 123 | if sup_loss_method == 'CE': 124 | main_loss = self.criterion(x, y) 125 | aux_loss = self.criterion(aux, y) 126 | elif sup_loss_method == 'lovasz': 127 | main_loss = self.criterion_lovasz(x, y) 128 | aux_loss = self.criterion_lovasz(aux, y) 129 | elif sup_loss_method == 'MSE': 130 | main_loss = self.criterion_sup_one_hot(x, y) 131 | aux_loss = self.criterion_sup_one_hot(aux, y) 132 | elif sup_loss_method == 'focal': 133 | main_loss = self.criterion_focal_loss(x, y) 134 | aux_loss = self.criterion_focal_loss(aux, y) 135 | else: 136 | main_loss = None 137 | aux_loss = None 138 | if main_loss is not None: 139 | return (x, aux), main_loss, aux_loss 140 | else: 141 | return x 142 | 143 | else: 144 | aux = self.aux(x_tmp) 145 | if self.zoom_factor != 1: 146 | aux = F.interpolate(aux, size=(h, w), mode='bilinear', align_corners=True) 147 | 148 | if y is not None: 149 | main_loss = self.criterion(x, y) 150 | aux_loss = self.criterion(aux, y) 151 | else: 152 | main_loss = None 153 | aux_loss = None 154 | if main_loss is not None: 155 | # return (x, aux), main_loss, aux_loss # gradient norm 156 | return x.max(1)[1], main_loss, aux_loss # else 157 | else: 158 | return x 159 | 160 | 161 | 162 | if __name__ == '__main__': 163 | import os 164 | os.environ["CUDA_VISIBLE_DEVICES"] = '0, 1' 165 | input = torch.rand(4, 3, 473, 473).cuda() 166 | model = PSPNet(layers=50, bins=(1, 2, 3, 6), dropout=0.1, classes=21, zoom_factor=1, use_ppm=True, pretrained=True).cuda() 167 | model.eval() 168 | print(model) 169 | output = model(input) 170 | print('PSPNet', output.size()) 171 | -------------------------------------------------------------------------------- /tool/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/tool/.DS_Store -------------------------------------------------------------------------------- /tool/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/tool/__init__.py -------------------------------------------------------------------------------- /tool/gen_pseudo_label.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # usage: 3 | # sh tool/gen_pseudo_label.sh cityscapes config_gen.yaml ex_test 4 | 5 | PYTHON=python3 6 | 7 | dataset=$1 8 | cfg=$2 9 | exp_name=$3 10 | 11 | 12 | exp_dir=exp/${exp_name} 13 | result_dir=${exp_dir}/result 14 | model_dir=${exp_dir}/model 15 | config=config/${dataset}/${cfg} 16 | now=$(date +"%Y%m%d_%H%M%S") 17 | 18 | mkdir -p ${result_dir} 19 | mkdir -p ${exp_dir} 20 | mkdir -p ${model_dir} 21 | cp tool/gen_pseudo_label.sh tool/gen_pseudo_label.py tool/test.py model/pspnet.py ${config} ${exp_dir} 22 | 23 | export PYTHONWARNINGS='ignore:semaphore_tracker:UserWarning' 24 | export PYTHONPATH=./ 25 | export KMP_INIT_AT_FORK=FALSE 26 | $PYTHON -u ${exp_dir}/gen_pseudo_label.py --config=${exp_dir}/${cfg} 2>&1 | tee ${exp_dir}/train-$now.log 27 | -------------------------------------------------------------------------------- /tool/scripts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/tool/scripts/.DS_Store -------------------------------------------------------------------------------- /tool/scripts/train_deeplabv2_cityscapes_split8_crop361.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_deeplabv2_cityscapes_split8_crop361.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh cityscapes train_deeplabv2_cityscapes_split8_crop361_round0.yaml train_deeplabv2_cityscapes_split8_crop361_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_deeplabv2_cityscapes_split8_crop361_round0/model/train_epoch_200.pth initmodel/train_deeplabv2_cityscapes_split8_crop361_round0.pth 9 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round1.yaml ex_gen 10 | rm dataset/cityscapes/pseudo_labels/deeplabv2_cityscapes_split8_crop361_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_deeplabv2_cityscapes_split8_crop361_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh cityscapes train_deeplabv2_cityscapes_split8_crop361_round1.yaml train_deeplabv2_cityscapes_split8_crop361_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_deeplabv2_cityscapes_split8_crop361_round1/model/train_epoch_400.pth initmodel/train_deeplabv2_cityscapes_split8_crop361_round1.pth 18 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_deeplabv2_cityscapes_split8_crop361_for_round2.yaml ex_gen 19 | rm dataset/cityscapes/pseudo_labels/deeplabv2_cityscapes_split8_crop361_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_deeplabv2_cityscapes_split8_crop361_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh cityscapes train_deeplabv2_cityscapes_split8_crop361_round2.yaml train_deeplabv2_cityscapes_split8_crop361_round2 -------------------------------------------------------------------------------- /tool/scripts/train_psp50_cityscapes_split4_crop361.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_psp50_cityscapes_split4_crop361.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop361_round0.yaml train_psp50_cityscapes_split4_crop361_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_psp50_cityscapes_split4_crop361_round0/model/train_epoch_200.pth initmodel/train_psp50_cityscapes_split4_crop361_round0.pth 9 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round1.yaml ex_gen 10 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split4_crop361_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_psp50_cityscapes_split4_crop361_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop361_round1.yaml train_psp50_cityscapes_split4_crop361_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_psp50_cityscapes_split4_crop361_round1/model/train_epoch_400.pth initmodel/train_psp50_cityscapes_split4_crop361_round1.pth 18 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split4_crop361_for_round2.yaml ex_gen 19 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split4_crop361_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_psp50_cityscapes_split4_crop361_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop361_round2.yaml train_psp50_cityscapes_split4_crop361_round2 -------------------------------------------------------------------------------- /tool/scripts/train_psp50_cityscapes_split4_crop713.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_psp50_cityscapes_split4_crop713.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop713_round0.yaml train_psp50_cityscapes_split4_crop713_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_psp50_cityscapes_split4_crop713_round0/model/train_epoch_200.pth initmodel/train_psp50_cityscapes_split4_crop713_round0.pth 9 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round1.yaml ex_gen 10 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split4_crop713_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_psp50_cityscapes_split4_crop713_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop713_round1.yaml train_psp50_cityscapes_split4_crop713_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_psp50_cityscapes_split4_crop713_round1/model/train_epoch_400.pth initmodel/train_psp50_cityscapes_split4_crop713_round1.pth 18 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split4_crop713_for_round2.yaml ex_gen 19 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split4_crop713_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_psp50_cityscapes_split4_crop713_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh cityscapes train_psp50_cityscapes_split4_crop713_round2.yaml train_psp50_cityscapes_split4_crop713_round2 -------------------------------------------------------------------------------- /tool/scripts/train_psp50_cityscapes_split8_crop361.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_psp50_cityscapes_split8_crop361.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop361_round0.yaml train_psp50_cityscapes_split8_crop361_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_psp50_cityscapes_split8_crop361_round0/model/train_epoch_200.pth initmodel/train_psp50_cityscapes_split8_crop361_round0.pth 9 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round1.yaml ex_gen 10 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split8_crop361_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_psp50_cityscapes_split8_crop361_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop361_round1.yaml train_psp50_cityscapes_split8_crop361_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_psp50_cityscapes_split8_crop361_round1/model/train_epoch_400.pth initmodel/train_psp50_cityscapes_split8_crop361_round1.pth 18 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split8_crop361_for_round2.yaml ex_gen 19 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split8_crop361_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_psp50_cityscapes_split8_crop361_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop361_round2.yaml train_psp50_cityscapes_split8_crop361_round2 -------------------------------------------------------------------------------- /tool/scripts/train_psp50_cityscapes_split8_crop713.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_psp50_cityscapes_split8_crop713.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop713_round0.yaml train_psp50_cityscapes_split8_crop713_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_psp50_cityscapes_split8_crop713_round0/model/train_epoch_200.pth initmodel/train_psp50_cityscapes_split8_crop713_round0.pth 9 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round1.yaml ex_gen 10 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split8_crop713_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_psp50_cityscapes_split8_crop713_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop713_round1.yaml train_psp50_cityscapes_split8_crop713_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_psp50_cityscapes_split8_crop713_round1/model/train_epoch_400.pth initmodel/train_psp50_cityscapes_split8_crop713_round1.pth 18 | sh tool/gen_pseudo_label.sh cityscapes gen_pseudo_label_psp50_cityscapes_split8_crop713_for_round2.yaml ex_gen 19 | rm dataset/cityscapes/pseudo_labels/psp50_cityscapes_split8_crop713_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_psp50_cityscapes_split8_crop713_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh cityscapes train_psp50_cityscapes_split8_crop713_round2.yaml train_psp50_cityscapes_split8_crop713_round2 -------------------------------------------------------------------------------- /tool/scripts/train_psp50_voc_split1464_crop321.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sh tool/scripts/train_psp50_voc_split1464_crop321.sh 3 | 4 | # --- Round 0: train with only labeled data 5 | sh tool/train.sh voc2012 train_psp50_voc_split1464_crop321_round0.yaml train_psp50_voc_split1464_crop321_round0 6 | 7 | # --- Pseudo label Generation for Round 1 8 | cp exp/train_psp50_voc_split1464_crop321_round0/model/train_epoch_50.pth initmodel/train_psp50_voc_split1464_crop321_round0.pth 9 | sh tool/gen_pseudo_label.sh voc2012 gen_pseudo_label_psp50_voc_split1464_crop321_for_round1.yaml ex_gen 10 | rm dataset/voc2012/pseudo_labels/psp50_voc_split1464_crop321_for_round1/1/*.npy # rm logit npy files to save disk space 11 | rm -r exp/npy_files/npy_psp50_voc_split1464_crop321_for_round1 # rm confidence npy files to save disk space 12 | 13 | # --- Round 1: train with labeled data and unlabeled data (equipped with generated pseudo labels) 14 | sh tool/train.sh voc2012 train_psp50_voc_split1464_crop321_round1.yaml train_psp50_voc_split1464_crop321_round1 15 | 16 | # --- Pseudo label Generation for Round 2 17 | cp exp/train_psp50_voc_split1464_crop321_round1/model/train_epoch_100.pth initmodel/train_psp50_voc_split1464_crop321_round1.pth 18 | sh tool/gen_pseudo_label.sh voc2012 gen_pseudo_label_psp50_voc_split1464_crop321_for_round2.yaml ex_gen 19 | rm dataset/voc2012/pseudo_labels/psp50_voc_split1464_crop321_for_round2/1/*.npy # rm logit npy files to save disk space 20 | rm -r exp/npy_files/npy_psp50_voc_split1464_crop321_for_round2 # rm confidence npy files to save disk space 21 | 22 | # --- Round 2: train with labeled data and unlabeled data (equipped with generated pseudo labels) 23 | sh tool/train.sh voc2012 train_psp50_voc_split1464_crop321_round2.yaml train_psp50_voc_split1464_crop321_round2 -------------------------------------------------------------------------------- /tool/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #PYTHON=/mnt/backup2/home/yczhang7/segahsj/anaconda3/envs/cuda10.2/bin/python3.7 4 | PYTHON=python3 5 | #dataset=cityscapes 6 | dataset=voc2012 7 | exp_name=$1 8 | exp_dir=exp/${exp_name} 9 | result_dir=${exp_dir}/result 10 | config=config/${dataset}/config_hu_0.60_gen.yaml 11 | now=$(date +"%Y%m%d_%H%M%S") 12 | 13 | mkdir -p ${result_dir} 14 | mkdir -p ${exp_dir} 15 | cp tool/test.sh tool/test.py ${config} ${exp_dir} 16 | #cp tool/test.sh tool/my_train2_task2.py ${config} ${exp_dir} 17 | #cp tool/test.sh tool/only_label.py ${config} ${exp_dir} 18 | 19 | export PYTHONPATH=./ 20 | export KMP_INIT_AT_FORK=FALSE 21 | #$PYTHON -u ${exp_dir}/my_train2.py --config=${config} 2>&1 | tee ${model_dir}/train-$now.log 22 | #$PYTHON -u ${exp_dir}/my_train2_task2.py --config=${config} 2>&1 | tee ${result_dir}/test-$now.log 23 | $PYTHON -u ${exp_dir}/test.py --config=${config} 2>&1 | tee ${result_dir}/test-$now.log 24 | #$PYTHON -u ${exp_dir}/only_label.py --config=${config} 2>&1 | tee ${result_dir}/test-$now.log 25 | -------------------------------------------------------------------------------- /tool/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # usage: 3 | # sh tool/train.sh cityscapes config-1.yaml ex200 4 | PYTHON=python3 5 | 6 | dataset=$1 7 | cfg=$2 8 | exp_name=$3 9 | 10 | exp_dir=exp/${exp_name} 11 | result_dir=${exp_dir}/result 12 | model_dir=${exp_dir}/model 13 | config=config/${dataset}/${cfg} 14 | now=$(date +"%Y%m%d_%H%M%S") 15 | 16 | mkdir -p ${result_dir} 17 | mkdir -p ${exp_dir} 18 | mkdir -p ${model_dir} 19 | cp tool/train.sh tool/train.py tool/train_func.py tool/test.py model/pspnet.py model/deeplabv2.py ${config} ${exp_dir} 20 | 21 | 22 | export PYTHONWARNINGS='ignore:semaphore_tracker:UserWarning' 23 | export PYTHONPATH=./ 24 | export KMP_INIT_AT_FORK=FALSE 25 | $PYTHON -u ${exp_dir}/train.py --config=${exp_dir}/${cfg} exp_name ${exp_name} 2>&1 | tee ${exp_dir}/train-$now.log 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__init__.py -------------------------------------------------------------------------------- /util/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /util/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/augmentation.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/augmentation.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/config.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/config.cpython-35.pyc -------------------------------------------------------------------------------- /util/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/dataset.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/dataset.cpython-35.pyc -------------------------------------------------------------------------------- /util/__pycache__/dataset.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/dataset.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/ramps.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/ramps.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/reader.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/reader.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/transform.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/transform.cpython-35.pyc -------------------------------------------------------------------------------- /util/__pycache__/transform.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/transform.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/util.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/util.cpython-35.pyc -------------------------------------------------------------------------------- /util/__pycache__/util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/util.cpython-36.pyc -------------------------------------------------------------------------------- /util/__pycache__/validate_full_size.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CVMI-Lab/DARS/0cfe09ad6758458a497940f4fe7829aad6983f67/util/__pycache__/validate_full_size.cpython-36.pyc -------------------------------------------------------------------------------- /util/augmentation.py: -------------------------------------------------------------------------------- 1 | # Code taken from https://github.com/DeepVoltaire/AutoAugment 2 | 3 | from PIL import Image, ImageEnhance, ImageOps 4 | import numpy as np 5 | import random 6 | 7 | 8 | class CIFAR10Policy(object): 9 | """ Randomly choose one of the best 25 Sub-policies on CIFAR10. 10 | 11 | Example: 12 | >>> policy = CIFAR10Policy() 13 | >>> transformed = policy(image) 14 | 15 | Example as a PyTorch Transform: 16 | >>> transform=transforms.Compose([ 17 | >>> transforms.Resize(256), 18 | >>> CIFAR10Policy(), 19 | >>> transforms.ToTensor()]) 20 | """ 21 | def __init__(self, fillcolor=(128, 128, 128)): 22 | self.policies = [ 23 | SubPolicy(0.1, "invert", 7, 0.2, "contrast", 6, fillcolor), 24 | SubPolicy(0.7, "rotate", 2, 0.3, "translateX", 9, fillcolor), 25 | SubPolicy(0.8, "sharpness", 1, 0.9, "sharpness", 3, fillcolor), 26 | SubPolicy(0.5, "shearY", 8, 0.7, "translateY", 9, fillcolor), 27 | SubPolicy(0.5, "autocontrast", 8, 0.9, "equalize", 2, fillcolor), 28 | 29 | SubPolicy(0.2, "shearY", 7, 0.3, "posterize", 7, fillcolor), 30 | SubPolicy(0.4, "color", 3, 0.6, "brightness", 7, fillcolor), 31 | SubPolicy(0.3, "sharpness", 9, 0.7, "brightness", 9, fillcolor), 32 | SubPolicy(0.6, "equalize", 5, 0.5, "equalize", 1, fillcolor), 33 | SubPolicy(0.6, "contrast", 7, 0.6, "sharpness", 5, fillcolor), 34 | 35 | SubPolicy(0.7, "color", 7, 0.5, "translateX", 8, fillcolor), 36 | SubPolicy(0.3, "equalize", 7, 0.4, "autocontrast", 8, fillcolor), 37 | SubPolicy(0.4, "translateY", 3, 0.2, "sharpness", 6, fillcolor), 38 | SubPolicy(0.9, "brightness", 6, 0.2, "color", 8, fillcolor), 39 | SubPolicy(0.5, "solarize", 2, 0.0, "invert", 3, fillcolor), 40 | 41 | SubPolicy(0.2, "equalize", 0, 0.6, "autocontrast", 0, fillcolor), 42 | SubPolicy(0.2, "equalize", 8, 0.8, "equalize", 4, fillcolor), 43 | SubPolicy(0.9, "color", 9, 0.6, "equalize", 6, fillcolor), 44 | SubPolicy(0.8, "autocontrast", 4, 0.2, "solarize", 8, fillcolor), 45 | SubPolicy(0.1, "brightness", 3, 0.7, "color", 0, fillcolor), 46 | 47 | SubPolicy(0.4, "solarize", 5, 0.9, "autocontrast", 3, fillcolor), 48 | SubPolicy(0.9, "translateY", 9, 0.7, "translateY", 9, fillcolor), 49 | SubPolicy(0.9, "autocontrast", 2, 0.8, "solarize", 3, fillcolor), 50 | SubPolicy(0.8, "equalize", 8, 0.1, "invert", 3, fillcolor), 51 | SubPolicy(0.7, "translateY", 9, 0.9, "autocontrast", 1, fillcolor) 52 | ] 53 | 54 | 55 | def __call__(self, img): 56 | policy_idx = random.randint(0, len(self.policies) - 1) 57 | return self.policies[policy_idx](img) 58 | 59 | def __repr__(self): 60 | return "AutoAugment CIFAR10 Policy" 61 | 62 | 63 | class SubPolicy(object): 64 | def __init__(self, p1, operation1, magnitude_idx1, p2, operation2, magnitude_idx2, fillcolor=(128, 128, 128)): 65 | ranges = { 66 | "shearX": np.linspace(0, 0.3, 10), 67 | "shearY": np.linspace(0, 0.3, 10), 68 | "translateX": np.linspace(0, 150 / 331, 10), 69 | "translateY": np.linspace(0, 150 / 331, 10), 70 | "rotate": np.linspace(0, 30, 10), 71 | "color": np.linspace(0.0, 0.9, 10), 72 | "posterize": np.round(np.linspace(8, 4, 10), 0).astype(np.int), 73 | "solarize": np.linspace(256, 0, 10), 74 | "contrast": np.linspace(0.0, 0.9, 10), 75 | "sharpness": np.linspace(0.0, 0.9, 10), 76 | "brightness": np.linspace(0.0, 0.9, 10), 77 | "autocontrast": [0] * 10, 78 | "equalize": [0] * 10, 79 | "invert": [0] * 10 80 | } 81 | 82 | # from https://stackoverflow.com/questions/5252170/specify-image-filling-color-when-rotating-in-python-with-pil-and-setting-expand 83 | def rotate_with_fill(img, magnitude): 84 | rot = img.convert("RGBA").rotate(magnitude) 85 | return Image.composite(rot, Image.new("RGBA", rot.size, (128,) * 4), rot).convert(img.mode) 86 | 87 | func = { 88 | "shearX": lambda img, magnitude: img.transform( 89 | img.size, Image.AFFINE, (1, magnitude * random.choice([-1, 1]), 0, 0, 1, 0), 90 | Image.BICUBIC, fillcolor=fillcolor), 91 | "shearY": lambda img, magnitude: img.transform( 92 | img.size, Image.AFFINE, (1, 0, 0, magnitude * random.choice([-1, 1]), 1, 0), 93 | Image.BICUBIC, fillcolor=fillcolor), 94 | "translateX": lambda img, magnitude: img.transform( 95 | img.size, Image.AFFINE, (1, 0, magnitude * img.size[0] * random.choice([-1, 1]), 0, 1, 0), 96 | fillcolor=fillcolor), 97 | "translateY": lambda img, magnitude: img.transform( 98 | img.size, Image.AFFINE, (1, 0, 0, 0, 1, magnitude * img.size[1] * random.choice([-1, 1])), 99 | fillcolor=fillcolor), 100 | "rotate": lambda img, magnitude: rotate_with_fill(img, magnitude), 101 | # "rotate": lambda img, magnitude: img.rotate(magnitude * random.choice([-1, 1])), 102 | "color": lambda img, magnitude: ImageEnhance.Color(img).enhance(1 + magnitude * random.choice([-1, 1])), 103 | "posterize": lambda img, magnitude: ImageOps.posterize(img, magnitude), 104 | "solarize": lambda img, magnitude: ImageOps.solarize(img, magnitude), 105 | "contrast": lambda img, magnitude: ImageEnhance.Contrast(img).enhance( 106 | 1 + magnitude * random.choice([-1, 1])), 107 | "sharpness": lambda img, magnitude: ImageEnhance.Sharpness(img).enhance( 108 | 1 + magnitude * random.choice([-1, 1])), 109 | "brightness": lambda img, magnitude: ImageEnhance.Brightness(img).enhance( 110 | 1 + magnitude * random.choice([-1, 1])), 111 | "autocontrast": lambda img, magnitude: ImageOps.autocontrast(img), 112 | "equalize": lambda img, magnitude: ImageOps.equalize(img), 113 | "invert": lambda img, magnitude: ImageOps.invert(img) 114 | } 115 | 116 | self.p1 = p1 117 | self.operation1 = func[operation1] 118 | self.magnitude1 = ranges[operation1][magnitude_idx1] 119 | self.p2 = p2 120 | self.operation2 = func[operation2] 121 | self.magnitude2 = ranges[operation2][magnitude_idx2] 122 | 123 | 124 | def __call__(self, img): 125 | if random.random() < self.p1: img = self.operation1(img, self.magnitude1) 126 | if random.random() < self.p2: img = self.operation2(img, self.magnitude2) 127 | return img 128 | -------------------------------------------------------------------------------- /util/config.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Functions for parsing args 3 | # ----------------------------------------------------------------------------- 4 | import yaml 5 | import os 6 | from ast import literal_eval 7 | import copy 8 | 9 | 10 | class CfgNode(dict): 11 | """ 12 | CfgNode represents an internal node in the configuration tree. It's a simple 13 | dict-like container that allows for attribute-based access to keys. 14 | """ 15 | 16 | def __init__(self, init_dict=None, key_list=None, new_allowed=False): 17 | # Recursively convert nested dictionaries in init_dict into CfgNodes 18 | init_dict = {} if init_dict is None else init_dict 19 | key_list = [] if key_list is None else key_list 20 | for k, v in init_dict.items(): 21 | if type(v) is dict: 22 | # Convert dict to CfgNode 23 | init_dict[k] = CfgNode(v, key_list=key_list + [k]) 24 | super(CfgNode, self).__init__(init_dict) 25 | 26 | def __getattr__(self, name): 27 | if name in self: 28 | return self[name] 29 | else: 30 | raise AttributeError(name) 31 | 32 | def __setattr__(self, name, value): 33 | self[name] = value 34 | 35 | def __str__(self): 36 | def _indent(s_, num_spaces): 37 | s = s_.split("\n") 38 | if len(s) == 1: 39 | return s_ 40 | first = s.pop(0) 41 | s = [(num_spaces * " ") + line for line in s] 42 | s = "\n".join(s) 43 | s = first + "\n" + s 44 | return s 45 | 46 | r = "" 47 | s = [] 48 | for k, v in sorted(self.items()): 49 | seperator = "\n" if isinstance(v, CfgNode) else " " 50 | attr_str = "{}:{}{}".format(str(k), seperator, str(v)) 51 | attr_str = _indent(attr_str, 2) 52 | s.append(attr_str) 53 | r += "\n".join(s) 54 | return r 55 | 56 | def __repr__(self): 57 | return "{}({})".format(self.__class__.__name__, super(CfgNode, self).__repr__()) 58 | 59 | 60 | def load_cfg_from_cfg_file(file): 61 | cfg = {} 62 | assert os.path.isfile(file) and file.endswith('.yaml'), \ 63 | '{} is not a yaml file'.format(file) 64 | 65 | with open(file, 'r') as f: 66 | cfg_from_file = yaml.safe_load(f) 67 | 68 | for key in cfg_from_file: 69 | for k, v in cfg_from_file[key].items(): 70 | cfg[k] = v 71 | 72 | cfg = CfgNode(cfg) 73 | return cfg 74 | 75 | 76 | def merge_cfg_from_list(cfg, cfg_list): 77 | new_cfg = copy.deepcopy(cfg) 78 | assert len(cfg_list) % 2 == 0 79 | for full_key, v in zip(cfg_list[0::2], cfg_list[1::2]): 80 | subkey = full_key.split('.')[-1] 81 | assert subkey in cfg, 'Non-existent key: {}'.format(full_key) 82 | value = _decode_cfg_value(v) 83 | value = _check_and_coerce_cfg_value_type( 84 | value, cfg[subkey], subkey, full_key 85 | ) 86 | setattr(new_cfg, subkey, value) 87 | 88 | return new_cfg 89 | 90 | 91 | def _decode_cfg_value(v): 92 | """Decodes a raw config value (e.g., from a yaml config files or command 93 | line argument) into a Python object. 94 | """ 95 | # All remaining processing is only applied to strings 96 | if not isinstance(v, str): 97 | return v 98 | # Try to interpret `v` as a: 99 | # string, number, tuple, list, dict, boolean, or None 100 | try: 101 | v = literal_eval(v) 102 | # The following two excepts allow v to pass through when it represents a 103 | # string. 104 | # 105 | # Longer explanation: 106 | # The type of v is always a string (before calling literal_eval), but 107 | # sometimes it *represents* a string and other times a data structure, like 108 | # a list. In the case that v represents a string, what we got back from the 109 | # yaml parser is 'foo' *without quotes* (so, not '"foo"'). literal_eval is 110 | # ok with '"foo"', but will raise a ValueError if given 'foo'. In other 111 | # cases, like paths (v = 'foo/bar' and not v = '"foo/bar"'), literal_eval 112 | # will raise a SyntaxError. 113 | except ValueError: 114 | pass 115 | except SyntaxError: 116 | pass 117 | return v 118 | 119 | 120 | def _check_and_coerce_cfg_value_type(replacement, original, key, full_key): 121 | """Checks that `replacement`, which is intended to replace `original` is of 122 | the right type. The type is correct if it matches exactly or is one of a few 123 | cases in which the type can be easily coerced. 124 | """ 125 | original_type = type(original) 126 | replacement_type = type(replacement) 127 | 128 | # The types must match (with some exceptions) 129 | if replacement_type == original_type: 130 | return replacement 131 | 132 | # Cast replacement from from_type to to_type if the replacement and original 133 | # types match from_type and to_type 134 | def conditional_cast(from_type, to_type): 135 | if replacement_type == from_type and original_type == to_type: 136 | return True, to_type(replacement) 137 | else: 138 | return False, None 139 | 140 | # Conditionally casts 141 | # list <-> tuple 142 | casts = [(tuple, list), (list, tuple)] 143 | # For py2: allow converting from str (bytes) to a unicode string 144 | try: 145 | casts.append((str, unicode)) # noqa: F821 146 | except Exception: 147 | pass 148 | 149 | for (from_type, to_type) in casts: 150 | converted, converted_value = conditional_cast(from_type, to_type) 151 | if converted: 152 | return converted_value 153 | 154 | raise ValueError( 155 | "Type mismatch ({} vs. {}) with values ({} vs. {}) for config " 156 | "key: {}".format( 157 | original_type, replacement_type, original, replacement, full_key 158 | ) 159 | ) 160 | 161 | 162 | def _assert_with_logging(cond, msg): 163 | if not cond: 164 | logger.debug(msg) 165 | assert cond, msg 166 | 167 | -------------------------------------------------------------------------------- /util/lovasz_softmax.py: -------------------------------------------------------------------------------- 1 | """ 2 | Lovasz-Softmax and Jaccard hinge loss in PyTorch 3 | Maxim Berman 2018 ESAT-PSI KU Leuven (MIT License) 4 | """ 5 | 6 | from __future__ import print_function, division 7 | 8 | import torch 9 | from torch.autograd import Variable 10 | import torch.nn.functional as F 11 | import numpy as np 12 | 13 | try: 14 | from itertools import ifilterfalse 15 | except ImportError: # py3k 16 | from itertools import filterfalse as ifilterfalse 17 | 18 | 19 | def lovasz_grad(gt_sorted): 20 | """ 21 | Computes gradient of the Lovasz extension w.r.t sorted errors 22 | See Alg. 1 in paper 23 | """ 24 | p = len(gt_sorted) 25 | gts = gt_sorted.sum() 26 | intersection = gts - gt_sorted.float().cumsum(0) 27 | union = gts + (1 - gt_sorted).float().cumsum(0) 28 | jaccard = 1. - intersection / union 29 | if p > 1: # cover 1-pixel case 30 | jaccard[1:p] = jaccard[1:p] - jaccard[0:-1] 31 | return jaccard 32 | 33 | 34 | def iou_binary(preds, labels, EMPTY=1., ignore=None, per_image=True): 35 | """ 36 | IoU for foreground class 37 | binary: 1 foreground, 0 background 38 | """ 39 | if not per_image: 40 | preds, labels = (preds,), (labels,) 41 | ious = [] 42 | for pred, label in zip(preds, labels): 43 | intersection = ((label == 1) & (pred == 1)).sum() 44 | union = ((label == 1) | ((pred == 1) & (label != ignore))).sum() 45 | if not union: 46 | iou = EMPTY 47 | else: 48 | iou = float(intersection) / float(union) 49 | ious.append(iou) 50 | iou = mean(ious) # mean accross images if per_image 51 | return 100 * iou 52 | 53 | 54 | def iou(preds, labels, C, EMPTY=1., ignore=None, per_image=False): 55 | """ 56 | Array of IoU for each (non ignored) class 57 | """ 58 | if not per_image: 59 | preds, labels = (preds,), (labels,) 60 | ious = [] 61 | for pred, label in zip(preds, labels): 62 | iou = [] 63 | for i in range(C): 64 | if i != ignore: # The ignored label is sometimes among predicted classes (ENet - CityScapes) 65 | intersection = ((label == i) & (pred == i)).sum() 66 | union = ((label == i) | ((pred == i) & (label != ignore))).sum() 67 | if not union: 68 | iou.append(EMPTY) 69 | else: 70 | iou.append(float(intersection) / float(union)) 71 | ious.append(iou) 72 | ious = [mean(iou) for iou in zip(*ious)] # mean accross images if per_image 73 | return 100 * np.array(ious) 74 | 75 | 76 | # --------------------------- BINARY LOSSES --------------------------- 77 | 78 | 79 | def lovasz_hinge(logits, labels, per_image=True, ignore=None): 80 | """ 81 | Binary Lovasz hinge loss 82 | logits: [B, H, W] Variable, logits at each pixel (between -\infty and +\infty) 83 | labels: [B, H, W] Tensor, binary ground truth masks (0 or 1) 84 | per_image: compute the loss per image instead of per batch 85 | ignore: void class id 86 | """ 87 | if per_image: 88 | loss = mean(lovasz_hinge_flat(*flatten_binary_scores(log.unsqueeze(0), lab.unsqueeze(0), ignore)) 89 | for log, lab in zip(logits, labels)) 90 | else: 91 | loss = lovasz_hinge_flat(*flatten_binary_scores(logits, labels, ignore)) 92 | return loss 93 | 94 | 95 | def lovasz_hinge_flat(logits, labels): 96 | """ 97 | Binary Lovasz hinge loss 98 | logits: [P] Variable, logits at each prediction (between -\infty and +\infty) 99 | labels: [P] Tensor, binary ground truth labels (0 or 1) 100 | ignore: label to ignore 101 | """ 102 | if len(labels) == 0: 103 | # only void pixels, the gradients should be 0 104 | return logits.sum() * 0. 105 | signs = 2. * labels.float() - 1. 106 | errors = (1. - logits * Variable(signs)) 107 | errors_sorted, perm = torch.sort(errors, dim=0, descending=True) 108 | perm = perm.data 109 | gt_sorted = labels[perm] 110 | grad = lovasz_grad(gt_sorted) 111 | loss = torch.dot(F.relu(errors_sorted), Variable(grad)) 112 | return loss 113 | 114 | 115 | def flatten_binary_scores(scores, labels, ignore=None): 116 | """ 117 | Flattens predictions in the batch (binary case) 118 | Remove labels equal to 'ignore' 119 | """ 120 | scores = scores.view(-1) 121 | labels = labels.view(-1) 122 | if ignore is None: 123 | return scores, labels 124 | valid = (labels != ignore) 125 | vscores = scores[valid] 126 | vlabels = labels[valid] 127 | return vscores, vlabels 128 | 129 | 130 | class StableBCELoss(torch.nn.modules.Module): 131 | def __init__(self): 132 | super(StableBCELoss, self).__init__() 133 | 134 | def forward(self, input, target): 135 | neg_abs = - input.abs() 136 | loss = input.clamp(min=0) - input * target + (1 + neg_abs.exp()).log() 137 | return loss.mean() 138 | 139 | 140 | def binary_xloss(logits, labels, ignore=None): 141 | """ 142 | Binary Cross entropy loss 143 | logits: [B, H, W] Variable, logits at each pixel (between -\infty and +\infty) 144 | labels: [B, H, W] Tensor, binary ground truth masks (0 or 1) 145 | ignore: void class id 146 | """ 147 | logits, labels = flatten_binary_scores(logits, labels, ignore) 148 | loss = StableBCELoss()(logits, Variable(labels.float())) 149 | return loss 150 | 151 | 152 | # --------------------------- MULTICLASS LOSSES --------------------------- 153 | 154 | 155 | def lovasz_softmax(probas, labels, classes='present', per_image=False, ignore=None): 156 | """ 157 | Multi-class Lovasz-Softmax loss 158 | probas: [B, C, H, W] Variable, class probabilities at each prediction (between 0 and 1). 159 | Interpreted as binary (sigmoid) output with outputs of size [B, H, W]. 160 | labels: [B, H, W] Tensor, ground truth labels (between 0 and C - 1) 161 | classes: 'all' for all, 'present' for classes present in labels, or a list of classes to average. 162 | per_image: compute the loss per image instead of per batch 163 | ignore: void class labels 164 | """ 165 | if per_image: 166 | loss = mean(lovasz_softmax_flat(*flatten_probas(prob.unsqueeze(0), lab.unsqueeze(0), ignore), classes=classes) 167 | for prob, lab in zip(probas, labels)) 168 | else: 169 | loss = lovasz_softmax_flat(*flatten_probas(probas, labels, ignore), classes=classes) 170 | return loss 171 | 172 | 173 | def lovasz_softmax_flat(probas, labels, classes='present'): 174 | """ 175 | Multi-class Lovasz-Softmax loss 176 | probas: [P, C] Variable, class probabilities at each prediction (between 0 and 1) 177 | labels: [P] Tensor, ground truth labels (between 0 and C - 1) 178 | classes: 'all' for all, 'present' for classes present in labels, or a list of classes to average. 179 | """ 180 | if probas.numel() == 0: 181 | # only void pixels, the gradients should be 0 182 | return probas * 0. 183 | C = probas.size(1) 184 | losses = [] 185 | class_to_sum = list(range(C)) if classes in ['all', 'present'] else classes 186 | for c in class_to_sum: 187 | fg = (labels == c).float() # foreground for class c 188 | if (classes is 'present' and fg.sum() == 0): 189 | continue 190 | if C == 1: 191 | if len(classes) > 1: 192 | raise ValueError('Sigmoid output possible only with 1 class') 193 | class_pred = probas[:, 0] 194 | else: 195 | class_pred = probas[:, c] 196 | errors = (Variable(fg) - class_pred).abs() 197 | errors_sorted, perm = torch.sort(errors, 0, descending=True) 198 | perm = perm.data 199 | fg_sorted = fg[perm] 200 | losses.append(torch.dot(errors_sorted, Variable(lovasz_grad(fg_sorted)))) 201 | return mean(losses) 202 | 203 | 204 | def flatten_probas(probas, labels, ignore=None): 205 | """ 206 | Flattens predictions in the batch 207 | """ 208 | if probas.dim() == 3: 209 | # assumes output of a sigmoid layer 210 | B, H, W = probas.size() 211 | probas = probas.view(B, 1, H, W) 212 | B, C, H, W = probas.size() 213 | probas = probas.permute(0, 2, 3, 1).contiguous().view(-1, C) # B * H * W, C = P, C 214 | labels = labels.view(-1) 215 | if ignore is None: 216 | return probas, labels 217 | valid = (labels != ignore) 218 | vprobas = probas[valid.nonzero().squeeze()] 219 | vlabels = labels[valid] 220 | return vprobas, vlabels 221 | 222 | 223 | def xloss(logits, labels, ignore=None): 224 | """ 225 | Cross entropy loss 226 | """ 227 | return F.cross_entropy(logits, Variable(labels), ignore_index=255) 228 | 229 | 230 | # --------------------------- HELPER FUNCTIONS --------------------------- 231 | def isnan(x): 232 | return x != x 233 | 234 | 235 | def mean(l, ignore_nan=False, empty=0): 236 | """ 237 | nanmean compatible with generators. 238 | """ 239 | l = iter(l) 240 | if ignore_nan: 241 | l = ifilterfalse(isnan, l) 242 | try: 243 | n = 1 244 | acc = next(l) 245 | except StopIteration: 246 | if empty == 'raise': 247 | raise ValueError('Empty mean') 248 | return empty 249 | for n, v in enumerate(l, 2): 250 | acc += v 251 | if n == 1: 252 | return acc 253 | return acc / n -------------------------------------------------------------------------------- /util/my_loss.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import time 4 | import cv2, math 5 | import numpy as np 6 | import logging 7 | import argparse 8 | import subprocess 9 | 10 | 11 | import torch 12 | import torch.backends.cudnn as cudnn 13 | import torch.nn as nn 14 | import torch.nn.functional as F 15 | import torch.nn.parallel 16 | import torch.optim 17 | import torch.utils.data 18 | from torch.utils.data import Subset, Dataset 19 | import torch.multiprocessing as mp 20 | import torch.distributed as dist 21 | import apex 22 | from tensorboardX import SummaryWriter 23 | 24 | import torchvision 25 | from torchvision.transforms import Compose 26 | from util import dataset, transform, config, augmentation, my_transform 27 | from util.util import AverageMeter, poly_learning_rate, intersectionAndUnionGPU, poly_learning_rate_warmup 28 | from util import ramps 29 | cv2.ocl.setUseOpenCL(False) 30 | cv2.setNumThreads(0) 31 | 32 | 33 | def get_kl_dis_of_same_shape(logits1,logits2): 34 | ''' 35 | 36 | :param logits1: BCHW 37 | :param logits2: BCHW 38 | :return: BHW 39 | ''' 40 | 41 | probas1 = F.log_softmax(logits1, dim=1) 42 | probas2 = F.softmax(logits2, dim=1) 43 | 44 | same_shape_as_input = F.kl_div(probas1, probas2, reduction='none') 45 | kl_dis_matrix = torch.sum(same_shape_as_input, dim=1) 46 | return kl_dis_matrix 47 | 48 | 49 | def get_smoonth_loss(logits, img): 50 | ''' 51 | edge aware smoonth loss for unlabeled data 52 | :param logits: BCHW 53 | :param img: B3HW 54 | :return: (1) 55 | ''' 56 | # import ipdb 57 | # ipdb.set_trace(context=20) 58 | kl_x = get_kl_dis_of_same_shape(logits[:,:,:,:-1], logits[:,:,:,1:]) 59 | kl_y = get_kl_dis_of_same_shape(logits[:,:,:-1,:], logits[:,:,1:,:]) 60 | 61 | grad_img_x = torch.mean(torch.abs(img[:, :, :, :-1] - img[:, :, :, 1:]), 1, keepdim=True) 62 | grad_img_y = torch.mean(torch.abs(img[:, :, :-1, :] - img[:, :, 1:, :]), 1, keepdim=True) 63 | 64 | grad_img_x = torch.squeeze(grad_img_x) 65 | grad_img_y = torch.squeeze(grad_img_y) 66 | 67 | kl_x *= torch.exp(-grad_img_x) 68 | kl_y *= torch.exp(-grad_img_y) 69 | 70 | return kl_x.mean() + kl_y.mean() 71 | 72 | 73 | def get_soft_label_weight_dict_from_npy(max_cf_in_soft_label=0.8): 74 | # every col in soft_matrix is the soft label value to replace hard label 75 | # npy_path = args.confusion_matrix_path 76 | # npy_path = 'initmodel/372_labeled_confusion_matrix_argmax.npy' # setting 0.63 77 | npy_path = 'initmodel/confusion_matrix_372_0.60_argmax.npy' # setting 0.60 78 | confusion_matrix = np.load(npy_path) 79 | for i in range(19): 80 | confusion_matrix[i, i] = 0 81 | 82 | normalized_confusion_matrix = confusion_matrix / confusion_matrix.sum(0) 83 | soft_matrix = np.identity(19) * max_cf_in_soft_label 84 | 85 | # if only_hard_class: 86 | # easy_class = [0,1,2,8,10,13] 87 | # for j in easy_class: 88 | # normalized_confusion_matrix[:,j] = 0 89 | # normalized_confusion_matrix[j,j] = 1 90 | soft_matrix += normalized_confusion_matrix * (1 - max_cf_in_soft_label) 91 | # import ipdb 92 | # ipdb.set_trace(context=20) 93 | return soft_matrix 94 | 95 | 96 | def hard_label_to_soft_label(hard_label, max_cf_in_soft_label=0.8): 97 | ''' 98 | 99 | :param hard_label: B*H*W 100 | :param max_cf_in_soft_label: max value in soft label 101 | :return: soft_label B*H*W*19 102 | ''' 103 | soft_matrix = get_soft_label_weight_dict_from_npy(max_cf_in_soft_label) 104 | soft_label = torch.ones((hard_label.shape[0], hard_label.shape[1], hard_label.shape[2], 19))*255 105 | soft_label = soft_label.cuda() 106 | 107 | # import ipdb 108 | # ipdb.set_trace(context=20) 109 | for j in range(19): 110 | class_j_position = (hard_label == j) 111 | soft_label[class_j_position] = torch.from_numpy(soft_matrix[:, j]).float().cuda() 112 | 113 | return soft_label 114 | 115 | 116 | def hard_label_to_soft_label_top2(hard_label, second_max, max_cf_in_soft_label=0.8): 117 | ''' 118 | 119 | :param hard_label: B*H*W 120 | :param second_max: B*H*W 121 | :param max_cf_in_soft_label: max value in soft label 122 | :return: soft_label B*H*W*19 123 | ''' 124 | soft_label = torch.ones((hard_label.shape[0], hard_label.shape[1], hard_label.shape[2], 19)) * 255 125 | soft_label = soft_label.cuda() 126 | 127 | high_cf_mask = (hard_label == 255) 128 | second_max[high_cf_mask] = 255 129 | 130 | for j in range(19): 131 | 132 | class_j_position_max = (hard_label == j) 133 | vec_max = torch.zeros(19).cuda() 134 | vec_max[j] = max_cf_in_soft_label 135 | soft_label[class_j_position_max] = vec_max 136 | 137 | for j in range(19): 138 | 139 | class_j_position_second_max = (second_max == j) 140 | vec_second_max = torch.zeros(19).cuda() 141 | vec_second_max[j] = 1 - max_cf_in_soft_label 142 | soft_label[class_j_position_second_max] += vec_second_max 143 | 144 | # import ipdb 145 | # ipdb.set_trace(context=20) 146 | return soft_label 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /util/ramps.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def sigmoid_rampup(current, rampup_length): 5 | if rampup_length == 0: 6 | return 1.0 7 | current = np.clip(current, 0.0, rampup_length) 8 | phase = 1.0 - current / rampup_length 9 | return float(np.exp(-5.0 * phase * phase)) 10 | 11 | 12 | def linear_rampup(current, rampup_length): 13 | assert current >= 0 and rampup_length >= 0 14 | if current >= rampup_length: 15 | return 1.0 16 | return current / rampup_length 17 | 18 | 19 | def cosine_rampup(current, rampup_length): 20 | if rampup_length == 0: 21 | return 1.0 22 | current = np.clip(current, 0.0, rampup_length) 23 | return 1 - float(.5 * (np.cos(np.pi * current / rampup_length) + 1)) 24 | 25 | 26 | def log_rampup(current, rampup_length): 27 | if rampup_length == 0: 28 | return 1.0 29 | current = np.clip(current, 0.0, rampup_length) 30 | return float(1 - np.exp(-5.0 * current / rampup_length)) 31 | 32 | 33 | def exp_rampup(current, rampup_length): 34 | if rampup_length == 0: 35 | return 1.0 36 | current = np.clip(current, 0.0, rampup_length) 37 | return float(np.exp(5.0 * (current / rampup_length - 1))) -------------------------------------------------------------------------------- /util/reader.py: -------------------------------------------------------------------------------- 1 | 2 | class DataReader(object): 3 | def __init__(self, dataloader): 4 | self.dataloader = dataloader 5 | 6 | def construct_iter(self): 7 | self.dataloader_iter = iter(self.dataloader) 8 | 9 | 10 | def read_data(self): 11 | try: 12 | return self.dataloader_iter.next() 13 | except: 14 | self.construct_iter() 15 | return self.dataloader_iter.next() 16 | 17 | class DataReader_orig(object): 18 | def __init__(self, dataloader, sampler): 19 | self.dataloader = dataloader 20 | self.sampler = sampler 21 | 22 | def construct_iter(self): 23 | self.dataloader_iter = iter(self.dataloader) 24 | 25 | def set_cur_epoch(self, cur_epoch): 26 | self.cur_epoch = cur_epoch 27 | 28 | def read_data(self): 29 | try: 30 | return self.dataloader_iter.next() 31 | except: 32 | if self.sampler is not None: 33 | self.sampler.set_epoch(self.cur_epoch) 34 | self.construct_iter() 35 | return self.dataloader_iter.next() -------------------------------------------------------------------------------- /util/validate_full_size.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import logging 4 | import argparse 5 | import torch.distributed as dist 6 | import cv2 7 | import numpy as np 8 | import torch 9 | import torch.backends.cudnn as cudnn 10 | import torch.nn.functional as F 11 | import torch.nn.parallel 12 | import torch.utils.data 13 | 14 | from util import dataset, transform, config 15 | from util.util import AverageMeter, intersectionAndUnion, check_makedirs, colorize 16 | 17 | cv2.ocl.setUseOpenCL(False) 18 | 19 | 20 | def net_process(model, image, mean, std=None, flip=True): 21 | input = torch.from_numpy(image.transpose((2, 0, 1))).float() 22 | if std is None: 23 | for t, m in zip(input, mean): 24 | t.sub_(m) 25 | else: 26 | for t, m, s in zip(input, mean, std): 27 | t.sub_(m).div_(s) 28 | input = input.unsqueeze(0).cuda() 29 | if flip: 30 | input = torch.cat([input, input.flip(3)], 0) 31 | with torch.no_grad(): 32 | output = model(input) 33 | _, _, h_i, w_i = input.shape 34 | _, _, h_o, w_o = output.shape 35 | if (h_o != h_i) or (w_o != w_i): 36 | output = F.interpolate(output, (h_i, w_i), mode='bilinear', align_corners=True) 37 | output = F.softmax(output, dim=1) 38 | if flip: 39 | output = (output[0] + output[1].flip(2)) / 2 40 | else: 41 | output = output[0] 42 | output = output.data.cpu().numpy() 43 | output = output.transpose(1, 2, 0) 44 | return output 45 | 46 | 47 | def scale_process(model, image, classes, crop_h, crop_w, h, w, mean, std=None, stride_rate=2/3): 48 | ori_h, ori_w, _ = image.shape 49 | pad_h = max(crop_h - ori_h, 0) 50 | pad_w = max(crop_w - ori_w, 0) 51 | pad_h_half = int(pad_h / 2) 52 | pad_w_half = int(pad_w / 2) 53 | if pad_h > 0 or pad_w > 0: 54 | image = cv2.copyMakeBorder(image, pad_h_half, pad_h - pad_h_half, pad_w_half, pad_w - pad_w_half, cv2.BORDER_CONSTANT, value=mean) 55 | new_h, new_w, _ = image.shape 56 | stride_h = int(np.ceil(crop_h*stride_rate)) 57 | stride_w = int(np.ceil(crop_w*stride_rate)) 58 | grid_h = int(np.ceil(float(new_h-crop_h)/stride_h) + 1) 59 | grid_w = int(np.ceil(float(new_w-crop_w)/stride_w) + 1) 60 | prediction_crop = np.zeros((new_h, new_w, classes), dtype=float) 61 | count_crop = np.zeros((new_h, new_w), dtype=float) 62 | for index_h in range(0, grid_h): 63 | for index_w in range(0, grid_w): 64 | s_h = index_h * stride_h 65 | e_h = min(s_h + crop_h, new_h) 66 | s_h = e_h - crop_h 67 | s_w = index_w * stride_w 68 | e_w = min(s_w + crop_w, new_w) 69 | s_w = e_w - crop_w 70 | image_crop = image[s_h:e_h, s_w:e_w].copy() 71 | count_crop[s_h:e_h, s_w:e_w] += 1 72 | prediction_crop[s_h:e_h, s_w:e_w, :] += net_process(model, image_crop, mean, std) 73 | prediction_crop /= np.expand_dims(count_crop, 2) 74 | prediction_crop = prediction_crop[pad_h_half:pad_h_half+ori_h, pad_w_half:pad_w_half+ori_w] 75 | prediction = cv2.resize(prediction_crop, (w, h), interpolation=cv2.INTER_LINEAR) 76 | return prediction 77 | 78 | 79 | def test(test_loader, data_list, model, classes, mean, std, base_size, crop_h, crop_w, scales, gray_folder, color_folder, colors, names, args): 80 | print('>>>>>>>>>>>>>>>> Validate at full size >>>>>>>>>>>>>>>>') 81 | data_time = AverageMeter() 82 | batch_time = AverageMeter() 83 | model.eval() 84 | check_makedirs(gray_folder) 85 | print('Saving validate prediction to %s' % gray_folder) 86 | end = time.time() 87 | for i, (input, _) in enumerate(test_loader): 88 | data_time.update(time.time() - end) 89 | input = np.squeeze(input.numpy(), axis=0) 90 | image = np.transpose(input, (1, 2, 0)) 91 | h, w, _ = image.shape 92 | prediction = np.zeros((h, w, classes), dtype=float) 93 | for scale in scales: 94 | long_size = round(scale * base_size) 95 | new_h = long_size 96 | new_w = long_size 97 | if h > w: 98 | new_w = round(long_size/float(h)*w) 99 | else: 100 | new_h = round(long_size/float(w)*h) 101 | image_scale = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_LINEAR) 102 | prediction += scale_process(model, image_scale, classes, crop_h, crop_w, h, w, mean, std) 103 | prediction /= len(scales) 104 | prediction = np.argmax(prediction, axis=2) 105 | batch_time.update(time.time() - end) 106 | end = time.time() 107 | 108 | 109 | # check_makedirs(color_folder) 110 | gray = np.uint8(prediction) 111 | # color = colorize(gray, colors) 112 | image_path, _ = data_list[i] 113 | image_name = image_path.split('/')[-1].split('.')[0] 114 | gray_path = os.path.join(gray_folder, image_name + '.png') 115 | color_path = os.path.join(color_folder, image_name + '.png') 116 | cv2.imwrite(gray_path, gray) 117 | # color.save(color_path) 118 | 119 | return cal_acc(data_list, gray_folder, classes, names, args) 120 | 121 | 122 | def cal_acc(data_list, pred_folder, classes, names, args): 123 | intersection_meter = AverageMeter() 124 | union_meter = AverageMeter() 125 | target_meter = AverageMeter() 126 | 127 | for i, (image_path, target_path) in enumerate(data_list): 128 | image_name = image_path.split('/')[-1].split('.')[0] 129 | pred = cv2.imread(os.path.join(pred_folder, image_name+'.png'), cv2.IMREAD_GRAYSCALE) 130 | target = cv2.imread(target_path, cv2.IMREAD_GRAYSCALE) 131 | # print(os.path.join(pred_folder, image_name+'.png')) 132 | if pred is None: 133 | print("pred is None") 134 | continue 135 | intersection, union, target = intersectionAndUnion(pred, target, classes) 136 | intersection_meter.update(intersection) 137 | union_meter.update(union) 138 | target_meter.update(target) 139 | accuracy = sum(intersection_meter.val) / (sum(target_meter.val) + 1e-10) 140 | # logger.info('Evaluating {0}/{1} on image {2}, accuracy {3:.4f}.'.format(i + 1, len(data_list), image_name+'.png', accuracy)) 141 | 142 | iou_class = intersection_meter.sum / (union_meter.sum + 1e-10) 143 | accuracy_class = intersection_meter.sum / (target_meter.sum + 1e-10) 144 | mIoU = np.mean(iou_class) 145 | mAcc = np.mean(accuracy_class) 146 | allAcc = sum(intersection_meter.sum) / (sum(target_meter.sum) + 1e-10) 147 | 148 | print('Eval result: mIoU/mAcc/allAcc {:.4f}/{:.4f}/{:.4f}.'.format(mIoU, mAcc, allAcc)) 149 | for i in range(classes): 150 | print('Class_{} result: iou/accuracy {:.4f}/{:.4f}, name: {}.'.format(i, iou_class[i], accuracy_class[i], names[i])) 151 | return mIoU, mAcc, allAcc 152 | 153 | --------------------------------------------------------------------------------