diff --git a/hub_module/modules/image/classification/resnext101_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext101_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..1a8585062b99c465ec489306bbb84965c1f3ecf2 --- /dev/null +++ b/hub_module/modules/image/classification/resnext101_32x4d_imagenet/module.py @@ -0,0 +1,193 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt101.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext101_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext101_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt101_32x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt101_32x4d, self).__init__() + + self.layers = 101 + self.cardinality = 32 + depth = [3, 4, 23, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext101_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext101_32x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext101_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext101_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..3c5703d30b679e27a5cb4993d16b92abf0555084 --- /dev/null +++ b/hub_module/modules/image/classification/resnext101_64x4d_imagenet/module.py @@ -0,0 +1,193 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt101.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext101_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext101_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt101_64x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt101_64x4d, self).__init__() + + self.layers = 101 + self.cardinality = 64 + depth = [3, 4, 23, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext101_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext101_64x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext101_vd_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext101_vd_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..ba128d83ba6b65cab6994e145ccd0dfee8d6686d --- /dev/null +++ b/hub_module/modules/image/classification/resnext101_vd_32x4d_imagenet/module.py @@ -0,0 +1,212 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext101_vd_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext101_vd_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt101_vd(nn.Layer): + """ResNeXt101_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt101_vd, self).__init__() + + self.layers = 101 + self.cardinality = 32 + depth = [3, 4, 23, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext101_vd_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext101_vd_32x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext101_vd_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext101_vd_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..dd26a774a3fa895bdc22a58dbe383b278bbd48f3 --- /dev/null +++ b/hub_module/modules/image/classification/resnext101_vd_64x4d_imagenet/module.py @@ -0,0 +1,212 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext101_vd_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext101_vd_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt101_vd(nn.Layer): + """ResNeXt101_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt101_vd, self).__init__() + + self.layers = 101 + self.cardinality = 64 + depth = [3, 4, 23, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext101_vd_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext101_vd_64x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext152_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext152_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..e9f6a57328e9d87587c1f8d220c39bc9c9599a41 --- /dev/null +++ b/hub_module/modules/image/classification/resnext152_32x4d_imagenet/module.py @@ -0,0 +1,193 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt152.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext152_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext152_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt152_32x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt152_32x4d, self).__init__() + + self.layers = 152 + self.cardinality = 32 + depth = [3, 8, 36, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext152_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext152_32x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext152_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext152_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..dbcf878cfa2f4994a1522f57269304ff00df8b61 --- /dev/null +++ b/hub_module/modules/image/classification/resnext152_64x4d_imagenet/module.py @@ -0,0 +1,193 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt152.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext152_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext152_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt152_64x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt152_64x4d, self).__init__() + + self.layers = 152 + self.cardinality = 64 + depth = [3, 8, 36, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext152_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext152_64x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext152_vd_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext152_vd_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..a1f4579dd17ec1f9b055bc5a5244170bad489288 --- /dev/null +++ b/hub_module/modules/image/classification/resnext152_vd_32x4d_imagenet/module.py @@ -0,0 +1,212 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt152_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext152_vd_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext152_vd_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt152_vd(nn.Layer): + """ResNeXt152_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt152_vd, self).__init__() + + self.layers = 152 + self.cardinality = 32 + depth = [3, 8, 36, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext152_vd_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext152_vd_32x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext152_vd_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext152_vd_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..b9e8f79378f1c6db092693841168f96221bcf13a --- /dev/null +++ b/hub_module/modules/image/classification/resnext152_vd_64x4d_imagenet/module.py @@ -0,0 +1,212 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt152_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext152_vd_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext152_vd_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt152_vd(nn.Layer): + """ResNeXt152_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt152_vd, self).__init__() + + self.layers = 152 + self.cardinality = 64 + depth = [3, 8, 36, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext152_vd_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext152_vd_64x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext50_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext50_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..44eeea3a91b1d595e3969276d127a3b94ad8f82b --- /dev/null +++ b/hub_module/modules/image/classification/resnext50_32x4d_imagenet/module.py @@ -0,0 +1,187 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext50_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext50_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt50_32x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt50_32x4d, self).__init__() + + self.layers = 50 + self.cardinality = 32 + depth = [3, 4, 6, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext50_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext50_32x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext50_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext50_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..4f44ffb8dfa2ae2c5b00903d104fe577d1c98c66 --- /dev/null +++ b/hub_module/modules/image/classification/resnext50_64x4d_imagenet/module.py @@ -0,0 +1,187 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(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 BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext50_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext50_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt50_64x4d(nn.Layer): + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt50_64x4d, self).__init__() + + self.layers = 50 + self.cardinality = 64 + depth = [3, 4, 6, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv = ConvBNLayer(num_channels=3, num_filters=64, filter_size=7, stride=2, act='relu', name="res_conv1") + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + self.pool2d_avg_channels = num_channels[-1] * 2 + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext50_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext50_64x4d_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): + y = self.conv(inputs) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext50_vd_32x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext50_vd_32x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..b388ce5c34070fa821b346abffe9cccb2b3d9d2a --- /dev/null +++ b/hub_module/modules/image/classification/resnext50_vd_32x4d_imagenet/module.py @@ -0,0 +1,206 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext50_vd_32x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext50_vd_32x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt50_vd(nn.Layer): + """ResNeXt50_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt50_vd, self).__init__() + + self.layers = 50 + self.cardinality = 32 + depth = [3, 4, 6, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [128, 256, 512, 1024] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext50_vd_32x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext50_vd_32x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y diff --git a/hub_module/modules/image/classification/resnext50_vd_64x4d_imagenet/module.py b/hub_module/modules/image/classification/resnext50_vd_64x4d_imagenet/module.py new file mode 100644 index 0000000000000000000000000000000000000000..b1eb63c03283e8eb3244410a093a3ffec585a018 --- /dev/null +++ b/hub_module/modules/image/classification/resnext50_vd_64x4d_imagenet/module.py @@ -0,0 +1,206 @@ +# 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 os + +import numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +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, + is_vd_mode: bool = False, + act: str = None, + name: str = None, + ): + super(ConvBNLayer, self).__init__() + + self.is_vd_mode = is_vd_mode + self._pool2d_avg = AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True) + 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) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm(num_filters, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale'), + bias_attr=ParamAttr(bn_name + '_offset'), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs: paddle.Tensor): + if self.is_vd_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + """Bottleneck Block for ResNeXt50_vd.""" + def __init__(self, + num_channels: int, + num_filters: int, + stride: int, + cardinality: int, + shortcut: bool = True, + if_first: bool = False, + name: str = None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters, + filter_size=1, + act='relu', + name=name + "_branch2a") + self.conv1 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters, + filter_size=3, + groups=cardinality, + stride=stride, + act='relu', + name=name + "_branch2b") + self.conv2 = ConvBNLayer(num_channels=num_filters, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(num_channels=num_channels, + num_filters=num_filters * 2 if cardinality == 32 else num_filters, + filter_size=1, + stride=1, + is_vd_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs: paddle.Tensor): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + + y = paddle.elementwise_add(x=short, y=conv2, act='relu') + return y + + +@moduleinfo(name="resnext50_vd_64x4d_imagenet", + type="CV/classification", + author="paddlepaddle", + author_email="", + summary="resnext50_vd_64x4d_imagenet is a classification model, " + "this module is trained with Baidu open sourced dataset.", + version="1.1.0", + meta=ImageClassifierModule) +class ResNeXt50_vd(nn.Layer): + """ResNeXt50_vd model.""" + def __init__(self, class_dim: int = 1000, load_checkpoint: str = None): + super(ResNeXt50_vd, self).__init__() + + self.layers = 50 + self.cardinality = 64 + depth = [3, 4, 6, 3] + num_channels = [64, 256, 512, 1024] + num_filters = [256, 512, 1024, 2048] + + self.conv1_1 = ConvBNLayer(num_channels=3, num_filters=32, filter_size=3, stride=2, act='relu', name="conv1_1") + self.conv1_2 = ConvBNLayer(num_channels=32, num_filters=32, filter_size=3, stride=1, act='relu', name="conv1_2") + self.conv1_3 = ConvBNLayer(num_channels=32, num_filters=64, filter_size=3, stride=1, act='relu', name="conv1_3") + + self.pool2d_max = MaxPool2d(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock(num_channels=num_channels[block] if i == 0 else num_filters[block] * + int(64 // self.cardinality), + num_filters=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + cardinality=self.cardinality, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + + self.pool2d_avg = AdaptiveAvgPool2d(1) + + self.pool2d_avg_channels = num_channels[-1] * 2 + + stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0) + + self.out = Linear(self.pool2d_avg_channels, + class_dim, + weight_attr=ParamAttr(initializer=Uniform(-stdv, stdv), name="fc_weights"), + bias_attr=ParamAttr(name="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, 'resnext50_vd_64x4d_imagenet.pdparams') + if not os.path.exists(checkpoint): + os.system( + 'wget https://paddlehub.bj.bcebos.com/dygraph/image_classification/resnext50_vd_64x4d_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): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + y = self.pool2d_avg(y) + y = paddle.reshape(y, shape=[-1, self.pool2d_avg_channels]) + y = self.out(y) + return y