SegFormer
repository·master·Indexed 25 days ago
https://github.com/nvlabs/segformerA simple, efficient, and powerful semantic segmentation method using Transformers. This official PyTorch implementation is built upon the MMSegmentation codebase and provides tools for training and evaluation, along with a wide array of pre-trained models for datasets including Cityscapes, ADE20K, and Pascal VOC 2012.
What's inside SegFormer
- This configuration directory provides the setup to reproduce the results from the paper "Disentangled Non-Local Neural Networks" for semantic segmentation. The implementation is currently in progress.
Prepare a model for publishing
masterUse
tools/publish_model.pyto prepare model weights for upload (e.g., to AWS). This script performs the following:- Converts model weights to CPU tensors.
- Deletes optimizer states.
- Computes the hash of the checkpoint file and appends the hash ID to the filename.
Example usage:
python tools/publish_model.py work_dirs/pspnet/latest.pth psp_r50_hszhao_200ep.pthIf the input is
psp_r50_hszhao_200ep.pth, the final output filename will include a hash ID, such aspsp_r50_512x1024_40ki_cityscapes-{hash id}.pth.python tools/publish_model.py ${INPUT_FILENAME} ${OUTPUT_FILENAME}Customize the optimizer constructor
masterFor fine-grained parameter tuning (e.g., different weight decay for specific layers like BatchNorm), you can implement a custom optimizer constructor. Use the
@OPTIMIZER_BUILDERS.register_moduledecorator. The class should implement a__call__(self, model)method that returns the configured optimizer instance.from mmcv.utils import build_from_cfg from mmcv.runner import OPTIMIZER_BUILDERS @OPTIMIZER_BUILDERS.register_module class CocktailOptimizerConstructor(object): def __init__(self, optimizer_cfg, paramwise_cfg=None): self.optimizer_cfg = optimizer_cfg self.paramwise_cfg = paramwise_cfg def __call__(self, model): # return configured optimizer return my_optimizerGenerate PNG files for Cityscapes official evaluation
masterTo generate PNG files for submission to the official Cityscapes evaluation server using multi-GPU testing, follow these steps:
- Update your config file (e.g.,
configs/pspnet/pspnet_r50-d8_512x1024_40k_cityscapes.py) to include the test directory paths:
data = dict( test=dict( img_dir='leftImg8bit/test', ann_dir='gtFine/test'))- Run the distributed test script with the
--format-onlyflag and specify an output prefix via--eval-options:
./tools/dist_test.sh configs/pspnet/pspnet_r50-d8_512x1024_40k_cityscapes.py \ checkpoints/pspnet_r50-d8_512x1024_40k_cityscapes_20200605_003338-2966598c.pth \ 4 --format-only --eval-options "imgfile_prefix=./pspnet_test_results"- The PNG files will be located in the
./pspnet_test_resultsdirectory. You can then zip this directory for submission.
./tools/dist_test.sh configs/pspnet/pspnet_r50-d8_512x1024_40k_cityscapes.py \ checkpoints/pspnet_r50-d8_512x1024_40k_cityscapes_20200605_003338-2966598c.pth \ 4 --format-only --eval-options "imgfile_prefix=./pspnet_test_results"- Update your config file (e.g.,
Add a new loss function
masterTo add a custom loss function:
- Implement the loss logic in a new file (e.g.,
mmseg/models/losses/my_loss.py). - Use the
@weighted_lossdecorator on the functional implementation to enable element-wise weighting. - Define a class inheriting from
torch.nn.Moduledecorated with@LOSSES.register_module. - Implement
__init__andforward(acceptingpred,target,weight,avg_factor, andreduction_override). - Import the module in
mmseg/models/losses/__init__.py. - Use it in your config by setting the
loss_decodefield in thedecode_headtodict(type='MyLoss', ...).
import torch import torch.nn as nn from ..builder import LOSSES from .utils import weighted_loss @weighted_loss def my_loss(pred, target): assert pred.size() == target.size() and target.numel() > 0 loss = torch.abs(pred - target) return loss @LOSSES.register_module class MyLoss(nn.Module): def __init__(self, reduction='mean', loss_weight=1.0): super(MyLoss, self).__init__() self.reduction = reduction self.loss_weight = loss_weight def forward(self, pred, target, weight=None, avg_factor=None, reduction_override=None): reduction = reduction_override if reduction_override else self.reduction loss = self.loss_weight * my_loss( pred, target, weight, reduction=reduction, avg_factor=avg_factor) return lossIn your config file:
loss_decode=dict(type='MyLoss', loss_weight=1.0)
- Implement the loss logic in a new file (e.g.,
Install SegFormer/MMSegmentation on Windows (Experimental)
masterWindows support is experimental. Ensure you have a native C++ compiler (like
cl.exe) and that it is added to your%PATH%.- Create and activate a conda environment:
conda create -n open-mmlab python=3.7 -y conda activate open-mmlab- Install PyTorch and torchvision:
conda install pytorch=1.6.0 torchvision cudatoolkit=10.1 -c pytorch- Install MMCV:
mmcv-fullis not supported on Windows. Installmmcvvia pip:pip install mmcv- Install MMSegmentation:
git clone https://github.com/open-mmlab/mmsegmentation.git cd mmsegmentation pip install -e .Important Windows Notes:
- Replace all backslashes
\in paths with forward slashes/in your Python code (e.g., using.replace('\', '/')). - Use absolute paths when linking datasets via
mklink.
conda create -n open-mmlab python=3.7 -y conda activate open-mmlab conda install pytorch=1.6.0 torchvision cudatoolkit=10.1 -c pytorch set PATH=full\path\to\your\cpp\compiler;%PATH% pip install mmcv git clone https://github.com/open-mmlab/mmsegmentation.git cd mmsegmentation pip install -e . mklink /D data %DATA_ROOT%Add a new segmentation head
masterTo implement a new segmentation decode head:
- Create a new file in
mmseg/models/decode_heads/. - Define a class that inherits from
BaseDecodeHeadand decorate it with@HEADS.register_module(). - Implement
__init__,init_weights, andforward. - Import the module in
mmseg/models/decode_heads/__init__.py. - Configure it in your model config under the
decode_headfield.
from .decode_head import BaseDecodeHead from ..registry import HEADS @HEADS.register_module() class PSPHead(BaseDecodeHead): def __init__(self, pool_scales=(1, 2, 3, 6), **kwargs): super(PSPHead, self).__init__(**kwargs) def init_weights(self): pass def forward(self, inputs): passIn your config file:
model = dict( decode_head=dict( type='PSPHead', in_channels=2048, in_index=3, channels=512, pool_scales=(1, 2, 3, 6), num_classes=19, ...) )
- Create a new file in
Prepare Pascal Context dataset
masterTo use the Pascal Context dataset, first install the
DetailAPI. Then, use the conversion script with thetrainval_merged.jsonfile to format the annotations correctly.python tools/convert_datasets/pascal_context.py data/VOCdevkit data/VOCdevkit/VOC2010/trainval_merged.jsonApply different learning rates for backbone and heads
masterTo improve performance or convergence, you can set a different learning rate for the model heads compared to the backbone. In MMSegmentation, use
paramwise_cfgwithin theoptimizerdictionary to apply a multiplier (lr_mult) to specific parameter groups based on their names. For example, to make the learning rate of the heads 10 times larger than the backbone, addcustom_keyswith'head'to the configuration.optimizer=dict( paramwise_cfg = dict( custom_keys={ 'head': dict(lr_mult=10.)}))Run speed benchmarks
masterTo compute the average inference time (including network forwarding and post-processing, but excluding data loading), use thetools/benchmark.pyscript. The benchmark is typically performed on 200 images withtorch.backends.cudnn.benchmark=Falseto ensure consistency.Convert a PyTorch model to ONNX format
masterUse the experimental
tools/pytorch2onnx.pyscript to convert a model to ONNX format. The resulting model can be visualized using tools like Netron. The script also supports verifying the output results by comparing the PyTorch and ONNX models.Note: This tool is experimental and some customized operators are currently unsupported.
python tools/pytorch2onnx.py ${CONFIG_FILE} --checkpoint ${CHECKPOINT_FILE} --output-file ${ONNX_FILE} [--shape ${INPUT_SHAPE} --verify]Prepare Cityscapes dataset
masterAfter downloading the Cityscapes dataset, use the conversion script to generate
**labelTrainIds.pngfiles required for training. You can specify the number of processes using--nprocto speed up conversion.# --nproc means 8 process for conversion, which could be omitted as well. python tools/convert_datasets/cityscapes.py data/cityscapes --nproc 8