未验证 提交 38157d2d 编写于 作者: H haoyuying 提交者: GitHub

add xception series

上级 35c96a7d
# 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 os
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2d, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2d, MaxPool2d, AvgPool2d
from paddle.nn.initializer import Uniform
from paddlehub.module.module import moduleinfo
from paddlehub.module.cv_module import ImageClassifierModule
def xavier(channels: int, filter_size: int, name: str):
"""Initialize the weights by uniform distribution."""
stdv = (3.0 / (filter_size**2 * channels))**0.5
param_attr = ParamAttr(initializer=Uniform(-stdv, stdv), name=name + "_weights")
return param_attr
class ConvLayer(nn.Layer):
"""Basic conv2d layer."""
def __init__(self,
num_channels: int,
num_filters: int,
filter_size: int,
stride: int = 1,
groups: int = 1,
name: str = None):
super(ConvLayer, self).__init__()
self._conv = Conv2d(in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
def forward(self, inputs: paddle.Tensor):
y = self._conv(inputs)
return y
class Inception(nn.Layer):
"""Inception block."""
def __init__(self,
input_channels: int,
output_channels: int,
filter1: int,
filter3R: int,
filter3: int,
filter5R: int,
filter5: int,
proj: int,
name: str = None):
super(Inception, self).__init__()
self._conv1 = ConvLayer(input_channels, filter1, 1, name="inception_" + name + "_1x1")
self._conv3r = ConvLayer(input_channels, filter3R, 1, name="inception_" + name + "_3x3_reduce")
self._conv3 = ConvLayer(filter3R, filter3, 3, name="inception_" + name + "_3x3")
self._conv5r = ConvLayer(input_channels, filter5R, 1, name="inception_" + name + "_5x5_reduce")
self._conv5 = ConvLayer(filter5R, filter5, 5, name="inception_" + name + "_5x5")
self._pool = MaxPool2d(kernel_size=3, stride=1, padding=1)
self._convprj = ConvLayer(input_channels, proj, 1, name="inception_" + name + "_3x3_proj")
def forward(self, inputs: paddle.Tensor):
conv1 = self._conv1(inputs)
conv3r = self._conv3r(inputs)
conv3 = self._conv3(conv3r)
conv5r = self._conv5r(inputs)
conv5 = self._conv5(conv5r)
pool = self._pool(inputs)
convprj = self._convprj(pool)
cat = paddle.concat([conv1, conv3, conv5, convprj], axis=1)
cat = F.relu(cat)
return cat
@moduleinfo(name="googlenet_imagenet",
type="CV/classification",
author="paddlepaddle",
author_email="",
summary="GoogleNet_imagenet is a classification model, "
"this module is trained with Imagenet dataset.",
version="1.1.0",
meta=ImageClassifierModule)
class GoogleNet(nn.Layer):
"""GoogleNet model"""
def __init__(self, class_dim: int = 1000, load_checkpoint: str = None):
super(GoogleNet, self).__init__()
self._conv = ConvLayer(3, 64, 7, 2, name="conv1")
self._pool = MaxPool2d(kernel_size=3, stride=2)
self._conv_1 = ConvLayer(64, 64, 1, name="conv2_1x1")
self._conv_2 = ConvLayer(64, 192, 3, name="conv2_3x3")
self._ince3a = Inception(192, 192, 64, 96, 128, 16, 32, 32, name="ince3a")
self._ince3b = Inception(256, 256, 128, 128, 192, 32, 96, 64, name="ince3b")
self._ince4a = Inception(480, 480, 192, 96, 208, 16, 48, 64, name="ince4a")
self._ince4b = Inception(512, 512, 160, 112, 224, 24, 64, 64, name="ince4b")
self._ince4c = Inception(512, 512, 128, 128, 256, 24, 64, 64, name="ince4c")
self._ince4d = Inception(512, 512, 112, 144, 288, 32, 64, 64, name="ince4d")
self._ince4e = Inception(528, 528, 256, 160, 320, 32, 128, 128, name="ince4e")
self._ince5a = Inception(832, 832, 256, 160, 320, 32, 128, 128, name="ince5a")
self._ince5b = Inception(832, 832, 384, 192, 384, 48, 128, 128, name="ince5b")
self._pool_5 = AvgPool2d(kernel_size=7, stride=7)
self._drop = Dropout(p=0.4, mode="downscale_in_infer")
self._fc_out = Linear(1024,
class_dim,
weight_attr=xavier(1024, 1, "out"),
bias_attr=ParamAttr(name="out_offset"))
if load_checkpoint is not None:
model_dict = paddle.load(load_checkpoint)[0]
self.set_dict(model_dict)
print("load custom checkpoint success")
else:
checkpoint = os.path.join(self.directory, 'googlenet_imagenet.pdparams')
if not os.path.exists(checkpoint):
os.system(
'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/googlenet_imagenet.pdparams -O' +
checkpoint)
model_dict = paddle.load(checkpoint)[0]
self.set_dict(model_dict)
print("load pretrained checkpoint success")
def forward(self, inputs: paddle.Tensor):
x = self._conv(inputs)
x = self._pool(x)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._pool(x)
x = self._ince3a(x)
x = self._ince3b(x)
x = self._pool(x)
ince4a = self._ince4a(x)
x = self._ince4b(ince4a)
x = self._ince4c(x)
ince4d = self._ince4d(x)
x = self._ince4e(ince4d)
x = self._pool(x)
x = self._ince5a(x)
ince5b = self._ince5b(x)
x = self._pool_5(ince5b)
x = self._drop(x)
x = paddle.squeeze(x, axis=[2, 3])
out = self._fc_out(x)
out = F.softmax(out)
return out
# 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 os
import math
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2d, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2d, MaxPool2d, AvgPool2d
from paddle.nn.initializer import Uniform
from paddlehub.module.module import moduleinfo
from paddlehub.module.cv_module import ImageClassifierModule
class ConvBNLayer(nn.Layer):
"""Basic conv bn layer."""
def __init__(self,
num_channels: int,
num_filters: int,
filter_size: int,
stride: int = 1,
padding: int = 0,
groups: int = 1,
act: str = 'relu',
name: str = None):
super(ConvBNLayer, self).__init__()
self._conv = Conv2d(in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=padding,
groups=groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
bn_name = name + "_bn"
self._batch_norm = BatchNorm(num_filters,
act=act,
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 + '_variance')
def forward(self, inputs: paddle.Tensor):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class InceptionStem(nn.Layer):
"""InceptionV4 stem module."""
def __init__(self):
super(InceptionStem, self).__init__()
self._conv_1 = ConvBNLayer(3, 32, 3, stride=2, act="relu", name="conv1_3x3_s2")
self._conv_2 = ConvBNLayer(32, 32, 3, act="relu", name="conv2_3x3_s1")
self._conv_3 = ConvBNLayer(32, 64, 3, padding=1, act="relu", name="conv3_3x3_s1")
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=0)
self._conv2 = ConvBNLayer(64, 96, 3, stride=2, act="relu", name="inception_stem1_3x3_s2")
self._conv1_1 = ConvBNLayer(160, 64, 1, act="relu", name="inception_stem2_3x3_reduce")
self._conv1_2 = ConvBNLayer(64, 96, 3, act="relu", name="inception_stem2_3x3")
self._conv2_1 = ConvBNLayer(160, 64, 1, act="relu", name="inception_stem2_1x7_reduce")
self._conv2_2 = ConvBNLayer(64, 64, (7, 1), padding=(3, 0), act="relu", name="inception_stem2_1x7")
self._conv2_3 = ConvBNLayer(64, 64, (1, 7), padding=(0, 3), act="relu", name="inception_stem2_7x1")
self._conv2_4 = ConvBNLayer(64, 96, 3, act="relu", name="inception_stem2_3x3_2")
self._conv3 = ConvBNLayer(192, 192, 3, stride=2, act="relu", name="inception_stem3_3x3_s2")
def forward(self, inputs: paddle.Tensor):
conv = self._conv_1(inputs)
conv = self._conv_2(conv)
conv = self._conv_3(conv)
pool1 = self._pool(conv)
conv2 = self._conv2(conv)
concat = paddle.concat([pool1, conv2], axis=1)
conv1 = self._conv1_1(concat)
conv1 = self._conv1_2(conv1)
conv2 = self._conv2_1(concat)
conv2 = self._conv2_2(conv2)
conv2 = self._conv2_3(conv2)
conv2 = self._conv2_4(conv2)
concat = paddle.concat([conv1, conv2], axis=1)
conv1 = self._conv3(concat)
pool1 = self._pool(concat)
concat = paddle.concat([conv1, pool1], axis=1)
return concat
class InceptionA(nn.Layer):
"""InceptionA module for InceptionV4."""
def __init__(self, name: str):
super(InceptionA, self).__init__()
self._pool = AvgPool2d(kernel_size=3, stride=1, padding=1)
self._conv1 = ConvBNLayer(384, 96, 1, act="relu", name="inception_a" + name + "_1x1")
self._conv2 = ConvBNLayer(384, 96, 1, act="relu", name="inception_a" + name + "_1x1_2")
self._conv3_1 = ConvBNLayer(384, 64, 1, act="relu", name="inception_a" + name + "_3x3_reduce")
self._conv3_2 = ConvBNLayer(64, 96, 3, padding=1, act="relu", name="inception_a" + name + "_3x3")
self._conv4_1 = ConvBNLayer(384, 64, 1, act="relu", name="inception_a" + name + "_3x3_2_reduce")
self._conv4_2 = ConvBNLayer(64, 96, 3, padding=1, act="relu", name="inception_a" + name + "_3x3_2")
self._conv4_3 = ConvBNLayer(96, 96, 3, padding=1, act="relu", name="inception_a" + name + "_3x3_3")
def forward(self, inputs: paddle.Tensor):
pool1 = self._pool(inputs)
conv1 = self._conv1(pool1)
conv2 = self._conv2(inputs)
conv3 = self._conv3_1(inputs)
conv3 = self._conv3_2(conv3)
conv4 = self._conv4_1(inputs)
conv4 = self._conv4_2(conv4)
conv4 = self._conv4_3(conv4)
concat = paddle.concat([conv1, conv2, conv3, conv4], axis=1)
return concat
class ReductionA(nn.Layer):
"""ReductionA module for InceptionV4."""
def __init__(self):
super(ReductionA, self).__init__()
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=0)
self._conv2 = ConvBNLayer(384, 384, 3, stride=2, act="relu", name="reduction_a_3x3")
self._conv3_1 = ConvBNLayer(384, 192, 1, act="relu", name="reduction_a_3x3_2_reduce")
self._conv3_2 = ConvBNLayer(192, 224, 3, padding=1, act="relu", name="reduction_a_3x3_2")
self._conv3_3 = ConvBNLayer(224, 256, 3, stride=2, act="relu", name="reduction_a_3x3_3")
def forward(self, inputs: paddle.Tensor):
pool1 = self._pool(inputs)
conv2 = self._conv2(inputs)
conv3 = self._conv3_1(inputs)
conv3 = self._conv3_2(conv3)
conv3 = self._conv3_3(conv3)
concat = paddle.concat([pool1, conv2, conv3], axis=1)
return concat
class InceptionB(nn.Layer):
"""InceptionB module for InceptionV4."""
def __init__(self, name: str = None):
super(InceptionB, self).__init__()
self._pool = AvgPool2d(kernel_size=3, stride=1, padding=1)
self._conv1 = ConvBNLayer(1024, 128, 1, act="relu", name="inception_b" + name + "_1x1")
self._conv2 = ConvBNLayer(1024, 384, 1, act="relu", name="inception_b" + name + "_1x1_2")
self._conv3_1 = ConvBNLayer(1024, 192, 1, act="relu", name="inception_b" + name + "_1x7_reduce")
self._conv3_2 = ConvBNLayer(192, 224, (1, 7), padding=(0, 3), act="relu", name="inception_b" + name + "_1x7")
self._conv3_3 = ConvBNLayer(224, 256, (7, 1), padding=(3, 0), act="relu", name="inception_b" + name + "_7x1")
self._conv4_1 = ConvBNLayer(1024, 192, 1, act="relu", name="inception_b" + name + "_7x1_2_reduce")
self._conv4_2 = ConvBNLayer(192, 192, (1, 7), padding=(0, 3), act="relu", name="inception_b" + name + "_1x7_2")
self._conv4_3 = ConvBNLayer(192, 224, (7, 1), padding=(3, 0), act="relu", name="inception_b" + name + "_7x1_2")
self._conv4_4 = ConvBNLayer(224, 224, (1, 7), padding=(0, 3), act="relu", name="inception_b" + name + "_1x7_3")
self._conv4_5 = ConvBNLayer(224, 256, (7, 1), padding=(3, 0), act="relu", name="inception_b" + name + "_7x1_3")
def forward(self, inputs: paddle.Tensor):
pool1 = self._pool(inputs)
conv1 = self._conv1(pool1)
conv2 = self._conv2(inputs)
conv3 = self._conv3_1(inputs)
conv3 = self._conv3_2(conv3)
conv3 = self._conv3_3(conv3)
conv4 = self._conv4_1(inputs)
conv4 = self._conv4_2(conv4)
conv4 = self._conv4_3(conv4)
conv4 = self._conv4_4(conv4)
conv4 = self._conv4_5(conv4)
concat = paddle.concat([conv1, conv2, conv3, conv4], axis=1)
return concat
class ReductionB(nn.Layer):
"""ReductionB module for InceptionV4."""
def __init__(self):
super(ReductionB, self).__init__()
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=0)
self._conv2_1 = ConvBNLayer(1024, 192, 1, act="relu", name="reduction_b_3x3_reduce")
self._conv2_2 = ConvBNLayer(192, 192, 3, stride=2, act="relu", name="reduction_b_3x3")
self._conv3_1 = ConvBNLayer(1024, 256, 1, act="relu", name="reduction_b_1x7_reduce")
self._conv3_2 = ConvBNLayer(256, 256, (1, 7), padding=(0, 3), act="relu", name="reduction_b_1x7")
self._conv3_3 = ConvBNLayer(256, 320, (7, 1), padding=(3, 0), act="relu", name="reduction_b_7x1")
self._conv3_4 = ConvBNLayer(320, 320, 3, stride=2, act="relu", name="reduction_b_3x3_2")
def forward(self, inputs: paddle.Tensor):
pool1 = self._pool(inputs)
conv2 = self._conv2_1(inputs)
conv2 = self._conv2_2(conv2)
conv3 = self._conv3_1(inputs)
conv3 = self._conv3_2(conv3)
conv3 = self._conv3_3(conv3)
conv3 = self._conv3_4(conv3)
concat = paddle.concat([pool1, conv2, conv3], axis=1)
return concat
class InceptionC(nn.Layer):
"""InceptionC module for InceptionV4."""
def __init__(self, name: str = None):
super(InceptionC, self).__init__()
self._pool = AvgPool2d(kernel_size=3, stride=1, padding=1)
self._conv1 = ConvBNLayer(1536, 256, 1, act="relu", name="inception_c" + name + "_1x1")
self._conv2 = ConvBNLayer(1536, 256, 1, act="relu", name="inception_c" + name + "_1x1_2")
self._conv3_0 = ConvBNLayer(1536, 384, 1, act="relu", name="inception_c" + name + "_1x1_3")
self._conv3_1 = ConvBNLayer(384, 256, (1, 3), padding=(0, 1), act="relu", name="inception_c" + name + "_1x3")
self._conv3_2 = ConvBNLayer(384, 256, (3, 1), padding=(1, 0), act="relu", name="inception_c" + name + "_3x1")
self._conv4_0 = ConvBNLayer(1536, 384, 1, act="relu", name="inception_c" + name + "_1x1_4")
self._conv4_00 = ConvBNLayer(384, 448, (1, 3), padding=(0, 1), act="relu", name="inception_c" + name + "_1x3_2")
self._conv4_000 = ConvBNLayer(448,
512, (3, 1),
padding=(1, 0),
act="relu",
name="inception_c" + name + "_3x1_2")
self._conv4_1 = ConvBNLayer(512, 256, (1, 3), padding=(0, 1), act="relu", name="inception_c" + name + "_1x3_3")
self._conv4_2 = ConvBNLayer(512, 256, (3, 1), padding=(1, 0), act="relu", name="inception_c" + name + "_3x1_3")
def forward(self, inputs: paddle.Tensor):
pool1 = self._pool(inputs)
conv1 = self._conv1(pool1)
conv2 = self._conv2(inputs)
conv3 = self._conv3_0(inputs)
conv3_1 = self._conv3_1(conv3)
conv3_2 = self._conv3_2(conv3)
conv4 = self._conv4_0(inputs)
conv4 = self._conv4_00(conv4)
conv4 = self._conv4_000(conv4)
conv4_1 = self._conv4_1(conv4)
conv4_2 = self._conv4_2(conv4)
concat = paddle.concat([conv1, conv2, conv3_1, conv3_2, conv4_1, conv4_2], axis=1)
return concat
@moduleinfo(name="inceptionv4_imagenet",
type="CV/classification",
author="paddlepaddle",
author_email="",
summary="InceptionV4_imagenet is a classification model, "
"this module is trained with Imagenet dataset.",
version="1.1.0",
meta=ImageClassifierModule)
class InceptionV4(nn.Layer):
"""InceptionV4 model."""
def __init__(self, class_dim: int = 1000, load_checkpoint: str = None):
super(InceptionV4, self).__init__()
self._inception_stem = InceptionStem()
self._inceptionA_1 = InceptionA(name="1")
self._inceptionA_2 = InceptionA(name="2")
self._inceptionA_3 = InceptionA(name="3")
self._inceptionA_4 = InceptionA(name="4")
self._reductionA = ReductionA()
self._inceptionB_1 = InceptionB(name="1")
self._inceptionB_2 = InceptionB(name="2")
self._inceptionB_3 = InceptionB(name="3")
self._inceptionB_4 = InceptionB(name="4")
self._inceptionB_5 = InceptionB(name="5")
self._inceptionB_6 = InceptionB(name="6")
self._inceptionB_7 = InceptionB(name="7")
self._reductionB = ReductionB()
self._inceptionC_1 = InceptionC(name="1")
self._inceptionC_2 = InceptionC(name="2")
self._inceptionC_3 = InceptionC(name="3")
self.avg_pool = AdaptiveAvgPool2d(1)
self._drop = Dropout(p=0.2, mode="downscale_in_infer")
stdv = 1.0 / math.sqrt(1536 * 1.0)
self.out = Linear(1536,
class_dim,
weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="final_fc_weights"),
bias_attr=ParamAttr(name="final_fc_offset"))
if load_checkpoint is not None:
model_dict = paddle.load(load_checkpoint)[0]
self.set_dict(model_dict)
print("load custom checkpoint success")
else:
checkpoint = os.path.join(self.directory, 'inceptionv4_imagenet.pdparams')
if not os.path.exists(checkpoint):
os.system(
'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/inceptionv4_imagenet.pdparams -O'
+ checkpoint)
model_dict = paddle.load(checkpoint)[0]
self.set_dict(model_dict)
print("load pretrained checkpoint success")
def forward(self, inputs):
x = self._inception_stem(inputs)
x = self._inceptionA_1(x)
x = self._inceptionA_2(x)
x = self._inceptionA_3(x)
x = self._inceptionA_4(x)
x = self._reductionA(x)
x = self._inceptionB_1(x)
x = self._inceptionB_2(x)
x = self._inceptionB_3(x)
x = self._inceptionB_4(x)
x = self._inceptionB_5(x)
x = self._inceptionB_6(x)
x = self._inceptionB_7(x)
x = self._reductionB(x)
x = self._inceptionC_1(x)
x = self._inceptionC_2(x)
x = self._inceptionC_3(x)
x = self.avg_pool(x)
x = paddle.squeeze(x, axis=[2, 3])
x = self._drop(x)
x = self.out(x)
return x
# 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 os
import sys
import math
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2d, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2d, MaxPool2d, AvgPool2d
from paddle.nn.initializer import Uniform
from paddlehub.module.module import moduleinfo
from paddlehub.module.cv_module import ImageClassifierModule
class ConvBNLayer(nn.Layer):
"""Basic conv bn layer."""
def __init__(self,
num_channels: int,
num_filters: int,
filter_size: int,
stride: int = 1,
groups: int = 1,
act: str = None,
name: str = None):
super(ConvBNLayer, self).__init__()
self._conv = Conv2d(in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
bn_name = "bn_" + name
self._batch_norm = BatchNorm(num_filters,
act=act,
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 + '_variance')
def forward(self, inputs: paddle.Tensor):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class SeparableConv(nn.Layer):
"""Basic separable conv layer, it contains pointwise conv and depthwise conv."""
def __init__(self, input_channels: int, output_channels: int, stride: int = 1, name: str = None):
super(SeparableConv, self).__init__()
self._pointwise_conv = ConvBNLayer(input_channels, output_channels, 1, name=name + "_sep")
self._depthwise_conv = ConvBNLayer(output_channels,
output_channels,
3,
stride=stride,
groups=output_channels,
name=name + "_dw")
def forward(self, inputs: paddle.Tensor):
x = self._pointwise_conv(inputs)
x = self._depthwise_conv(x)
return x
class EntryFlowBottleneckBlock(nn.Layer):
"""Basic entry flow bottleneck block for Xception."""
def __init__(self,
input_channels: int,
output_channels: int,
stride: int = 2,
name: str = None,
relu_first: bool = False):
super(EntryFlowBottleneckBlock, self).__init__()
self.relu_first = relu_first
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels,
kernel_size=1,
stride=stride,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv1 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=stride, padding=1)
def forward(self, inputs: paddle.Tensor):
conv0 = inputs
short = self._short(inputs)
if self.relu_first:
conv0 = F.relu(conv0)
conv1 = self._conv1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class EntryFlow(nn.Layer):
"""Entry flow for Xception."""
def __init__(self, block_num: int = 3):
super(EntryFlow, self).__init__()
name = "entry_flow"
self.block_num = block_num
self._conv1 = ConvBNLayer(3, 32, 3, stride=2, act="relu", name=name + "_conv1")
self._conv2 = ConvBNLayer(32, 64, 3, act="relu", name=name + "_conv2")
if block_num == 3:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=2, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 728, stride=2, name=name + "_2", relu_first=True)
elif block_num == 5:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=1, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 256, stride=2, name=name + "_2", relu_first=True)
self._conv_3 = EntryFlowBottleneckBlock(256, 728, stride=1, name=name + "_3", relu_first=True)
self._conv_4 = EntryFlowBottleneckBlock(728, 728, stride=2, name=name + "_4", relu_first=True)
else:
sys.exit(-1)
def forward(self, inputs: paddle.Tensor):
x = self._conv1(inputs)
x = self._conv2(x)
if self.block_num == 3:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
elif self.block_num == 5:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
return x
class MiddleFlowBottleneckBlock(nn.Layer):
"""Basic middle flow bottleneck block for Xception."""
def __init__(self, input_channels: int, output_channels: int, name: str):
super(MiddleFlowBottleneckBlock, self).__init__()
self._conv_0 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv_1 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._conv_2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2c_weights")
def forward(self, inputs: paddle.Tensor):
conv0 = F.relu(inputs)
conv0 = self._conv_0(conv0)
conv1 = F.relu(conv0)
conv1 = self._conv_1(conv1)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
return paddle.elementwise_add(x=inputs, y=conv2)
class MiddleFlow(nn.Layer):
"""Middle flow for Xception."""
def __init__(self, block_num: int = 8):
super(MiddleFlow, self).__init__()
self.block_num = block_num
self._conv_0 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_0")
self._conv_1 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_1")
self._conv_2 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_2")
self._conv_3 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_3")
self._conv_4 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_4")
self._conv_5 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_5")
self._conv_6 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_6")
self._conv_7 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_7")
if block_num == 16:
self._conv_8 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_8")
self._conv_9 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_9")
self._conv_10 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_10")
self._conv_11 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_11")
self._conv_12 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_12")
self._conv_13 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_13")
self._conv_14 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_14")
self._conv_15 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_15")
def forward(self, inputs: paddle.Tensor):
x = self._conv_0(inputs)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
x = self._conv_5(x)
x = self._conv_6(x)
x = self._conv_7(x)
if self.block_num == 16:
x = self._conv_8(x)
x = self._conv_9(x)
x = self._conv_10(x)
x = self._conv_11(x)
x = self._conv_12(x)
x = self._conv_13(x)
x = self._conv_14(x)
x = self._conv_15(x)
return x
class ExitFlowBottleneckBlock(nn.Layer):
"""Basic exit flow bottleneck block for Xception."""
def __init__(self, input_channels: int, output_channels1: int, output_channels2: int, name: str):
super(ExitFlowBottleneckBlock, self).__init__()
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels2,
kernel_size=1,
stride=2,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv_1 = SeparableConv(input_channels, output_channels1, stride=1, name=name + "_branch2a_weights")
self._conv_2 = SeparableConv(output_channels1, output_channels2, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=1)
def forward(self, inputs: paddle.Tensor):
short = self._short(inputs)
conv0 = F.relu(inputs)
conv1 = self._conv_1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class ExitFlow(nn.Layer):
"""Exit flow for Xception."""
def __init__(self, class_dim: int):
super(ExitFlow, self).__init__()
name = "exit_flow"
self._conv_0 = ExitFlowBottleneckBlock(728, 728, 1024, name=name + "_1")
self._conv_1 = SeparableConv(1024, 1536, stride=1, name=name + "_2")
self._conv_2 = SeparableConv(1536, 2048, stride=1, name=name + "_3")
self._pool = AdaptiveAvgPool2d(1)
stdv = 1.0 / math.sqrt(2048 * 1.0)
self._out = Linear(2048,
class_dim,
weight_attr=ParamAttr(name="fc_weights", initializer=Uniform(-stdv, stdv)),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs: paddle.Tensor):
conv0 = self._conv_0(inputs)
conv1 = self._conv_1(conv0)
conv1 = F.relu(conv1)
conv2 = self._conv_2(conv1)
conv2 = F.relu(conv2)
pool = self._pool(conv2)
pool = paddle.reshape(pool, [0, -1])
out = self._out(pool)
return out
@moduleinfo(name="xception41_imagenet",
type="CV/classification",
author="paddlepaddle",
author_email="",
summary="Xception41_imagenet is a classification model, "
"this module is trained with Imagenet dataset.",
version="1.1.0",
meta=ImageClassifierModule)
class Xception41(nn.Layer):
"""Xception41 model."""
def __init__(self, class_dim: int = 1000, load_checkpoint: str = None):
super(Xception41, self).__init__()
self.entry_flow_block_num = 3
self.middle_flow_block_num = 8
self._entry_flow = EntryFlow(self.entry_flow_block_num)
self._middle_flow = MiddleFlow(self.middle_flow_block_num)
self._exit_flow = ExitFlow(class_dim)
if load_checkpoint is not None:
model_dict = paddle.load(load_checkpoint)[0]
self.set_dict(model_dict)
print("load custom checkpoint success")
else:
checkpoint = os.path.join(self.directory, 'xception41_imagenet.pdparams')
if not os.path.exists(checkpoint):
os.system(
'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/xception41_imagenet.pdparams -O'
+ checkpoint)
model_dict = paddle.load(checkpoint)[0]
self.set_dict(model_dict)
print("load pretrained checkpoint success")
def forward(self, inputs: paddle.Tensor):
x = self._entry_flow(inputs)
x = self._middle_flow(x)
x = self._exit_flow(x)
return x
# 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 os
import sys
import math
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2d, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2d, MaxPool2d, AvgPool2d
from paddle.nn.initializer import Uniform
from paddlehub.module.module import moduleinfo
from paddlehub.module.cv_module import ImageClassifierModule
class ConvBNLayer(nn.Layer):
"""Basic conv bn layer."""
def __init__(self,
num_channels: int,
num_filters: int,
filter_size: int,
stride: int = 1,
groups: int = 1,
act: str = None,
name: str = None):
super(ConvBNLayer, self).__init__()
self._conv = Conv2d(in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
bn_name = "bn_" + name
self._batch_norm = BatchNorm(num_filters,
act=act,
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 + '_variance')
def forward(self, inputs: paddle.Tensor):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class SeparableConv(nn.Layer):
"""Basic separable conv layer, it contains pointwise conv and depthwise conv."""
def __init__(self, input_channels: int, output_channels: int, stride: int = 1, name: str = None):
super(SeparableConv, self).__init__()
self._pointwise_conv = ConvBNLayer(input_channels, output_channels, 1, name=name + "_sep")
self._depthwise_conv = ConvBNLayer(output_channels,
output_channels,
3,
stride=stride,
groups=output_channels,
name=name + "_dw")
def forward(self, inputs: paddle.Tensor):
x = self._pointwise_conv(inputs)
x = self._depthwise_conv(x)
return x
class EntryFlowBottleneckBlock(nn.Layer):
"""Basic entry flow bottleneck block for Xception."""
def __init__(self,
input_channels: int,
output_channels: int,
stride: int = 2,
name: str = None,
relu_first: bool = False):
super(EntryFlowBottleneckBlock, self).__init__()
self.relu_first = relu_first
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels,
kernel_size=1,
stride=stride,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv1 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=stride, padding=1)
def forward(self, inputs: paddle.Tensor):
conv0 = inputs
short = self._short(inputs)
if self.relu_first:
conv0 = F.relu(conv0)
conv1 = self._conv1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class EntryFlow(nn.Layer):
"""Entry flow for Xception."""
def __init__(self, block_num: int = 3):
super(EntryFlow, self).__init__()
name = "entry_flow"
self.block_num = block_num
self._conv1 = ConvBNLayer(3, 32, 3, stride=2, act="relu", name=name + "_conv1")
self._conv2 = ConvBNLayer(32, 64, 3, act="relu", name=name + "_conv2")
if block_num == 3:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=2, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 728, stride=2, name=name + "_2", relu_first=True)
elif block_num == 5:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=1, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 256, stride=2, name=name + "_2", relu_first=True)
self._conv_3 = EntryFlowBottleneckBlock(256, 728, stride=1, name=name + "_3", relu_first=True)
self._conv_4 = EntryFlowBottleneckBlock(728, 728, stride=2, name=name + "_4", relu_first=True)
else:
sys.exit(-1)
def forward(self, inputs: paddle.Tensor):
x = self._conv1(inputs)
x = self._conv2(x)
if self.block_num == 3:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
elif self.block_num == 5:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
return x
class MiddleFlowBottleneckBlock(nn.Layer):
"""Basic middle flow bottleneck block for Xception."""
def __init__(self, input_channels: int, output_channels: int, name: str):
super(MiddleFlowBottleneckBlock, self).__init__()
self._conv_0 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv_1 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._conv_2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2c_weights")
def forward(self, inputs: paddle.Tensor):
conv0 = F.relu(inputs)
conv0 = self._conv_0(conv0)
conv1 = F.relu(conv0)
conv1 = self._conv_1(conv1)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
return paddle.elementwise_add(x=inputs, y=conv2)
class MiddleFlow(nn.Layer):
"""Middle flow for Xception."""
def __init__(self, block_num: int = 8):
super(MiddleFlow, self).__init__()
self.block_num = block_num
self._conv_0 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_0")
self._conv_1 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_1")
self._conv_2 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_2")
self._conv_3 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_3")
self._conv_4 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_4")
self._conv_5 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_5")
self._conv_6 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_6")
self._conv_7 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_7")
if block_num == 16:
self._conv_8 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_8")
self._conv_9 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_9")
self._conv_10 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_10")
self._conv_11 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_11")
self._conv_12 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_12")
self._conv_13 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_13")
self._conv_14 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_14")
self._conv_15 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_15")
def forward(self, inputs: paddle.Tensor):
x = self._conv_0(inputs)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
x = self._conv_5(x)
x = self._conv_6(x)
x = self._conv_7(x)
if self.block_num == 16:
x = self._conv_8(x)
x = self._conv_9(x)
x = self._conv_10(x)
x = self._conv_11(x)
x = self._conv_12(x)
x = self._conv_13(x)
x = self._conv_14(x)
x = self._conv_15(x)
return x
class ExitFlowBottleneckBlock(nn.Layer):
"""Basic exit flow bottleneck block for Xception."""
def __init__(self, input_channels, output_channels1, output_channels2, name):
super(ExitFlowBottleneckBlock, self).__init__()
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels2,
kernel_size=1,
stride=2,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv_1 = SeparableConv(input_channels, output_channels1, stride=1, name=name + "_branch2a_weights")
self._conv_2 = SeparableConv(output_channels1, output_channels2, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=1)
def forward(self, inputs: paddle.Tensor):
short = self._short(inputs)
conv0 = F.relu(inputs)
conv1 = self._conv_1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class ExitFlow(nn.Layer):
"""Exit flow for Xception."""
def __init__(self, class_dim):
super(ExitFlow, self).__init__()
name = "exit_flow"
self._conv_0 = ExitFlowBottleneckBlock(728, 728, 1024, name=name + "_1")
self._conv_1 = SeparableConv(1024, 1536, stride=1, name=name + "_2")
self._conv_2 = SeparableConv(1536, 2048, stride=1, name=name + "_3")
self._pool = AdaptiveAvgPool2d(1)
stdv = 1.0 / math.sqrt(2048 * 1.0)
self._out = Linear(2048,
class_dim,
weight_attr=ParamAttr(name="fc_weights", initializer=Uniform(-stdv, stdv)),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs: paddle.Tensor):
conv0 = self._conv_0(inputs)
conv1 = self._conv_1(conv0)
conv1 = F.relu(conv1)
conv2 = self._conv_2(conv1)
conv2 = F.relu(conv2)
pool = self._pool(conv2)
pool = paddle.reshape(pool, [0, -1])
out = self._out(pool)
return out
@moduleinfo(name="xception65_imagenet",
type="CV/classification",
author="paddlepaddle",
author_email="",
summary="Xception65_imagenet is a classification model, "
"this module is trained with Imagenet dataset.",
version="1.1.0",
meta=ImageClassifierModule)
class Xception65(nn.Layer):
def __init__(self, class_dim=1000, load_checkpoint: str = None):
super(Xception65, self).__init__()
self.entry_flow_block_num = 3
self.middle_flow_block_num = 16
self._entry_flow = EntryFlow(self.entry_flow_block_num)
self._middle_flow = MiddleFlow(self.middle_flow_block_num)
self._exit_flow = ExitFlow(class_dim)
if load_checkpoint is not None:
model_dict = paddle.load(load_checkpoint)[0]
self.set_dict(model_dict)
print("load custom checkpoint success")
else:
checkpoint = os.path.join(self.directory, 'xception65_imagenet.pdparams')
if not os.path.exists(checkpoint):
os.system(
'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/xception65_imagenet.pdparams -O'
+ checkpoint)
model_dict = paddle.load(checkpoint)[0]
self.set_dict(model_dict)
print("load pretrained checkpoint success")
def forward(self, inputs):
x = self._entry_flow(inputs)
x = self._middle_flow(x)
x = self._exit_flow(x)
return x
# 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 os
import sys
import math
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2d, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2d, MaxPool2d, AvgPool2d
from paddle.nn.initializer import Uniform
from paddlehub.module.module import moduleinfo
from paddlehub.module.cv_module import ImageClassifierModule
class ConvBNLayer(nn.Layer):
"""Basic conv bn layer."""
def __init__(self,
num_channels: int,
num_filters: int,
filter_size: int,
stride: int = 1,
groups: int = 1,
act: str = None,
name: str = None):
super(ConvBNLayer, self).__init__()
self._conv = Conv2d(in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
bn_name = "bn_" + name
self._batch_norm = BatchNorm(num_filters,
act=act,
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 + '_variance')
def forward(self, inputs: paddle.Tensor):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class SeparableConv(nn.Layer):
"""Basic separable conv layer, it contains pointwise conv and depthwise conv."""
def __init__(self, input_channels: int, output_channels: int, stride: int = 1, name: str = None):
super(SeparableConv, self).__init__()
self._pointwise_conv = ConvBNLayer(input_channels, output_channels, 1, name=name + "_sep")
self._depthwise_conv = ConvBNLayer(output_channels,
output_channels,
3,
stride=stride,
groups=output_channels,
name=name + "_dw")
def forward(self, inputs: paddle.Tensor):
x = self._pointwise_conv(inputs)
x = self._depthwise_conv(x)
return x
class EntryFlowBottleneckBlock(nn.Layer):
"""Basic entry flow bottleneck block for Xception."""
def __init__(self,
input_channels: int,
output_channels: int,
stride: int = 2,
name: str = None,
relu_first: bool = False):
super(EntryFlowBottleneckBlock, self).__init__()
self.relu_first = relu_first
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels,
kernel_size=1,
stride=stride,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv1 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=stride, padding=1)
def forward(self, inputs: paddle.Tensor):
conv0 = inputs
short = self._short(inputs)
if self.relu_first:
conv0 = F.relu(conv0)
conv1 = self._conv1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class EntryFlow(nn.Layer):
"""Entry flow for Xception."""
def __init__(self, block_num: int = 3):
super(EntryFlow, self).__init__()
name = "entry_flow"
self.block_num = block_num
self._conv1 = ConvBNLayer(3, 32, 3, stride=2, act="relu", name=name + "_conv1")
self._conv2 = ConvBNLayer(32, 64, 3, act="relu", name=name + "_conv2")
if block_num == 3:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=2, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 728, stride=2, name=name + "_2", relu_first=True)
elif block_num == 5:
self._conv_0 = EntryFlowBottleneckBlock(64, 128, stride=2, name=name + "_0", relu_first=False)
self._conv_1 = EntryFlowBottleneckBlock(128, 256, stride=1, name=name + "_1", relu_first=True)
self._conv_2 = EntryFlowBottleneckBlock(256, 256, stride=2, name=name + "_2", relu_first=True)
self._conv_3 = EntryFlowBottleneckBlock(256, 728, stride=1, name=name + "_3", relu_first=True)
self._conv_4 = EntryFlowBottleneckBlock(728, 728, stride=2, name=name + "_4", relu_first=True)
else:
sys.exit(-1)
def forward(self, inputs: paddle.Tensor):
x = self._conv1(inputs)
x = self._conv2(x)
if self.block_num == 3:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
elif self.block_num == 5:
x = self._conv_0(x)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
return x
class MiddleFlowBottleneckBlock(nn.Layer):
"""Basic middle flow bottleneck block for Xception."""
def __init__(self, input_channels: int, output_channels: int, name: str):
super(MiddleFlowBottleneckBlock, self).__init__()
self._conv_0 = SeparableConv(input_channels, output_channels, stride=1, name=name + "_branch2a_weights")
self._conv_1 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2b_weights")
self._conv_2 = SeparableConv(output_channels, output_channels, stride=1, name=name + "_branch2c_weights")
def forward(self, inputs: paddle.Tensor):
conv0 = F.relu(inputs)
conv0 = self._conv_0(conv0)
conv1 = F.relu(conv0)
conv1 = self._conv_1(conv1)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
return paddle.elementwise_add(x=inputs, y=conv2)
class MiddleFlow(nn.Layer):
"""Middle flow for Xception."""
def __init__(self, block_num: int = 8):
super(MiddleFlow, self).__init__()
self.block_num = block_num
self._conv_0 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_0")
self._conv_1 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_1")
self._conv_2 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_2")
self._conv_3 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_3")
self._conv_4 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_4")
self._conv_5 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_5")
self._conv_6 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_6")
self._conv_7 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_7")
if block_num == 16:
self._conv_8 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_8")
self._conv_9 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_9")
self._conv_10 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_10")
self._conv_11 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_11")
self._conv_12 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_12")
self._conv_13 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_13")
self._conv_14 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_14")
self._conv_15 = MiddleFlowBottleneckBlock(728, 728, name="middle_flow_15")
def forward(self, inputs: paddle.Tensor):
x = self._conv_0(inputs)
x = self._conv_1(x)
x = self._conv_2(x)
x = self._conv_3(x)
x = self._conv_4(x)
x = self._conv_5(x)
x = self._conv_6(x)
x = self._conv_7(x)
if self.block_num == 16:
x = self._conv_8(x)
x = self._conv_9(x)
x = self._conv_10(x)
x = self._conv_11(x)
x = self._conv_12(x)
x = self._conv_13(x)
x = self._conv_14(x)
x = self._conv_15(x)
return x
class ExitFlowBottleneckBlock(nn.Layer):
"""Basic exit flow bottleneck block for Xception."""
def __init__(self, input_channels: int, output_channels1: int, output_channels2: int, name: str):
super(ExitFlowBottleneckBlock, self).__init__()
self._short = Conv2d(in_channels=input_channels,
out_channels=output_channels2,
kernel_size=1,
stride=2,
padding=0,
weight_attr=ParamAttr(name + "_branch1_weights"),
bias_attr=False)
self._conv_1 = SeparableConv(input_channels, output_channels1, stride=1, name=name + "_branch2a_weights")
self._conv_2 = SeparableConv(output_channels1, output_channels2, stride=1, name=name + "_branch2b_weights")
self._pool = MaxPool2d(kernel_size=3, stride=2, padding=1)
def forward(self, inputs: paddle.Tensor):
short = self._short(inputs)
conv0 = F.relu(inputs)
conv1 = self._conv_1(conv0)
conv2 = F.relu(conv1)
conv2 = self._conv_2(conv2)
pool = self._pool(conv2)
return paddle.elementwise_add(x=short, y=pool)
class ExitFlow(nn.Layer):
def __init__(self, class_dim: int):
super(ExitFlow, self).__init__()
name = "exit_flow"
self._conv_0 = ExitFlowBottleneckBlock(728, 728, 1024, name=name + "_1")
self._conv_1 = SeparableConv(1024, 1536, stride=1, name=name + "_2")
self._conv_2 = SeparableConv(1536, 2048, stride=1, name=name + "_3")
self._pool = AdaptiveAvgPool2d(1)
stdv = 1.0 / math.sqrt(2048 * 1.0)
self._out = Linear(2048,
class_dim,
weight_attr=ParamAttr(name="fc_weights", initializer=Uniform(-stdv, stdv)),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs: paddle.Tensor):
conv0 = self._conv_0(inputs)
conv1 = self._conv_1(conv0)
conv1 = F.relu(conv1)
conv2 = self._conv_2(conv1)
conv2 = F.relu(conv2)
pool = self._pool(conv2)
pool = paddle.reshape(pool, [0, -1])
out = self._out(pool)
return out
@moduleinfo(name="xception71_imagenet",
type="CV/classification",
author="paddlepaddle",
author_email="",
summary="Xception71_imagenet is a classification model, "
"this module is trained with Imagenet dataset.",
version="1.1.0",
meta=ImageClassifierModule)
class Xception71(nn.Layer):
def __init__(self, class_dim=1000, load_checkpoint: str = None):
super(Xception71, self).__init__()
self.entry_flow_block_num = 5
self.middle_flow_block_num = 16
self._entry_flow = EntryFlow(self.entry_flow_block_num)
self._middle_flow = MiddleFlow(self.middle_flow_block_num)
self._exit_flow = ExitFlow(class_dim)
if load_checkpoint is not None:
model_dict = paddle.load(load_checkpoint)[0]
self.set_dict(model_dict)
print("load custom checkpoint success")
else:
checkpoint = os.path.join(self.directory, 'xception71_imagenet.pdparams')
if not os.path.exists(checkpoint):
os.system(
'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/xception71_imagenet.pdparams -O'
+ checkpoint)
model_dict = paddle.load(checkpoint)[0]
self.set_dict(model_dict)
print("load pretrained checkpoint success")
def forward(self, inputs):
x = self._entry_flow(inputs)
x = self._middle_flow(x)
x = self._exit_flow(x)
return x
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册