evaluation/tiny_benchmark/maskrcnn_benchmark/modeling/down_up_sampler.py (108 lines of code) (raw):
# add by hui ###################################
from torch import nn
import torch.nn.functional as F
from maskrcnn_benchmark.layers import ConvTranspose2d
import torch
import numpy as np
LEAKY_RELU_RATE = 0.1
class CBRBlock(nn.Module):
def __init__(self, in_channle, out_channle, kernel, stride, padding, no_relu=False, use_leaky_relu=False):
super(CBRBlock, self).__init__()
self.conv = nn.Conv2d(in_channle, out_channle, kernel, stride, padding)
self.bn = nn.BatchNorm2d(out_channle)
self.no_relu = no_relu
self.use_leaky_relu = use_leaky_relu
def forward(self, x):
x = self.bn(self.conv(x))
if not self.no_relu:
if self.use_leaky_relu:
x = F.leaky_relu(x, LEAKY_RELU_RATE)
else:
x = F.relu(x)
return x
class EmptyBlock(object):
def __call__(self, x):
return x
class DeConvUpSampler(nn.Module):
"""
up sample 4x
deconv(2, 2, 0)
transform():
CBR: Conv BN Relu
...
CBR
deconv(2, 2, 0)
transform()
"""
def __init__(self, num_inputs=256, dim_reduced=256, num_conv=0, no_transform1=False, first_kernel=3,
no_relu=False, use_leaky_relu=False):
super(DeConvUpSampler, self).__init__()
self.first_kernel = first_kernel
self.no_relu = no_relu
self.use_leaky_relu = use_leaky_relu
if no_transform1:
self.transform1 = EmptyBlock()
else:
self.transform1 = self.build_transform(num_inputs, dim_reduced, dim_reduced, num_conv)
self.deconv1 = ConvTranspose2d(dim_reduced, dim_reduced, 2, 2, 0)
self.transform2 = self.build_transform(dim_reduced, dim_reduced, dim_reduced, num_conv)
self.deconv2 = ConvTranspose2d(dim_reduced, num_inputs, 2, 2, 0)
for modules in [self.transform1.modules(), self.transform2.modules(), [self.deconv1, self.deconv2]]:
for l in modules:
if isinstance(l, (nn.Conv2d, nn.ConvTranspose2d)):
nn.init.kaiming_normal_(l.weight, mode="fan_out", nonlinearity="relu")
nn.init.constant_(l.bias, 0)
def build_transform(self, in_channel, reduce_channel, out_channel, num_conv):
if num_conv <= 0:
return EmptyBlock()
if num_conv == 1:
return nn.Sequential(CBRBlock(in_channel, out_channel, self.first_kernel, 1,
(self.first_kernel-1)//2, self.no_relu, self.use_leaky_relu))
transforms = [CBRBlock(in_channel, out_channel, self.first_kernel, 1,
(self.first_kernel-1)//2, self.no_relu, self.use_leaky_relu)]
for i in range(num_conv-2):
transforms.append(CBRBlock(reduce_channel, reduce_channel, 3, 1, 1, self.no_relu, self.use_leaky_relu))
transforms.append(CBRBlock(reduce_channel, out_channel, 3, 1, 1, self.no_relu, self.use_leaky_relu))
return nn.Sequential(*transforms)
def forward(self, features):
for i in range(len(features)):
x = self.deconv1(self.transform1(features[i]))
if not self.no_relu:
if self.use_leaky_relu:
x = F.leaky_relu(x, LEAKY_RELU_RATE)
else:
x = F.relu(x)
features[i] = self.deconv2(self.transform2(x))
return features
class InterpolateUpSampler(nn.Module):
def __init__(self, upsample_rate, upsample_mode):
super(InterpolateUpSampler, self).__init__()
self.upsample_rate = upsample_rate
self.upsample_mode = upsample_mode
def forward(self, features):
for i in range(len(features)):
features[i] = F.interpolate(features[i], scale_factor=self.upsample_rate[i], mode=self.upsample_mode)
return features
class PoolDownSampler(nn.Module):
def __init__(self, downsample_rate):
super(PoolDownSampler, self).__init__()
self.down_sample_rate = downsample_rate
def forward(self, features):
for i in range(len(features)):
s = self.down_sample_rate[i]
features[i] = F.avg_pool2d(features[i], s, s, 0)
return features
def build_sampler(cfg):
upsample_rate = cfg.MODEL.UPSAMPLE_RATE
upsample_mode = cfg.MODEL.UPSAMPLE_MODE # add by hui
upsample_transform_num_conv = cfg.MODEL.UPSAMPLE_TRANSFORM_NUM_CONV
assert len(upsample_rate) == 0 or len(cfg.MODEL.FPN.UPSAMPLE_RATE) == 0, \
'specified both cfg.MODEL.UPSAMPLE_RATE and cfg.MODEL.FPN.UPSAMPLE_RATE, it maybe a mistake.'
if len(upsample_rate) == 0:
return EmptyBlock() # empty
if upsample_mode == 'deconv':
sampler = DeConvUpSampler(num_conv=upsample_transform_num_conv)
elif upsample_mode == 'deconv2':
sampler = DeConvUpSampler(num_conv=upsample_transform_num_conv, no_transform1=True)
elif upsample_mode == 'deconv3':
sampler = DeConvUpSampler(num_conv=upsample_transform_num_conv, no_relu=True)
elif upsample_mode == 'deconv4':
sampler = DeConvUpSampler(num_conv=upsample_transform_num_conv, first_kernel=1)
elif upsample_mode == 'deconv5':
sampler = DeConvUpSampler(num_conv=upsample_transform_num_conv, use_leaky_relu=True)
elif upsample_mode == 'downsample':
downsample_rate = torch.round(1 / torch.Tensor(upsample_rate)).numpy().astype(np.int64).tolist()
print("use downsample rate {}".format(downsample_rate))
sampler = PoolDownSampler(downsample_rate)
else:
sampler = InterpolateUpSampler(upsample_rate, upsample_mode)
return sampler
# ##############################################