未验证 提交 a9970268 编写于 作者: K Kaipeng Deng 提交者: GitHub

Merge pull request #81 from heavengate/fix_yolov3

fix yolov3
...@@ -12,12 +12,11 @@ ...@@ -12,12 +12,11 @@
#See the License for the specific language governing permissions and #See the License for the specific language governing permissions and
#limitations under the License. #limitations under the License.
import math
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay from paddle.fluid.regularizer import L2Decay
from paddle.fluid.dygraph.nn import Conv2D, BatchNorm, Pool2D, Linear from paddle.fluid.dygraph.nn import Conv2D, BatchNorm
from paddle.incubate.hapi.model import Model from paddle.incubate.hapi.model import Model
from paddle.incubate.hapi.download import get_weights_path_from_url from paddle.incubate.hapi.download import get_weights_path_from_url
...@@ -25,10 +24,9 @@ from paddle.incubate.hapi.download import get_weights_path_from_url ...@@ -25,10 +24,9 @@ from paddle.incubate.hapi.download import get_weights_path_from_url
__all__ = ['DarkNet', 'darknet53'] __all__ = ['DarkNet', 'darknet53']
# {num_layers: (url, md5)} # {num_layers: (url, md5)}
model_urls = { pretrain_infos = {
'darknet53': 53: ('https://paddlemodels.bj.bcebos.com/hapi/darknet53.pdparams',
('https://paddle-hapi.bj.bcebos.com/models/darknet53.pdparams', '2506357a5c31e865785112fc614a487d')
'ca506a90e2efecb9a2093f8ada808708')
} }
...@@ -68,14 +66,17 @@ class ConvBNLayer(fluid.dygraph.Layer): ...@@ -68,14 +66,17 @@ class ConvBNLayer(fluid.dygraph.Layer):
def forward(self, inputs): def forward(self, inputs):
out = self.conv(inputs) out = self.conv(inputs)
out = self.batch_norm(out) out = self.batch_norm(out)
if self.act == 'leaky': if self.act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1) out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out return out
class DownSample(fluid.dygraph.Layer): class DownSample(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out, filter_size=3, stride=2, padding=1): def __init__(self,
ch_in,
ch_out,
filter_size=3,
stride=2,
padding=1):
super(DownSample, self).__init__() super(DownSample, self).__init__()
...@@ -86,45 +87,46 @@ class DownSample(fluid.dygraph.Layer): ...@@ -86,45 +87,46 @@ class DownSample(fluid.dygraph.Layer):
stride=stride, stride=stride,
padding=padding) padding=padding)
self.ch_out = ch_out self.ch_out = ch_out
def forward(self, inputs): def forward(self, inputs):
out = self.conv_bn_layer(inputs) out = self.conv_bn_layer(inputs)
return out return out
class BasicBlock(fluid.dygraph.Layer): class BasicBlock(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out): def __init__(self, ch_in, ch_out):
super(BasicBlock, self).__init__() super(BasicBlock, self).__init__()
self.conv1 = ConvBNLayer( self.conv1 = ConvBNLayer(
ch_in=ch_in, ch_out=ch_out, filter_size=1, stride=1, padding=0) ch_in=ch_in,
ch_out=ch_out,
filter_size=1,
stride=1,
padding=0)
self.conv2 = ConvBNLayer( self.conv2 = ConvBNLayer(
ch_in=ch_out, ch_in=ch_out,
ch_out=ch_out * 2, ch_out=ch_out*2,
filter_size=3, filter_size=3,
stride=1, stride=1,
padding=1) padding=1)
def forward(self, inputs): def forward(self, inputs):
conv1 = self.conv1(inputs) conv1 = self.conv1(inputs)
conv2 = self.conv2(conv1) conv2 = self.conv2(conv1)
out = fluid.layers.elementwise_add(x=inputs, y=conv2, act=None) out = fluid.layers.elementwise_add(x=inputs, y=conv2, act=None)
return out return out
class LayerWarp(fluid.dygraph.Layer): class LayerWarp(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out, count): def __init__(self, ch_in, ch_out, count):
super(LayerWarp, self).__init__() super(LayerWarp,self).__init__()
self.basicblock0 = BasicBlock(ch_in, ch_out) self.basicblock0 = BasicBlock(ch_in, ch_out)
self.res_out_list = [] self.res_out_list = []
for i in range(1, count): for i in range(1,count):
res_out = self.add_sublayer("basic_block_%d" % (i), res_out = self.add_sublayer("basic_block_%d" % (i),
BasicBlock(ch_out * 2, ch_out)) BasicBlock(
ch_out*2,
ch_out))
self.res_out_list.append(res_out) self.res_out_list.append(res_out)
self.ch_out = ch_out self.ch_out = ch_out
def forward(self,inputs):
def forward(self, inputs):
y = self.basicblock0(inputs) y = self.basicblock0(inputs)
for basic_block_i in self.res_out_list: for basic_block_i in self.res_out_list:
y = basic_block_i(y) y = basic_block_i(y)
...@@ -140,100 +142,78 @@ class DarkNet(Model): ...@@ -140,100 +142,78 @@ class DarkNet(Model):
Args: Args:
num_layers (int): layer number of DarkNet, only 53 supported currently, default: 53. num_layers (int): layer number of DarkNet, only 53 supported currently, default: 53.
num_classes (int): output dim of last fc layer. If num_classes <=0, last fc layer ch_in (int): channel number of input data, default 3.
will not be defined. Default: 1000.
with_pool (bool): use pool before the last fc layer or not. Default: True.
classifier_activation (str): activation for the last fc layer. Default: 'softmax'.
""" """
def __init__(self, def __init__(self, num_layers=53, ch_in=3):
num_layers=53,
num_classes=1000,
with_pool=True,
classifier_activation='softmax'):
super(DarkNet, self).__init__() super(DarkNet, self).__init__()
assert num_layers in DarkNet_cfg.keys(), \ assert num_layers in DarkNet_cfg.keys(), \
"only support num_layers in {} currently" \ "only support num_layers in {} currently" \
.format(DarkNet_cfg.keys()) .format(DarkNet_cfg.keys())
self.stages = DarkNet_cfg[num_layers] self.stages = DarkNet_cfg[num_layers]
self.stages = self.stages[0:5] self.stages = self.stages[0:5]
self.num_classes = num_classes
self.with_pool = True
ch_in = 3
self.conv0 = ConvBNLayer( self.conv0 = ConvBNLayer(
ch_in=ch_in, ch_out=32, filter_size=3, stride=1, padding=1) ch_in=ch_in,
ch_out=32,
filter_size=3,
stride=1,
padding=1)
self.downsample0 = DownSample(ch_in=32, ch_out=32 * 2) self.downsample0 = DownSample(
ch_in=32,
ch_out=32 * 2)
self.darknet53_conv_block_list = [] self.darknet53_conv_block_list = []
self.downsample_list = [] self.downsample_list = []
ch_in = [64, 128, 256, 512, 1024] ch_in = [64,128,256,512,1024]
for i, stage in enumerate(self.stages): for i, stage in enumerate(self.stages):
conv_block = self.add_sublayer("stage_%d" % (i), conv_block = self.add_sublayer(
"stage_%d" % (i),
LayerWarp( LayerWarp(
int(ch_in[i]), 32 * (2**i), int(ch_in[i]),
32*(2**i),
stage)) stage))
self.darknet53_conv_block_list.append(conv_block) self.darknet53_conv_block_list.append(conv_block)
for i in range(len(self.stages) - 1): for i in range(len(self.stages) - 1):
downsample = self.add_sublayer( downsample = self.add_sublayer(
"stage_%d_downsample" % i, "stage_%d_downsample" % i,
DownSample( DownSample(
ch_in=32 * (2**(i + 1)), ch_out=32 * (2**(i + 2)))) ch_in = 32*(2**(i+1)),
ch_out = 32*(2**(i+2))))
self.downsample_list.append(downsample) self.downsample_list.append(downsample)
if self.with_pool: def forward(self,inputs):
self.global_pool = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True)
if self.num_classes > 0:
stdv = 1.0 / math.sqrt(32 * (2**(i + 2)))
self.fc_input_dim = 32 * (2**(i + 2))
self.fc = Linear(
self.fc_input_dim,
num_classes,
act='softmax',
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv)))
def forward(self, inputs):
out = self.conv0(inputs) out = self.conv0(inputs)
out = self.downsample0(out) out = self.downsample0(out)
blocks = []
for i, conv_block_i in enumerate(self.darknet53_conv_block_list): for i, conv_block_i in enumerate(self.darknet53_conv_block_list):
out = conv_block_i(out) out = conv_block_i(out)
blocks.append(out)
if i < len(self.stages) - 1: if i < len(self.stages) - 1:
out = self.downsample_list[i](out) out = self.downsample_list[i](out)
return blocks[-1:-4:-1]
if self.with_pool:
out = self.global_pool(out)
if self.num_classes > 0:
out = fluid.layers.reshape(out, shape=[-1, self.fc_input_dim])
out = self.fc(out)
return out
def _darknet(arch, num_layers=53, pretrained=False, **kwargs): def _darknet(num_layers=53, input_channels=3, pretrained=True):
model = DarkNet(num_layers, **kwargs) model = DarkNet(num_layers, input_channels)
if pretrained: if pretrained:
assert arch in model_urls, "{} model do not have a pretrained model now, you should set pretrained=False".format( assert num_layers in pretrain_infos.keys(), \
arch) "DarkNet{} do not have pretrained weights now, " \
weight_path = get_weights_path_from_url(*(model_urls[arch])) "pretrained should be set as False".format(num_layers)
weight_path = get_weights_path_from_url(*(pretrain_infos[num_layers]))
assert weight_path.endswith('.pdparams'), \ assert weight_path.endswith('.pdparams'), \
"suffix of weight must be .pdparams" "suffix of weight must be .pdparams"
model.load(weight_path) model.load(weight_path[:-9])
return model return model
def darknet53(pretrained=False, **kwargs): def darknet53(input_channels=3, pretrained=True):
"""DarkNet 53-layer model """DarkNet 53-layer model
Args: Args:
input_channels (bool): channel number of input data, default 3. input_channels (bool): channel number of input data, default 3.
pretrained (bool): If True, returns a model pre-trained on ImageNet, pretrained (bool): If True, returns a model pre-trained on ImageNet,
default True. default True.
""" """
return _darknet('darknet53', 53, pretrained, **kwargs) return _darknet(53, input_channels, pretrained)
...@@ -215,7 +215,7 @@ if __name__ == '__main__': ...@@ -215,7 +215,7 @@ if __name__ == '__main__':
metavar='LR', metavar='LR',
help='initial learning rate') help='initial learning rate')
parser.add_argument( parser.add_argument(
"-b", "--batch_size", default=8, type=int, help="batch size") "-b", "--batch_size", default=16, type=int, help="batch size")
parser.add_argument( parser.add_argument(
"-j", "-j",
"--num_workers", "--num_workers",
......
...@@ -20,9 +20,9 @@ from paddle.fluid.dygraph.nn import Conv2D, BatchNorm ...@@ -20,9 +20,9 @@ from paddle.fluid.dygraph.nn import Conv2D, BatchNorm
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay from paddle.fluid.regularizer import L2Decay
from hapi.model import Model from paddle.incubate.hapi.model import Model
from hapi.loss import Loss from paddle.incubate.hapi.loss import Loss
from hapi.download import get_weights_path_from_url from paddle.incubate.hapi.download import get_weights_path_from_url
from darknet import darknet53 from darknet import darknet53
__all__ = ['YoloLoss', 'YOLOv3', 'yolov3_darknet53'] __all__ = ['YoloLoss', 'YOLOv3', 'yolov3_darknet53']
...@@ -158,10 +158,7 @@ class YOLOv3(Model): ...@@ -158,10 +158,7 @@ class YOLOv3(Model):
self.nms_posk = 100 self.nms_posk = 100
self.draw_thresh = 0.5 self.draw_thresh = 0.5
self.backbone = darknet53( self.backbone = darknet53(pretrained=(model_mode == 'train'))
pretrained=(model_mode == 'train'),
with_pool=False,
num_classes=-1)
self.block_outputs = [] self.block_outputs = []
self.yolo_blocks = [] self.yolo_blocks = []
self.route_blocks = [] self.route_blocks = []
...@@ -300,7 +297,7 @@ class YoloLoss(Loss): ...@@ -300,7 +297,7 @@ class YoloLoss(Loss):
anchors=self.anchors, anchors=self.anchors,
class_num=self.num_classes, class_num=self.num_classes,
ignore_thresh=self.ignore_thresh, ignore_thresh=self.ignore_thresh,
use_label_smooth=True) use_label_smooth=False)
loss = fluid.layers.reduce_mean(loss) loss = fluid.layers.reduce_mean(loss)
losses.append(loss) losses.append(loss)
downsample //= 2 downsample //= 2
......
...@@ -16,19 +16,16 @@ from . import resnet ...@@ -16,19 +16,16 @@ from . import resnet
from . import vgg from . import vgg
from . import mobilenetv1 from . import mobilenetv1
from . import mobilenetv2 from . import mobilenetv2
from . import darknet
from . import lenet from . import lenet
from .resnet import * from .resnet import *
from .mobilenetv1 import * from .mobilenetv1 import *
from .mobilenetv2 import * from .mobilenetv2 import *
from .vgg import * from .vgg import *
from .darknet import *
from .lenet import * from .lenet import *
__all__ = resnet.__all__ \ __all__ = resnet.__all__ \
+ vgg.__all__ \ + vgg.__all__ \
+ mobilenetv1.__all__ \ + mobilenetv1.__all__ \
+ mobilenetv2.__all__ \ + mobilenetv2.__all__ \
+ darknet.__all__\
+ lenet.__all__ + lenet.__all__
# 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.
import math
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay
from paddle.fluid.dygraph.nn import Conv2D, BatchNorm, Pool2D, Linear
from hapi.model import Model
from hapi.download import get_weights_path_from_url
__all__ = ['DarkNet', 'darknet53']
# {num_layers: (url, md5)}
model_urls = {
'darknet53':
('https://paddle-hapi.bj.bcebos.com/models/darknet53.pdparams',
'ca506a90e2efecb9a2093f8ada808708')
}
class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self,
ch_in,
ch_out,
filter_size=3,
stride=1,
groups=1,
padding=0,
act="leaky"):
super(ConvBNLayer, self).__init__()
self.conv = Conv2D(
num_channels=ch_in,
num_filters=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding,
groups=groups,
param_attr=ParamAttr(
initializer=fluid.initializer.Normal(0., 0.02)),
bias_attr=False,
act=None)
self.batch_norm = BatchNorm(
num_channels=ch_out,
param_attr=ParamAttr(
initializer=fluid.initializer.Normal(0., 0.02),
regularizer=L2Decay(0.)),
bias_attr=ParamAttr(
initializer=fluid.initializer.Constant(0.0),
regularizer=L2Decay(0.)))
self.act = act
def forward(self, inputs):
out = self.conv(inputs)
out = self.batch_norm(out)
# out = fluid.layers.relu(out)
if self.act == 'leaky':
out = fluid.layers.leaky_relu(x=out, alpha=0.1)
return out
class DownSample(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out, filter_size=3, stride=2, padding=1):
super(DownSample, self).__init__()
self.conv_bn_layer = ConvBNLayer(
ch_in=ch_in,
ch_out=ch_out,
filter_size=filter_size,
stride=stride,
padding=padding)
self.ch_out = ch_out
def forward(self, inputs):
out = self.conv_bn_layer(inputs)
return out
class BasicBlock(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out):
super(BasicBlock, self).__init__()
self.conv1 = ConvBNLayer(
ch_in=ch_in, ch_out=ch_out, filter_size=1, stride=1, padding=0)
self.conv2 = ConvBNLayer(
ch_in=ch_out,
ch_out=ch_out * 2,
filter_size=3,
stride=1,
padding=1)
def forward(self, inputs):
conv1 = self.conv1(inputs)
conv2 = self.conv2(conv1)
out = fluid.layers.elementwise_add(x=inputs, y=conv2, act=None)
return out
class LayerWarp(fluid.dygraph.Layer):
def __init__(self, ch_in, ch_out, count):
super(LayerWarp, self).__init__()
self.basicblock0 = BasicBlock(ch_in, ch_out)
self.res_out_list = []
for i in range(1, count):
res_out = self.add_sublayer("basic_block_%d" % (i),
BasicBlock(ch_out * 2, ch_out))
self.res_out_list.append(res_out)
self.ch_out = ch_out
def forward(self, inputs):
y = self.basicblock0(inputs)
for basic_block_i in self.res_out_list:
y = basic_block_i(y)
return y
DarkNet_cfg = {53: ([1, 2, 8, 8, 4])}
class DarkNet(Model):
"""DarkNet model from
`"YOLOv3: An Incremental Improvement" <https://arxiv.org/abs/1804.02767>`_
Args:
num_layers (int): layer number of DarkNet, only 53 supported currently, default: 53.
num_classes (int): output dim of last fc layer. If num_classes <=0, last fc layer
will not be defined. Default: 1000.
with_pool (bool): use pool before the last fc layer or not. Default: True.
classifier_activation (str): activation for the last fc layer. Default: 'softmax'.
Examples:
.. code-block:: python
from hapi.vision.models import DarkNet
model = DarkNet()
"""
def __init__(self,
num_layers=53,
num_classes=1000,
with_pool=True,
classifier_activation='softmax'):
super(DarkNet, self).__init__()
assert num_layers in DarkNet_cfg.keys(), \
"only support num_layers in {} currently" \
.format(DarkNet_cfg.keys())
self.stages = DarkNet_cfg[num_layers]
self.stages = self.stages[0:5]
self.num_classes = num_classes
self.with_pool = True
ch_in = 3
self.conv0 = ConvBNLayer(
ch_in=ch_in, ch_out=32, filter_size=3, stride=1, padding=1)
self.downsample0 = DownSample(ch_in=32, ch_out=32 * 2)
self.darknet53_conv_block_list = []
self.downsample_list = []
ch_in = [64, 128, 256, 512, 1024]
for i, stage in enumerate(self.stages):
conv_block = self.add_sublayer("stage_%d" % (i),
LayerWarp(
int(ch_in[i]), 32 * (2**i),
stage))
self.darknet53_conv_block_list.append(conv_block)
for i in range(len(self.stages) - 1):
downsample = self.add_sublayer(
"stage_%d_downsample" % i,
DownSample(
ch_in=32 * (2**(i + 1)), ch_out=32 * (2**(i + 2))))
self.downsample_list.append(downsample)
if self.with_pool:
self.global_pool = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True)
if self.num_classes > 0:
stdv = 1.0 / math.sqrt(32 * (2**(i + 2)))
self.fc_input_dim = 32 * (2**(i + 2))
self.fc = Linear(
self.fc_input_dim,
num_classes,
act='softmax',
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv)))
def forward(self, inputs):
out = self.conv0(inputs)
out = self.downsample0(out)
for i, conv_block_i in enumerate(self.darknet53_conv_block_list):
out = conv_block_i(out)
if i < len(self.stages) - 1:
out = self.downsample_list[i](out)
if self.with_pool:
out = self.global_pool(out)
if self.num_classes > 0:
out = fluid.layers.reshape(out, shape=[-1, self.fc_input_dim])
out = self.fc(out)
return out
def _darknet(arch, num_layers=53, pretrained=False, **kwargs):
model = DarkNet(num_layers, **kwargs)
if pretrained:
assert arch in model_urls, "{} model do not have a pretrained model now, you should set pretrained=False".format(
arch)
weight_path = get_weights_path_from_url(*(model_urls[arch]))
assert weight_path.endswith('.pdparams'), \
"suffix of weight must be .pdparams"
model.load(weight_path)
return model
def darknet53(pretrained=False, **kwargs):
"""DarkNet 53-layer model
Args:
input_channels (bool): channel number of input data, default 3.
pretrained (bool): If True, returns a model pre-trained on ImageNet,
default True.
Examples:
.. code-block:: python
from hapi.vision.models import darknet53
# build model
model = darknet53()
#build model and load imagenet pretrained weight
model = darknet53(pretrained=True)
"""
return _darknet('darknet53', 53, pretrained, **kwargs)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册