class ChannelIncreaseBlock(Module): """Channel increase block, which passes several blocks, and concat the result on channel dim.""" def __init__(self, blocks, base_channel): """Construct the class ChannelIncreaseBlock. :param blocks: list of string of the blocks :param base_channel: number of input channels """ super(ChannelIncreaseBlock, self).__init__() self.layers = list() for block_name in blocks: self.layers.append( NAME_BLOCKS[block_name](base_channel=base_channel)) self.layers = Sequential(*self.layers) self.blocks = self.layers.children() if isinstance( self.layers.children(), list) else list(self.layers.children()) def call(self, inputs): """Calculate the output of the model. :param x: input tensor :return: output tensor of the model """ out = () x = inputs for block in self.blocks: x = block(x) out += (x, ) return ops.concat(out)
def __init__(self, inp, hidden_dim, oup, kernel_size, stride, use_se=False, use_hs=False, momentum=0.1): """Init InvertedResidualSE.""" super(InvertedResidualSE, self).__init__() self.identity = stride == 1 and inp == oup self.ir_block = Sequential( # pw ops.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False), ops.BatchNorm2d(hidden_dim, momentum=momentum), ops.Hswish() if use_hs else ops.Relu(inplace=True), # dw ops.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False), ops.BatchNorm2d(hidden_dim, momentum=momentum), # Squeeze-and-Excite SELayer(hidden_dim) if use_se else Sequential(), ops.Hswish() if use_hs else ops.Relu(inplace=True), # pw-linear ops.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), ops.BatchNorm2d(oup, momentum=momentum), )
def __init__(self, num_classes, backbone='SerialBackbone', neck='TorchFPN', network_name='torchvision_FasterRCNN', weight_file=None, **kwargs): """Create layers. :param num_class: number of class :type num_class: int """ super(FasterRCNN, self).__init__() self.weight_file = weight_file backbone_cls = self.define_props('backbone', backbone, dtype=ClassType.NETWORK) backbone_cls.freeze() if getattr(backbone_cls, 'out_channels') and 'in_channels' not in neck: neck_in_channel = backbone_cls.out_channels params = {"in_channels": neck_in_channel} neck_cls = self.define_props('neck', neck, dtype=ClassType.NETWORK, params=params) else: neck_cls = self.define_props('neck', neck, dtype=ClassType.NETWORK) backbone_neck = Sequential(backbone_cls, neck_cls) backbone_neck.freeze() self.model = ClassFactory.get_cls(ClassType.NETWORK, network_name)(backbone_neck, num_classes, **kwargs)
def __init__(self, **descript): """Create layers.""" super().__init__() state_dim = descript.get("state_dim") action_dim = descript.get("action_dim") self.fc1 = Sequential(Linear(64, 64), Linear(64, action_dim)) self.fc2 = Sequential(Linear(64, 64), Linear(64, 1))
def __init__(self, cfgs, mode='small', input_channel=3, feat_channels=16, special_stride=1, num_classes=10, width_mult=1., block=InvertedResidualSE, momentum=0.1, is_prune_mode=False, **kwargs): """Init MobileNetV3. :params cfgs: cfgs for mobilenetv3 :type cfgs: list :params special_stride: the stride of the first InvertedResidualSE block. :type special_stride: int (1 for cifar10, 2 for imagenet) """ super(MobileNetV3, self).__init__() self.cfgs = cfgs # building first layer if not is_prune_mode: feat_channels = _make_divisible(feat_channels * width_mult, 8) else: feat_channels = int(feat_channels * width_mult) layers = [ ConvBnAct(input_channel, feat_channels, kernel_size=3, momentum=momentum, stride=special_stride, padding=1, activation='hswish') ] # buidling blocks # kernel_size, expand_ratio, output_channels, use_se, use_hs, stride for k, t, c, use_se, use_hs, s in self.cfgs: output_channel = _make_divisible( c * width_mult, 8) if not is_prune_mode else int(c * width_mult) hidden_dim = _make_divisible(t, 8) if not is_prune_mode else t layers.append( block(feat_channels, hidden_dim, output_channel, k, s, use_se, use_hs, momentum)) feat_channels = output_channel self.features = Sequential(*layers) # building last linear layer self.avgpool = ops.AdaptiveAvgPool2d((1, 1)) chn = 1280 if mode == 'large' else 1024 self.classifier = Sequential(ops.View(), ops.Linear(feat_channels, chn), ops.Hswish(), ops.Dropout(0.2), ops.Linear(chn, num_classes)) self._initialize_weights()
def __init__(self, **descript): """Create layers.""" super().__init__() state_dim = descript.get("state_dim") action_dim = descript.get("action_dim") self.fc2 = Sequential(Linear(state_dim, HIDDEN_SIZE), Linear(HIDDEN_SIZE, action_dim), Lambda(lambda x: softmax(x))) self.fc3 = Sequential(Linear(state_dim, HIDDEN_SIZE), Linear(HIDDEN_SIZE, 1))
def __init__(self, **descript): """Create layers.""" super().__init__() state_dim = descript.get("state_dim") action_dim = descript.get("action_dim") self.back_bone = PpoCnnBackBone(**descript) self.fc2 = Sequential(Linear(256, action_dim)) self.fc3 = Sequential(Linear(256, 1))
def __init__(self, **descript): """Create layers.""" super().__init__() state_dim = descript.get("state_dim") action_dim = descript.get("action_dim") self.back_bone = ImpalaCnnBackBone(**descript) self.fc2 = Sequential(Linear(256, action_dim), Lambda(lambda x: softmax(x))) self.fc3 = Sequential(Linear(256, 1))
def __init__(self, block_type, conv_num, growth_rate, type_prob, conv_prob, growth_prob, G0, scale, code, architecture): """Construct the ESRN class. :param net_desc: config of the searched structure :type net_desc: list """ super(ESRN, self).__init__() logging.info("start init ESRN") self.arch = architecture self.D = len(self.arch) r = scale G0 = G0 kSize = 3 n_colors = 3 self.SFENet1 = ops.Conv2d(n_colors, G0, kSize, padding=(kSize - 1) // 2, stride=1) self.ERDBLayer = ERDBLayer(architecture, G0, kSize) if r == 2 or r == 3: self.UPNet = Sequential( ops.Conv2d(G0, G0 * 3, kSize, padding=(kSize - 1) // 2, stride=1), ops.PixelShuffle(r), ops.Conv2d(int(G0 * 3 / 4), n_colors, kSize, padding=(kSize - 1) // 2, stride=1)) elif r == 4: self.UPNet = Sequential( ops.Conv2d(G0, G0 * 4, kSize, padding=(kSize - 1) // 2, stride=1), ops.PixelShuffle(2), ops.Conv2d(G0, G0 * 4, kSize, padding=(kSize - 1) // 2, stride=1), ops.PixelShuffle(2), ops.Conv2d(G0, n_colors, kSize, padding=(kSize - 1) // 2, stride=1)) else: raise ValueError("scale must be 2 or 3 or 4.")
def __init__(self, blocks, base_channel): """Construct the class ChannelIncreaseBlock. :param blocks: list of string of the blocks :param base_channel: number of input channels """ super(ChannelIncreaseBlock, self).__init__() self.layers = list() for block_name in blocks: self.layers.append( NAME_BLOCKS[block_name](base_channel=base_channel)) self.layers = Sequential(*self.layers)
class SerialBackbone(Module): """Serial Net for spnas.""" def __init__(self, code='111-2111-211111-211', block='BottleneckBlock', in_channels=64, weight_file=None, out_layers=None): """Init SerialBackbone.""" super(SerialBackbone, self).__init__() self.inplanes = in_channels self.planes = self.inplanes self.weight_file = weight_file self.channels = [3] self.code = code.split('-') self.block = ClassFactory.get_cls(ClassType.NETWORK, block) self._make_stem_layer() self.layers = Sequential() if out_layers == -1 else OutDictSequential() self.make_cells() @property def out_channels(self): """Output Channel for Module.""" return self.layers.out_channels def load_state_dict(self, state_dict=None, strict=None): """Remove backbone.""" state_dict = {k.replace('backbone.', ''): v for k, v in state_dict.items()} super().load_state_dict(state_dict, strict or False) def _make_stem_layer(self): """Make stem layer.""" self.conv1 = ops.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, bias=False) self.bn1 = ops.BatchNorm2d(self.inplanes) self.relu = ops.Relu(inplace=True) self.maxpool = ops.MaxPool2d(kernel_size=3, stride=2, padding=1) def make_cells(self): """Make ResNet Cell.""" for i, code in enumerate(self.code): layer, planes = self.make_layers(self.block, self.inplanes, self.planes, code=code) self.channels.append(planes) self.inplanes = planes self.layers.append(layer) self.planes = self.planes * 2 def make_layers(self, block, inplanes, planes, code=None): """Make ResNet layers.""" strides = list(map(int, code)) layers = [] layers.append(block(inplanes, planes, stride=strides[0])) inplanes = planes * block.expansion for stride in strides[1:]: layers.append(block(inplanes, planes, stride=stride)) inplanes = planes * block.expansion return Sequential(*layers), inplanes
def __init__(self, code='111-2111-211111-211', block='BottleneckBlock', in_channels=64, weight_file=None, out_layers=None): """Init SerialBackbone.""" super(SerialBackbone, self).__init__() self.inplanes = in_channels self.planes = self.inplanes self.weight_file = weight_file self.channels = [3] self.code = code.split('-') self.block = ClassFactory.get_cls(ClassType.NETWORK, block) self._make_stem_layer() self.layers = Sequential() if out_layers == -1 else OutDictSequential() self.make_cells()
def __init__(self, encoding, n_class=1000): super(DNet, self).__init__() op_names = ["conv3", "conv1", "conv3_grp2", "conv3_grp4", "conv3_base1", "conv3_base32", "conv3_sep"] block_str, num_channel, macro_str = encoding.split('_') curr_channel, index = int(num_channel), 0 _big_model = "*" in block_str if _big_model: block_encoding_list = block_str.split('*') # stem self.layers = Sequential( create_op('conv3', 3, curr_channel // 2, stride=2), ops.Relu(), create_op('conv3', curr_channel // 2, curr_channel // 2), ops.Relu(), create_op('conv3', curr_channel // 2, curr_channel, stride=2), ops.Relu() ) # body if not _big_model: while index < len(macro_str): stride = 1 if macro_str[index] == '-': stride = 2 index += 1 channel_increase = int(macro_str[index]) block = EncodedBlock(block_str, curr_channel, op_names, stride, channel_increase) self.layers.append(block) curr_channel *= channel_increase index += 1 else: block_encoding_index = 0 while index < len(macro_str): stride = 1 if macro_str[index] == '-': stride = 2 index += 1 block_encoding_index += 1 channel_increase = int(macro_str[index]) block_encoding = block_encoding_list[block_encoding_index] block = EncodedBlock(block_encoding, curr_channel, op_names, stride, channel_increase) self.layers.append(block) curr_channel *= channel_increase index += 1 self.layers.append(ops.AdaptiveAvgPool2d((1, 1))) self.view = ops.View() self.fc = ops.Linear(in_features=curr_channel, out_features=n_class)
def __init__(self, cfgs, input_channel=3, feat_channels=16, num_classes=10, width_mult=1., block=InvertedResidualSE, is_prune_mode=True, **kwargs): """Init MobileNetV3. :params cfgs: cfgs for mobilenetv3 :type cfgs: list """ super(MobileNetV3, self).__init__() self.cfgs = cfgs # building first layer if not is_prune_mode: feat_channels = _make_divisible(feat_channels * width_mult, 8) else: feat_channels = int(feat_channels * width_mult) layers = [ ConvBnAct(input_channel, feat_channels, kernel_size=3, stride=2, padding=1, activation='hswish') ] # buidling blocks # kernel_size, expand_ratio, output_channels, use_se, use_hs, stride for k, t, c, use_se, use_hs, s in self.cfgs: output_channel = _make_divisible( c * width_mult, 8) if not is_prune_mode else int(c * width_mult) hidden_dim = _make_divisible(t, 8) if not is_prune_mode else t layers.append( block(feat_channels, hidden_dim, output_channel, k, s, use_se, use_hs)) feat_channels = output_channel self.features = Sequential(*layers) # building last linear layer self.avgpool = ops.AdaptiveAvgPool2d((1, 1)) self.classifier = Sequential(ops.Linear(feat_channels, num_classes), ) self._initialize_weights()
def __init__(self, inChannels, growRate, sh_groups, conv_groups, kSize=3): """Initialize Block. :param inChannels: channel number of input :type inChannels: int :param growRate: growth rate of block :type growRate: int :param sh_groups: group number of shuffle operation :type sh_groups: int :param conv_groups: group number of convolution operation :type conv_groups: int :param kSize: kernel size of convolution operation :type kSize: int """ super(RDB_Conv, self).__init__() Cin = inChannels G = growRate self.shgroup = sh_groups self.congroup = conv_groups self.conv = Sequential( ops.Conv2d(Cin, G, kSize, padding=(kSize - 1) // 2, stride=1, groups=self.congroup), ops.Relu())
def make_res_layer_from_code(block, inplanes, planes, blocks, stride=1, dilation=1, style='pytorch', with_cp=False, code=None): """Make res layer from code.""" if code is None: return make_res_layer(block, inplanes, planes, blocks, stride, dilation, style, with_cp) strides = map(int, code) layers = [] for stride in strides: layers.append( block(inplanes=inplanes, planes=planes, stride=stride, dilation=dilation, style=style, with_cp=with_cp)) inplanes = planes * block.expansion return Sequential(*layers)
def __init__(self, inp, oup, stride, kernel=3, expand_ratio=1): """Construct InvertedResidual class. :param inp: input channel :param oup: output channel :param stride: stride :param kernel: kernel :param expand_ratio: channel increase multiplier """ super(InvertedConv, self).__init__() hidden_dim = round(inp * expand_ratio) conv = [] if expand_ratio > 1: conv = [ ops.Conv2d(in_channels=inp, out_channels=hidden_dim, kernel_size=1, stride=1, padding=0, bias=False), ops.BatchNorm2d(num_features=hidden_dim), ops.Relu6(inplace=True) ] conv = conv + [ ops.Conv2d(in_channels=hidden_dim, out_channels=hidden_dim, kernel_size=kernel, stride=stride, padding=kernel // 2, groups=hidden_dim, bias=False, depthwise=True), ops.BatchNorm2d(num_features=hidden_dim), ops.Relu6(inplace=True), ops.Conv2d(in_channels=hidden_dim, out_channels=oup, kernel_size=1, stride=1, padding=0, bias=False), ops.BatchNorm2d(num_features=oup) ] self.models = Sequential(*conv)
def __init__(self, in_chnls, cardinality, group_depth, stride): super(ResNeXt_Block, self).__init__() self.group_chnls = cardinality * group_depth self.conv1 = BN_Conv2d(in_chnls, self.group_chnls, 1, stride=1, padding=0) self.conv2 = BN_Conv2d(self.group_chnls, self.group_chnls, 3, stride=stride, padding=1, groups=cardinality) self.conv3 = ops.Conv2d(self.group_chnls, self.group_chnls * 2, 1, stride=1, padding=0) self.bn = ops.BatchNorm2d(self.group_chnls * 2) self.short_cut = Sequential( ops.Conv2d(in_chnls, self.group_chnls * 2, 1, stride, 0, bias=False), ops.BatchNorm2d(self.group_chnls * 2))
def __init__(self, in_channel, out_channel, upscale, rgb_mean, blocks, candidates, cib_range, method, code, block_range): """Construct the MtMSR class. :param net_desc: config of the searched structure """ super(MtMSR, self).__init__() logging.info("start init MTMSR") current_channel = in_channel layers = list() for i, block_name in enumerate(blocks): if isinstance(block_name, list): layers.append(ChannelIncreaseBlock(block_name, current_channel)) current_channel *= len(block_name) else: if block_name == "res2": layers.append( ResidualBlock(kernel_size=2, base_channel=current_channel)) elif block_name == "res3": layers.append( ResidualBlock(kernel_size=3, base_channel=current_channel)) layers.extend([ conv(current_channel, out_channel * upscale**2), ops.PixelShuffle(upscale) ]) initialize_weights(layers[-2], 0.1) self.sub_mean = ops.MeanShift(1.0, rgb_mean) body = Sequential(*layers) upsample = ops.InterpolateScale(scale_factor=upscale) self.add = Add(body, upsample) self.head = ops.MeanShift(1.0, rgb_mean, sign=1)
def make_resnet_layer_from_code(block, inplanes, planes, dilation=1, with_cp=False, code=None): """Make resnet layer from code.""" strides = list(map(int, code)) layers = [] layers.append( block(inplanes=inplanes, planes=planes, stride=strides[0], dilation=dilation, with_cp=with_cp, downsample=True)) inplanes = planes * block.expansion for stride in strides[1:]: layers.append( block(inplanes=inplanes, planes=planes, stride=stride, dilation=dilation, with_cp=with_cp)) inplanes = planes * block.expansion return Sequential(*layers), inplanes
def _make_layers(self, inplanes, d, blocks, stride, code): """Make layer.""" strides = map(int, code) layers = [] for stride in strides: layers.append(ResNeXt_Block(inplanes, self.cardinality, d, stride)) inplanes = self.cardinality * d * 2 return Sequential(*layers), inplanes
def __init__(self, in_channels, out_channels, kernel_size, stride, padding, dilation=1, groups=1, bias=False): super(BN_Conv2d, self).__init__() self.seq = Sequential( ops.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias), ops.BatchNorm2d(out_channels), ops.Relu() )
def __init__(self, channel, reduction=4): """Init SELayer.""" super(SELayer, self).__init__() self.avg_pool = ops.AdaptiveAvgPool2d(1) hidden_dim = _make_divisible(channel // reduction, 8) self.fc = Sequential(ops.Linear(channel, hidden_dim), ops.Relu(inplace=True), ops.Linear(hidden_dim, channel), ops.Hsigmoid())
def __init__(self, InChannel, OutChannel, growRate, nConvLayers, kSize=3): """Initialize Block. :param InChannel: channel number of input :type InChannel: int :param OutChannel: channel number of output :type OutChannel: int :param growRate: growth rate of block :type growRate: int :param nConvLayers: the number of convlution layer :type nConvLayers: int :param kSize: kernel size of convolution operation :type kSize: int """ super(Cont_RDB, self).__init__() self.InChan = InChannel self.OutChan = OutChannel self.G = growRate self.C = nConvLayers if self.InChan != self.G: self.InConv = ops.Conv2d(self.InChan, self.G, 1, padding=0, stride=1) if self.OutChan != self.G and self.OutChan != self.InChan: self.OutConv = ops.Conv2d(self.InChan, self.OutChan, 1, padding=0, stride=1) self.pool = ops.AvgPool2d(2, 2) self.shup = ops.PixelShuffle(2) self.Convs = ops.MoudleList() self.ShrinkConv = ops.MoudleList() for i in range(self.C): self.Convs.append( Sequential( ops.Conv2d(self.G, self.G, kSize, padding=(kSize - 1) // 2, stride=1), ops.Relu())) if i < (self.C - 1): self.ShrinkConv.append( ops.Conv2d((2 + i) * self.G, self.G, 1, padding=0, stride=1)) else: self.ShrinkConv.append( ops.Conv2d(int((2 + i) * self.G / 4), self.OutChan, 1, padding=0, stride=1))
def __init__(self, encoding): super(DNetBackbone, self).__init__() op_names = [ "conv3", "conv1", "conv3_grp2", "conv3_grp4", "conv3_base1", "conv3_base32", "conv3_sep" ] # code with kangning block_str, num_channel, macro_str = encoding.split('_') curr_channel, index = int(num_channel), 0 _big_model = "*" in block_str if _big_model: block_encoding_list = block_str.split('*') # stem layers = [ create_op('conv3', 3, curr_channel // 2, stride=2), ops.Relu(), create_op('conv3', curr_channel // 2, curr_channel // 2), ops.Relu(), create_op('conv3', curr_channel // 2, curr_channel, stride=2), ops.Relu() ] # body if not _big_model: while index < len(macro_str): stride = 1 if macro_str[index] == '-': stride = 2 index += 1 channel_increase = int(macro_str[index]) block = EncodedBlock(block_str, curr_channel, op_names, stride, channel_increase) layers.append(block) curr_channel *= channel_increase index += 1 else: block_encoding_index = 0 while index < len(macro_str): stride = 1 if macro_str[index] == '-': stride = 2 index += 1 block_encoding_index += 1 channel_increase = int(macro_str[index]) block_encoding = block_encoding_list[block_encoding_index] block = EncodedBlock(block_encoding, curr_channel, op_names, stride, channel_increase) layers.append(block) curr_channel *= channel_increase index += 1 layers.append(ops.AdaptiveAvgPool2d((1, 1))) self.layers = Sequential(*layers)
def make_layers(self, block, inplanes, planes, code=None): """Make ResNet layers.""" strides = list(map(int, code)) layers = [] layers.append(block(inplanes, planes, stride=strides[0])) inplanes = planes * block.expansion for stride in strides[1:]: layers.append(block(inplanes, planes, stride=stride)) inplanes = planes * block.expansion return Sequential(*layers), inplanes
def _blocks(self, out_channels, desc_blocks): blocks = ModuleList() in_channels = 32 for i in range(desc_blocks): blocks.append(Sequential( ops.Conv2d(in_channels, out_channels, padding=1, kernel_size=3), ops.BatchNorm2d(out_channels), ops.Relu(inplace=True), )) in_channels = out_channels return blocks
def __init__(self, arch, G0, kSize): """Create ERDBLayer. :param arch: arch :type arch: dict :param G0: G0 :type G0: G0 :param kSize: kSize :type kSize: int """ super(ERDBLayer, self).__init__() self.SFENet2 = ops.Conv2d(G0, G0, kSize, padding=(kSize - 1) // 2, stride=1) b_in_chan = G0 b_out_chan = 0 Conc_all = 0 ERDBs = ops.MoudleList() for i in range(len(arch)): name = arch[i] key = name.split('_') if i > 0: b_in_chan = b_out_chan b_conv_num = int(key[1]) b_grow_rat = int(key[2]) b_out_chan = int(key[3]) Conc_all += b_out_chan if key[0] == 'S': ERDBs.append( Shrink_RDB(InChannel=b_in_chan, OutChannel=b_out_chan, growRate=b_grow_rat, nConvLayers=b_conv_num)) elif key[0] == 'G': ERDBs.append( Group_RDB(InChannel=b_in_chan, OutChannel=b_out_chan, growRate=b_grow_rat, nConvLayers=b_conv_num)) elif key[0] == 'C': ERDBs.append( Cont_RDB(InChannel=b_in_chan, OutChannel=b_out_chan, growRate=b_grow_rat, nConvLayers=b_conv_num)) self.ERBD = ERDBs self.GFF = Sequential( ops.Conv2d(Conc_all, G0, 1, padding=0, stride=1), ops.Conv2d(G0, G0, kSize, padding=(kSize - 1) // 2, stride=1))
def make_res_layer(block, inplanes, planes, blocks, stride=1, dilation=1, style='pytorch', with_cp=False): """Build resnet layer.""" downsample = None if stride != 1 or inplanes != planes * block.expansion: conv_layer = ops.Conv2d(inplanes, planes * block.expansion, kernel_size=1, stride=stride, bias=False) norm_layer = ops.BatchNorm2d(planes * block.expansion) downsample = Sequential(conv_layer, norm_layer) layers = [] layers.append( block(inplanes=inplanes, planes=planes, stride=stride, dilation=dilation, downsample=downsample, style=style, with_cp=with_cp)) inplanes = planes * block.expansion for i in range(1, blocks): layers.append( block(inplanes=inplanes, planes=planes, stride=1, dilation=dilation, style=style, with_cp=with_cp)) return Sequential(*layers)
def __init__(self, inplanes, planes, stride=1, dilation=1, downsample=None, style='pytorch', with_cp=False): """Init Bottleneck.""" super(Bottleneck, self).__init__() assert style in ['pytorch', 'caffe'] self.inplanes = inplanes self.planes = planes self.stride = stride self.dilation = dilation self.style = style self.with_cp = with_cp self.norm1 = ops.BatchNorm2d(planes) self.norm2 = ops.BatchNorm2d(planes) self.norm3 = ops.BatchNorm2d(planes * self.expansion) self.conv1 = ops.Conv2d(inplanes, planes, kernel_size=1, bias=False) self.with_modulated_dcn = False self.conv2 = ops.Conv2d( planes, planes, kernel_size=3, stride=stride, padding=dilation, dilation=dilation, bias=False, ) self.conv3 = ops.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False) self.relu = ops.Relu(inplace=True) if stride > 1 or downsample is not None: conv_layer = ops.Conv2d(inplanes, planes * self.expansion, kernel_size=1, stride=stride, bias=False) norm_layer = ops.BatchNorm2d(planes * self.expansion) self.downsample = Sequential(conv_layer, norm_layer) else: self.downsample = None