| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- # copyright (c) 2021 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.
- # Code was based on https://github.com/d-li14/involution
- import paddle
- import paddle.nn as nn
- from paddle.vision.models import resnet
- from paddlex.ppcls.utils.save_load import load_dygraph_pretrain, load_dygraph_pretrain_from_url
- MODEL_URLS = {
- "RedNet26":
- "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/RedNet26_pretrained.pdparams",
- "RedNet38":
- "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/RedNet38_pretrained.pdparams",
- "RedNet50":
- "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/RedNet50_pretrained.pdparams",
- "RedNet101":
- "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/RedNet101_pretrained.pdparams",
- "RedNet152":
- "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/RedNet152_pretrained.pdparams"
- }
- __all__ = MODEL_URLS.keys()
- class Involution(nn.Layer):
- def __init__(self, channels, kernel_size, stride):
- super(Involution, self).__init__()
- self.kernel_size = kernel_size
- self.stride = stride
- self.channels = channels
- reduction_ratio = 4
- self.group_channels = 16
- self.groups = self.channels // self.group_channels
- self.conv1 = nn.Sequential(
- ('conv', nn.Conv2D(
- in_channels=channels,
- out_channels=channels // reduction_ratio,
- kernel_size=1,
- bias_attr=False)),
- ('bn', nn.BatchNorm2D(channels // reduction_ratio)),
- ('activate', nn.ReLU()))
- self.conv2 = nn.Sequential(('conv', nn.Conv2D(
- in_channels=channels // reduction_ratio,
- out_channels=kernel_size**2 * self.groups,
- kernel_size=1,
- stride=1)))
- if stride > 1:
- self.avgpool = nn.AvgPool2D(stride, stride)
- def forward(self, x):
- weight = self.conv2(
- self.conv1(x if self.stride == 1 else self.avgpool(x)))
- b, c, h, w = weight.shape
- weight = weight.reshape(
- (b, self.groups, self.kernel_size**2, h, w)).unsqueeze(2)
- out = nn.functional.unfold(x, self.kernel_size, self.stride,
- (self.kernel_size - 1) // 2, 1)
- out = out.reshape(
- (b, self.groups, self.group_channels, self.kernel_size**2, h, w))
- out = (weight * out).sum(axis=3).reshape((b, self.channels, h, w))
- return out
- class BottleneckBlock(resnet.BottleneckBlock):
- def __init__(self,
- inplanes,
- planes,
- stride=1,
- downsample=None,
- groups=1,
- base_width=64,
- dilation=1,
- norm_layer=None):
- super(BottleneckBlock, self).__init__(inplanes, planes, stride,
- downsample, groups, base_width,
- dilation, norm_layer)
- width = int(planes * (base_width / 64.)) * groups
- self.conv2 = Involution(width, 7, stride)
- class RedNet(resnet.ResNet):
- def __init__(self, block, depth, class_num=1000, with_pool=True):
- super(RedNet, self).__init__(
- block=block, depth=50, num_classes=class_num, with_pool=with_pool)
- layer_cfg = {
- 26: [1, 2, 4, 1],
- 38: [2, 3, 5, 2],
- 50: [3, 4, 6, 3],
- 101: [3, 4, 23, 3],
- 152: [3, 8, 36, 3]
- }
- layers = layer_cfg[depth]
- self.conv1 = None
- self.bn1 = None
- self.relu = None
- self.inplanes = 64
- self.class_num = class_num
- self.stem = nn.Sequential(
- nn.Sequential(
- ('conv', nn.Conv2D(
- in_channels=3,
- out_channels=self.inplanes // 2,
- kernel_size=3,
- stride=2,
- padding=1,
- bias_attr=False)),
- ('bn', nn.BatchNorm2D(self.inplanes // 2)),
- ('activate', nn.ReLU())),
- Involution(self.inplanes // 2, 3, 1),
- nn.BatchNorm2D(self.inplanes // 2),
- nn.ReLU(),
- nn.Sequential(
- ('conv', nn.Conv2D(
- in_channels=self.inplanes // 2,
- out_channels=self.inplanes,
- kernel_size=3,
- stride=1,
- padding=1,
- bias_attr=False)), ('bn', nn.BatchNorm2D(self.inplanes)),
- ('activate', nn.ReLU())))
- self.layer1 = self._make_layer(block, 64, layers[0])
- self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
- self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
- self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
- def forward(self, x):
- x = self.stem(x)
- x = self.maxpool(x)
- x = self.layer1(x)
- x = self.layer2(x)
- x = self.layer3(x)
- x = self.layer4(x)
- if self.with_pool:
- x = self.avgpool(x)
- if self.class_num > 0:
- x = paddle.flatten(x, 1)
- x = self.fc(x)
- return x
- def _load_pretrained(pretrained, model, model_url, use_ssld=False):
- if pretrained is False:
- pass
- elif pretrained is True:
- load_dygraph_pretrain_from_url(model, model_url, use_ssld=use_ssld)
- elif isinstance(pretrained, str):
- load_dygraph_pretrain(model, pretrained)
- else:
- raise RuntimeError(
- "pretrained type is not available. Please use `string` or `boolean` type."
- )
- def RedNet26(pretrained=False, **kwargs):
- model = RedNet(BottleneckBlock, 26, **kwargs)
- _load_pretrained(pretrained, model, MODEL_URLS["RedNet26"])
- return model
- def RedNet38(pretrained=False, **kwargs):
- model = RedNet(BottleneckBlock, 38, **kwargs)
- _load_pretrained(pretrained, model, MODEL_URLS["RedNet38"])
- return model
- def RedNet50(pretrained=False, **kwargs):
- model = RedNet(BottleneckBlock, 50, **kwargs)
- _load_pretrained(pretrained, model, MODEL_URLS["RedNet50"])
- return model
- def RedNet101(pretrained=False, **kwargs):
- model = RedNet(BottleneckBlock, 101, **kwargs)
- _load_pretrained(pretrained, model, MODEL_URLS["RedNet101"])
- return model
- def RedNet152(pretrained=False, **kwargs):
- model = RedNet(BottleneckBlock, 152, **kwargs)
- _load_pretrained(pretrained, model, MODEL_URLS["RedNet152"])
- return model
|