rpn_head.py 4.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. 
#   
# Licensed under the Apache License, Version 2.0 (the "License");   
# you may not use this file except in compliance with the License.  
# You may obtain a copy of the License at   
#   
#     http://www.apache.org/licenses/LICENSE-2.0    
#   
# Unless required by applicable law or agreed to in writing, software   
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
# See the License for the specific language governing permissions and   
# limitations under the License.

import paddle
import paddle.nn as nn
import paddle.nn.functional as F
from paddle import ParamAttr
from paddle.nn.initializer import Normal
from paddle.regularizer import L2Decay
from paddle.nn import Conv2D

F
FDInSky 已提交
23
from ppdet.core.workspace import register
24
from ppdet.modeling import ops
F
FDInSky 已提交
25 26 27


@register
28
class RPNFeat(nn.Layer):
F
FDInSky 已提交
29 30
    def __init__(self, feat_in=1024, feat_out=1024):
        super(RPNFeat, self).__init__()
31
        # rpn feat is shared with each level
32
        self.rpn_conv = Conv2D(
33 34 35
            in_channels=feat_in,
            out_channels=feat_out,
            kernel_size=3,
F
FDInSky 已提交
36
            padding=1,
37 38
            weight_attr=ParamAttr(initializer=Normal(
                mean=0., std=0.01)),
F
FDInSky 已提交
39
            bias_attr=ParamAttr(
40
                learning_rate=2., regularizer=L2Decay(0.)))
F
FDInSky 已提交
41

42 43 44
    def forward(self, inputs, feats):
        rpn_feats = []
        for feat in feats:
45
            rpn_feats.append(F.relu(self.rpn_conv(feat)))
46
        return rpn_feats
F
FDInSky 已提交
47 48 49


@register
50
class RPNHead(nn.Layer):
F
FDInSky 已提交
51 52
    __inject__ = ['rpn_feat']

53
    def __init__(self, rpn_feat, anchor_per_position=15, rpn_channel=1024):
F
FDInSky 已提交
54 55
        super(RPNHead, self).__init__()
        self.rpn_feat = rpn_feat
56 57 58
        if isinstance(rpn_feat, dict):
            self.rpn_feat = RPNFeat(**rpn_feat)
        # rpn head is shared with each level
F
FDInSky 已提交
59
        # rpn roi classification scores
60
        self.rpn_rois_score = Conv2D(
61 62 63
            in_channels=rpn_channel,
            out_channels=anchor_per_position,
            kernel_size=1,
F
FDInSky 已提交
64
            padding=0,
65 66
            weight_attr=ParamAttr(initializer=Normal(
                mean=0., std=0.01)),
F
FDInSky 已提交
67
            bias_attr=ParamAttr(
68
                learning_rate=2., regularizer=L2Decay(0.)))
F
FDInSky 已提交
69 70

        # rpn roi bbox regression deltas
71
        self.rpn_rois_delta = Conv2D(
72 73 74
            in_channels=rpn_channel,
            out_channels=4 * anchor_per_position,
            kernel_size=1,
F
FDInSky 已提交
75
            padding=0,
76 77
            weight_attr=ParamAttr(initializer=Normal(
                mean=0., std=0.01)),
F
FDInSky 已提交
78
            bias_attr=ParamAttr(
79
                learning_rate=2., regularizer=L2Decay(0.)))
F
FDInSky 已提交
80

81 82 83 84 85 86 87 88
    def forward(self, inputs, feats):
        rpn_feats = self.rpn_feat(inputs, feats)
        rpn_head_out = []
        for rpn_feat in rpn_feats:
            rrs = self.rpn_rois_score(rpn_feat)
            rrd = self.rpn_rois_delta(rpn_feat)
            rpn_head_out.append((rrs, rrd))
        return rpn_feats, rpn_head_out
F
FDInSky 已提交
89

K
Kaipeng Deng 已提交
90
    def get_loss(self, loss_inputs):
F
FDInSky 已提交
91
        # cls loss
92
        score_tgt = paddle.cast(
93 94
            x=loss_inputs['rpn_score_target'], dtype='float32')
        score_tgt.stop_gradient = True
95 96 97
        loss_rpn_cls = ops.sigmoid_cross_entropy_with_logits(
            input=loss_inputs['rpn_score_pred'], label=score_tgt)
        loss_rpn_cls = paddle.mean(loss_rpn_cls, name='loss_rpn_cls')
F
FDInSky 已提交
98 99

        # reg loss
100
        loc_tgt = paddle.cast(x=loss_inputs['rpn_rois_target'], dtype='float32')
101
        loc_tgt.stop_gradient = True
102 103 104
        loss_rpn_reg = ops.smooth_l1(
            input=loss_inputs['rpn_rois_pred'],
            label=loc_tgt,
105
            inside_weight=loss_inputs['rpn_rois_weight'],
106 107 108 109 110 111
            outside_weight=loss_inputs['rpn_rois_weight'],
            sigma=3.0, )
        loss_rpn_reg = paddle.sum(loss_rpn_reg)
        score_shape = paddle.shape(score_tgt)
        score_shape = paddle.cast(score_shape, dtype='float32')
        norm = paddle.prod(score_shape)
112 113
        norm.stop_gradient = True
        loss_rpn_reg = loss_rpn_reg / norm
F
FDInSky 已提交
114

115
        return {'loss_rpn_cls': loss_rpn_cls, 'loss_rpn_reg': loss_rpn_reg}