#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # #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. from __future__ import absolute_import from __future__ import division from __future__ import print_function import paddle.fluid as fluid from paddle.fluid.param_attr import ParamAttr import math __all__ = ["DarkNet53"] class DarkNet53(): def __init__(self): pass def net(self, input, class_dim=1000): DarkNet_cfg = {53: ([1, 2, 8, 8, 4], self.basicblock)} stages, block_func = DarkNet_cfg[53] stages = stages[0:5] conv1 = self.conv_bn_layer( input, ch_out=32, filter_size=3, stride=1, padding=1, name="yolo_input") conv = self.downsample( conv1, ch_out=conv1.shape[1] * 2, name="yolo_input.downsample") for i, stage in enumerate(stages): conv = self.layer_warp( block_func, conv, 32 * (2**i), stage, name="stage.{}".format(i)) if i < len(stages) - 1: # do not downsaple in the last stage conv = self.downsample( conv, ch_out=conv.shape[1] * 2, name="stage.{}.downsample".format(i)) pool = fluid.layers.pool2d( input=conv, pool_type='avg', global_pooling=True) stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) out = fluid.layers.fc( input=pool, size=class_dim, param_attr=ParamAttr( initializer=fluid.initializer.Uniform(-stdv, stdv), name='fc_weights'), bias_attr=ParamAttr(name='fc_offset')) return out def conv_bn_layer(self, input, ch_out, filter_size, stride, padding, name=None): conv = fluid.layers.conv2d( input=input, num_filters=ch_out, filter_size=filter_size, stride=stride, padding=padding, act=None, param_attr=ParamAttr(name=name + ".conv.weights"), bias_attr=False) bn_name = name + ".bn" out = fluid.layers.batch_norm( input=conv, act='relu', param_attr=ParamAttr(name=bn_name + '.scale'), bias_attr=ParamAttr(name=bn_name + '.offset'), moving_mean_name=bn_name + '.mean', moving_variance_name=bn_name + '.var') return out def downsample(self, input, ch_out, filter_size=3, stride=2, padding=1, name=None): return self.conv_bn_layer( input, ch_out=ch_out, filter_size=filter_size, stride=stride, padding=padding, name=name) def basicblock(self, input, ch_out, name=None): conv1 = self.conv_bn_layer(input, ch_out, 1, 1, 0, name=name + ".0") conv2 = self.conv_bn_layer( conv1, ch_out * 2, 3, 1, 1, name=name + ".1") out = fluid.layers.elementwise_add(x=input, y=conv2, act=None) return out def layer_warp(self, block_func, input, ch_out, count, name=None): res_out = block_func(input, ch_out, name='{}.0'.format(name)) for j in range(1, count): res_out = block_func(res_out, ch_out, name='{}.{}'.format(name, j)) return res_out