Skip to content

Commit 7cf51ce

Browse files
authored
Add DecoupledSegNet
1 parent dfc89e5 commit 7cf51ce

16 files changed

Lines changed: 737 additions & 19 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Welcome to PaddleSeg! PaddleSeg is an end-to-end image segmentation development
4040
|[U<sup>2</sup>-Net](./configs/u2net)|-|-|-|-|
4141
|[Att U-Net](./configs/attention_unet)|-|-|-|-|
4242
|[U-Net++](./configs/unet_plusplus)|-|-|-|-|
43+
|[DecoupledSegNet](./configs/decoupled_segnet)|||||
4344

4445
## Dataset
4546

README_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ PaddleSeg是基于飞桨[PaddlePaddle](https://www.paddlepaddle.org.cn)开发的
4040
|[U<sup>2</sup>-Net](./configs/u2net)|-|-|-|-|
4141
|[Att U-Net](./configs/attention_unet)|-|-|-|-|
4242
|[U-Net++](./configs/unet_plusplus)|-|-|-|-|
43+
|[DecoupledSegNet](./configs/decoupled_segnet)|||||
4344

4445
## 数据集
4546

configs/decoupled_segnet/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Improving Semantic Segmentation via Decoupled Body and Edge Supervision
2+
3+
## Reference
4+
5+
> Li X, Li X, Zhang L, et al. Improving semantic segmentation via decoupled body and edge supervision[J]. arXiv preprint arXiv:2007.10035, 2020.
6+
7+
## Performance
8+
9+
### Cityscapes
10+
11+
| Model | Backbone | Resolution | Training Iters | mIoU | mIoU (flip) | mIoU (ms+flip) | Links |
12+
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
13+
|DecoupledSegNet|ResNet50_OS8|1024x512|80000|80.86%|81.34%|81.49%|[model](https://bj.bcebos.com/paddleseg/dygraph/cityscapes/decoupledsegnet_resnet50_os8_cityscapes_1024x512_80k/model.pdparams) \| [log](https://bj.bcebos.com/paddleseg/dygraph/cityscapes/decoupledsegnet_resnet50_os8_cityscapes_1024x512_80k/train.log) \| [vdl](https://www.paddlepaddle.org.cn/paddle/visualdl/service/app/scalar?id=3c5cba5e6f89b33dc75b43c62026dc12)|
14+
|DecoupledSegNet|ResNet50_OS8|832x832|80000|81.26%|81.56%|81.80%|[model](https://bj.bcebos.com/paddleseg/dygraph/cityscapes/decoupledsegnet_resnet50_os8_cityscapes_832x832_80k/model.pdparams) \| [log](https://bj.bcebos.com/paddleseg/dygraph/cityscapes/decoupledsegnet_resnet50_os8_cityscapes_832x832_80k/train.log) \| [vdl](https://paddlepaddle.org.cn/paddle/visualdl/service/app?id=e3e8f9044d96a57f7337f5928f2c265f)|
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
_base_: '../_base_/cityscapes.yml'
2+
3+
model:
4+
type: DecoupledSegNet
5+
backbone:
6+
type: ResNet50_vd
7+
output_stride: 8
8+
multi_grid: [1, 2, 4]
9+
pretrained: https://bj.bcebos.com/paddleseg/dygraph/resnet50_vd_ssld_v2.tar.gz
10+
num_classes: 19
11+
backbone_indices: [0, 3]
12+
aspp_ratios: [1, 12, 24, 36]
13+
aspp_out_channels: 256
14+
align_corners: False
15+
pretrained: null
16+
17+
loss:
18+
types:
19+
- type: OhemCrossEntropyLoss
20+
- type: RelaxBoundaryLoss
21+
- type: BCELoss
22+
weight: 'dynamic'
23+
edge_label: True
24+
- type: OhemEdgeAttentionLoss
25+
coef: [1,1,25,1]
26+
27+
train_dataset:
28+
edge: True
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
_base_: '../_base_/cityscapes.yml'
2+
3+
model:
4+
type: DecoupledSegNet
5+
backbone:
6+
type: ResNet50_vd
7+
output_stride: 8
8+
multi_grid: [1, 2, 4]
9+
pretrained: https://bj.bcebos.com/paddleseg/dygraph/resnet50_vd_ssld_v2.tar.gz
10+
num_classes: 19
11+
backbone_indices: [0, 3]
12+
aspp_ratios: [1, 12, 24, 36]
13+
aspp_out_channels: 256
14+
align_corners: False
15+
pretrained: null
16+
17+
loss:
18+
types:
19+
- type: OhemCrossEntropyLoss
20+
- type: RelaxBoundaryLoss
21+
- type: BCELoss
22+
weight: 'dynamic'
23+
edge_label: True
24+
- type: OhemEdgeAttentionLoss
25+
coef: [1,1,25,1]
26+
27+
train_dataset:
28+
transforms:
29+
- type: ResizeStepScaling
30+
min_scale_factor: 0.75
31+
max_scale_factor: 2.0
32+
scale_step_size: 0.25
33+
- type: RandomPaddingCrop
34+
crop_size: [832, 832]
35+
- type: RandomHorizontalFlip
36+
- type: RandomDistort
37+
brightness_range: 0.4
38+
contrast_range: 0.4
39+
saturation_range: 0.4
40+
- type: Normalize
41+
edge: True
42+
43+
optimizer:
44+
weight_decay: 5.0e-4

docs/apis/models.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The models subpackage contains the following model for image sementic segmentaio
1818
- [U<sup>2</sup>Net+](#U2Net-1)
1919
- [AttentionUNet](#AttentionUNet)
2020
- [UNet++](#UNet-1)
21+
- [DecoupledSegNet](#DecoupledSegNet)
2122

2223
## [DeepLabV3+](../../paddleseg/models/deeplab.py)
2324
> CLASS paddleseg.models.DeepLabV3P(num_classes, backbone, backbone_indices=(0, 3), aspp_ratios=(1, 6, 12, 18), aspp_out_channels=256, align_corners=False, pretrained=None)
@@ -402,3 +403,32 @@ The models subpackage contains the following model for image sementic segmentaio
402403
is even, e.g. 1024x512, otherwise it is True, e.g. 769x769. Default: False.
403404
> > > - **pretrained** (str, optional): The path or url of pretrained model for fine tuning. Default: None.
404405
> > > - **is_ds** (bool): use deep supervision or not. Default: True
406+
407+
## [DecoupledSegNet](../../paddleseg/models/decoupled_segnet.py)
408+
> class DecoupledSegNet(num_classes,
409+
backbone,
410+
backbone_indices=(0, 3),
411+
aspp_ratios=(1, 6, 12, 18),
412+
aspp_out_channels=256,
413+
align_corners=False,
414+
pretrained=None)
415+
416+
The DecoupledSegNet implementation based on PaddlePaddle.
417+
418+
The original article refers to
419+
Xiangtai Li, et, al. "Improving Semantic Segmentation via Decoupled Body and Edge Supervision"
420+
(https://arxiv.org/pdf/2007.10035.pdf)
421+
422+
> > Args
423+
> > > - **num_classes** (int): The unique number of target classes.
424+
> > > - **backbone** (paddle.nn.Layer): Backbone network, currently support Resnet50_vd/Resnet101_vd.
425+
> > > - **backbone_indices** (tuple, optional): Two values in the tuple indicate the indices of output of backbone.
426+
Default: (0, 3).
427+
> > > - **aspp_ratios** (tuple, optional): The dilation rate using in ASSP module.
428+
If output_stride=16, aspp_ratios should be set as (1, 6, 12, 18).
429+
If output_stride=8, aspp_ratios is (1, 12, 24, 36).
430+
Default: (1, 6, 12, 18).
431+
> > > - **aspp_out_channels** (int, optional): The output channels of ASPP module. Default: 256.
432+
> > > - **align_corners** (bool, optional): An argument of F.interpolate. It should be set to False when the feature size is even,
433+
e.g. 1024x512, otherwise it is True, e.g. 769x769. Default: False.
434+
> > > - **pretrained** (str, optional): The path or url of pretrained model. Default: None.

paddleseg/core/train.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ def check_logits_losses(logits_list, losses):
3535

3636
def loss_computation(logits_list, labels, losses, edges=None):
3737
check_logits_losses(logits_list, losses)
38-
loss = 0
38+
loss_list = []
3939
for i in range(len(logits_list)):
4040
logits = logits_list[i]
4141
loss_i = losses['types'][i]
42-
# Whether to use edges as labels According to loss type .
42+
# Whether to use edges as labels According to loss type.
4343
if loss_i.__class__.__name__ in ('BCELoss', ) and loss_i.edge_label:
44-
loss += losses['coef'][i] * loss_i(logits, edges)
44+
loss_list.append(losses['coef'][i] * loss_i(logits, edges))
4545
else:
46-
loss += losses['coef'][i] * loss_i(logits, labels)
47-
return loss
46+
loss_list.append(losses['coef'][i] * loss_i(logits, labels))
47+
return loss_list
4848

4949

5050
def train(model,
@@ -115,6 +115,7 @@ def train(model,
115115

116116
timer = Timer()
117117
avg_loss = 0.0
118+
avg_loss_list = []
118119
iters_per_epoch = len(batch_sampler)
119120
best_mean_iou = -1.0
120121
best_model_iter = -1
@@ -140,11 +141,12 @@ def train(model,
140141
logits_list = ddp_model(images)
141142
else:
142143
logits_list = model(images)
143-
loss = loss_computation(
144+
loss_list = loss_computation(
144145
logits_list=logits_list,
145146
labels=labels,
146147
losses=losses,
147148
edges=edges)
149+
loss = sum(loss_list)
148150
loss.backward()
149151

150152
optimizer.step()
@@ -154,10 +156,18 @@ def train(model,
154156
optimizer._learning_rate.step()
155157
model.clear_gradients()
156158
avg_loss += loss.numpy()[0]
159+
if not avg_loss_list:
160+
avg_loss_list = [l for l in loss_list]
161+
else:
162+
for i in range(len(loss_list)):
163+
avg_loss_list[i] += loss_list[i]
157164
train_batch_cost += timer.elapsed_time()
158165

159166
if (iter) % log_iters == 0 and local_rank == 0:
160167
avg_loss /= log_iters
168+
avg_loss_list = [
169+
l.numpy()[0] / log_iters for l in avg_loss_list
170+
]
161171
avg_train_reader_cost = train_reader_cost / log_iters
162172
avg_train_batch_cost = train_batch_cost / log_iters
163173
train_reader_cost = 0.0
@@ -171,12 +181,22 @@ def train(model,
171181
avg_train_reader_cost, eta))
172182
if use_vdl:
173183
log_writer.add_scalar('Train/loss', avg_loss, iter)
184+
# Record all losses if there are more than 2 losses.
185+
if len(avg_loss_list) > 1:
186+
avg_loss_dict = {}
187+
for i, value in enumerate(avg_loss_list):
188+
avg_loss_dict['loss_' + str(i)] = value
189+
for key, value in avg_loss_dict.items():
190+
log_tag = 'Train/' + key
191+
log_writer.add_scalar(log_tag, value, iter)
192+
174193
log_writer.add_scalar('Train/lr', lr, iter)
175194
log_writer.add_scalar('Train/batch_cost',
176195
avg_train_batch_cost, iter)
177196
log_writer.add_scalar('Train/reader_cost',
178197
avg_train_reader_cost, iter)
179198
avg_loss = 0.0
199+
avg_loss_list = []
180200

181201
if (iter % save_interval == 0
182202
or iter == iters) and (val_dataset is not None):

paddleseg/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@
3030
from .u2net import U2Net, U2Netp
3131
from .attention_unet import AttentionUNet
3232
from .unet_plusplus import UNetPlusPlus
33+
from .decoupled_segnet import DecoupledSegNet

0 commit comments

Comments
 (0)