def __init__(self, indepth, middepth=0, outdepth=1000, dropout=(0, 0), active='relu', with_fc=True, active_me=True): """ - indepth: 对所有输入x, 进行拼接后的输入通道数 - middepth: fc 层的中间隐藏层,=0 则无隐藏层 - outdepth: 输出通道数 => nlabels - dropout: fc 层的辍学率 - active: fc 层的激活函数 - withfc: when indepth==outdepth, False => 不添加fc层,直接输出拼接向量进行分类. - active_me: 是否激活当前模块,不激活则计算时绕过此模块 """ super(ConcatSummary, self).__init__(active_me) if not with_fc: assert indepth == outdepth, '<withfc> can be False only under <indepth>==<outdepth>.' self.classifier = ReturnX() else: self.classifier = Clssifier(indepth, middepth, outdepth, dropout, active)
def __init__(self, indepth, outdepth, ksize=1, stride=1, padding=0, dilation=1, groups='gcu||1', active='relu', isview=True, which=0): """ 用conv_KxK提升fmap通道,并转换为特征向量fvector。ksize为当前特征图的平面尺寸。 self.view ==> AdaPoolView(). 比如224x224训练,ksize=28x28,可获得1x1的特征图; 但当改变输入尺寸为320x320时,ksize却不能随之而变为40x40,仍然是固定的28x28, 因而获得的fmap不是1x1,需要AdaPoolView()。 """ super(AdaConvView, self).__init__() self.which = which if groups == 'gcu': groups = xtils.GCU(indepth, outdepth) self.conv = nn.Conv2d(indepth, outdepth, ksize, stride, padding, dilation, groups, bias=False) # can not work on 1x1-fmap # self.bn = nn.BatchNorm1d(outdepth) active = self._ActiveFuc[active] self.active = active(inplace=True) self.view = [ReturnX(), AdaPoolView('avg', -1, 0)][isview]
class RetxSummary(Summary): """ 将输入直接返回,作为输出. """ def __init__(self, active_me=True): super(RetxSummary, self).__init__(active_me=active_me) self.classifier = ReturnX() def forward(self, x): x = self.classifier(x) return x def __repr__(self): strme = self.__class__.__name__ + '(\n' + \ ' (classifier): ' + self.classifier.__repr__() + '\n)' return strme
def __init__(self, indepth=3, outdepth=16, branch=3, expand=(0, 0), dataset='cfar'): super(RockBlockN, self).__init__() self.indepth = indepth self.outdepth = outdepth self.branch = branch self.expand = expand if dataset == 'cifar': self.branch1 = nn.Conv2d(indepth, outdepth, kernel_size=3, stride=1, padding=1, bias=False) if indepth == outdepth: self.branch1 = ReturnX() if branch >= 2: self.branch2 = nn.Conv2d(indepth, outdepth + expand[0], kernel_size=3, stride=2, padding=1, bias=False) if branch >= 3: self.branch3 = nn.Sequential( nn.Conv2d(indepth, outdepth + expand[0] + expand[1], kernel_size=3, stride=2, padding=1, bias=False), nn.MaxPool2d(kernel_size=2, stride=2, padding=0), ) elif dataset == 'imagenet': self.branch1 = nn.Sequential( nn.Conv2d(indepth, outdepth, kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(outdepth), nn.ReLU(inplace=True), # nn.MaxPool2d(kernel_size=3, stride=2, padding=1), nn.MaxPool2d(kernel_size=2, stride=2, padding=0), ) if branch >= 2: self.branch2 = nn.Sequential( nn.Conv2d(indepth, outdepth + expand[0], kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(outdepth + expand[0]), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=4, stride=4, padding=0), ) if branch >= 3: self.branch3 = nn.Sequential( nn.Conv2d(indepth, outdepth + expand[0] + expand[1], kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(outdepth + expand[0] + expand[1]), nn.ReLU(inplace=True), # ?? nn.MaxPool2d(kernel_size=4, stride=4, padding=0), nn.MaxPool2d(kernel_size=2, stride=2, padding=0) )
def __init__(self, active_me=True): super(RetxSummary, self).__init__(active_me=active_me) self.classifier = ReturnX()
def __init__(self, indepth, outdepth, growth, pre_ind_grow, ksp='3.1.1', pre_ksp_half=False, groups='auto', skgroups='gcu', active='relu', dropout=0.0, isse=1, seactive='hsig', first=False, idx=1): """ - indepth: 当前block的输入通道数. - outdepth: 当前block的输出通道数. - growth: 当前block的通道增长数. - pre_ind_grow: 上一个block内, 输入通道数indepth + 通道增长数growth 的值. - ksp: kernel_size, stride, padding in Depth-Wise Convolution. cur_ksp_half, 当前block内是否将特征图尺寸减半. - pre_ksp_half: 上一个block内, 是否对特征图进行了尺寸减半. - groups: groups 值 in Depth-Wise Convolution. - skgroups: 所有 skip 连接的groups值, skip-groups - active: - dropout: - isse: 是否包含SeModule. =1: no-SeModule ; >1: has-SeModule(reduction=isse) 默认值4 - first: - idx: """ super(MoBlock, self).__init__() Active = self._ActiveFuc[active] ksp = [int(x) for x in ksp.split(sep='.')] assert len(ksp) == 3 cur_ksp_half = bool(ksp[1] == 2) self.ksp = ksp assert dropout * ( 0.5 - dropout ) >= 0, '<dropout> must be in [0, 0.5], but get %s .' % dropout self.dropout = dropout assert isse >= 1 and isinstance( isse, int), '<isse> must be a int >=1, but get %s .' % isse self.isse = isse self.first = first self.idx = idx if groups == '1x': groups = 1 elif groups == 'auto': groups = indepth + growth curr_ind_grow = indepth + growth self.conv1 = nn.Conv2d(indepth, curr_ind_grow, kernel_size=1, stride=1, padding=0, bias=False) self.bn1 = nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1) self.act1 = Active(inplace=True) # depth-wise conv self.conv2 = nn.Conv2d(curr_ind_grow, curr_ind_grow, ksp[0], ksp[1], ksp[2], groups=groups, bias=False) self.bn2 = nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1) self.act2 = Active(inplace=True) self.segate2 = [ ReturnX(), SeModule(curr_ind_grow, isse, active=seactive) ][isse != 1] # 计算 skip1 & skip2 if self.first: self.skip1 = ReturnX() self.skip2 = ReturnX() else: if curr_ind_grow == pre_ind_grow: skip_group = GCU(pre_ind_grow, curr_ind_grow) if skgroups == 'gcu' else 1 if not pre_ksp_half: # print('init---> idx %s .' % idx) self.skip1 = ReturnX() else: skip1_ksp = (2, 2, 0) self.skip1 = nn.Sequential( nn.Conv2d(pre_ind_grow, curr_ind_grow, skip1_ksp[0], skip1_ksp[1], skip1_ksp[2], bias=False, groups=skip_group), nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1)) if not cur_ksp_half: self.skip2 = ReturnX() else: skip2_ksp = (2, 2, 0) self.skip2 = nn.Sequential( nn.Conv2d(pre_ind_grow, curr_ind_grow, skip2_ksp[0], skip2_ksp[1], skip2_ksp[2], bias=False, groups=skip_group), nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1)) elif curr_ind_grow != pre_ind_grow: skip_group = GCU(pre_ind_grow, curr_ind_grow) if skgroups == 'gcu' else 1 skip1_ksp = (2, 2, 0) if pre_ksp_half else (1, 1, 0) skip2_ksp = (2, 2, 0) if cur_ksp_half else (1, 1, 0) self.skip1 = nn.Sequential( nn.Conv2d(pre_ind_grow, curr_ind_grow, skip1_ksp[0], skip1_ksp[1], skip1_ksp[2], bias=False, groups=skip_group), nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1)) self.skip2 = nn.Sequential( nn.Conv2d(pre_ind_grow, curr_ind_grow, skip2_ksp[0], skip2_ksp[1], skip2_ksp[2], bias=False, groups=skip_group), nn.BatchNorm2d(curr_ind_grow, eps=1e-05, momentum=0.1)) # 计算skip3 if outdepth == indepth and not cur_ksp_half: self.skip3 = ReturnX() else: skip3_ksp = (2, 2, 0) if cur_ksp_half else (1, 1, 0) skip_group = GCU(indepth, outdepth) if skgroups == 'gcu' else 1 self.skip3 = nn.Sequential( nn.Conv2d(indepth, outdepth, skip3_ksp[0], skip3_ksp[1], skip3_ksp[2], bias=False, groups=skip_group), nn.BatchNorm2d(outdepth, eps=1e-05, momentum=0.1)) # point-wise conv self.conv3 = nn.Conv2d(curr_ind_grow, outdepth, kernel_size=1, stride=1, padding=0, groups=1, bias=False) self.bn3 = nn.BatchNorm2d(outdepth, eps=1e-05, momentum=0.1) self.act3 = Active(inplace=True) self.drop3 = nn.Dropout2d(p=dropout, inplace=False)
def __init__(self, block='P', nblocks=(3, 3, 3), inplanes=16, bottle=1, active='fx', dataset='cifar10'): """ Constructor Args: bottle: =1 a ResPlain block; >1 a dilate ResBottle block; <1, a shrink ResBottle block. """ super(XResNet, self).__init__() assert block in self.residual.keys( ), 'Unknown residual block: %s.' % block assert dataset in self.datasets.keys( ), 'Unsupported dataset: %s.' % dataset assert len(nblocks) == [ 4, 3 ][dataset != 'imagenet'], 'Assure <nblocks> match with dataset.' block = self.residual[block] self.block = block self.nblocks = nblocks self.inplanes = inplanes self.bottle = bottle self.active = active self.dataset = dataset nlabels = self.datasets[dataset] nplanes = [inplanes, 2 * inplanes, 4 * inplanes, 8 * inplanes] nblocks = nblocks if len( nblocks) >= 4 else list(nblocks) + [-1] # 添加伪数,防止越界 nbottls = [bottle] * len(nblocks) self.preproc = PreProc(3, nplanes[0], dataset) self.stage_1 = self._make_layer(block, nplanes[0], nblocks[0], nbottls[0], stride=1) self.stage_2 = self._make_layer(block, nplanes[1], nblocks[1], nbottls[1], stride=2) self.stage_3 = self._make_layer(block, nplanes[2], nblocks[2], nbottls[2], stride=2) self.stage_4 = [ self._make_layer(block, nplanes[3], nblocks[3], nbottls[3], stride=2), ReturnX() ][dataset != 'imagenet'] out_planes = [nplanes[-1], nplanes[-2]][dataset != 'imagenet'] self.squeeze = nn.Sequential( nn.BatchNorm2d(out_planes * block.expansion), nn.ReLU(inplace=True), AdaAvgPool(), ViewLayer()) self.classifier = nn.Linear(out_planes * block.expansion, nlabels) self._init_params()
def __init__(self, depth, expand, growth, slink='A', after=True, down=False, dfunc='A', dstyle=('maxpool', 'convk3m', 'convk2'), classify=0, nclass=1000, last_branch=1, last_down=False, last_dfuc='D', version=1): super(DoubleCouple, self).__init__() assert last_branch <= 3, '<last_branch> of DoubleCouple should be <= 3...' assert len(growth) == 2, 'len of <growth> of DoubleCouple should be 2' assert last_dfuc != 'O', '<last_dfuc> of DoubleCouple should not be "O", ' \ 'choose others in <down_func_dict>' assert set(dstyle).issubset( self.down_style ), '<dstyle> should be in <down_style>, but %s.' % dstyle assert version in [ 1, 2, 3, 5 ], '<version> now expected in [1, 2, 3, 5], but %s.' % version self.depth = depth self.expand = expand self.growth = growth # how much channels will be added or minus, when plain size is halved or doubled. growtha, growthb = growth self.slink = slink self.after = after # dose still have another DoubleCouple behind of this DoubleCouple. ? self.down = [down, ['independent', 'interactive'][dfunc == 'O']][down] # dose connect to a same-size DoubleCouple or down-sized DoubleCouple. ? self.dfunc = dfunc self.down_func = self.down_func_dict[dfunc] self.dstyle = dstyle self.last_branch = last_branch # how many output-ways (branches) for the classifier ? self.last_down = last_down # dose down size for the classifier? self.last_dfuc = self.down_func_dict[last_dfuc] self.classify = classify self.nclass = nclass self.version = version self.active_fc = False if version in [1, 2]: deck, decop = 4, 0 elif version == 3: deck, decop = 3, 1 elif version == 5: pass self.bn1 = nn.BatchNorm2d(depth) self.conv1 = nn.Conv2d(depth, depth + growtha, 3, stride=2, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(depth + growtha) self.conv2 = nn.Conv2d(depth + growtha, depth + 2 * growtha, 3, stride=2, padding=1, bias=False) if version in [1, 2, 3]: self.bn3 = nn.BatchNorm2d(depth + 2 * growtha) self.deconv3 = nn.ConvTranspose2d(depth + 2 * growtha, depth + growtha, deck, stride=2, padding=1, bias=False, output_padding=decop, dilation=1) self.bn4 = nn.BatchNorm2d(depth + growtha) self.deconv4 = nn.ConvTranspose2d(depth + growtha, depth, deck, stride=2, padding=1, bias=False, output_padding=decop, dilation=1) elif version == 5: self.bn3 = nn.BatchNorm2d(depth + 2 * growtha) self.deconv3 = nn.UpsamplingNearest2d(scale_factor=2) self.bn4 = nn.BatchNorm2d(depth + growtha) self.deconv4 = nn.UpsamplingNearest2d(scale_factor=2) if self.classify > 0: self.classifier = XClassifier(depth + 2 * growtha, nclass) if self.after: if self.down == 'independent': self.down_res4 = self.down_func(depth, depth + expand) self.down_res3 = self.down_func(depth + growtha, depth + expand + growthb) self.down_res2 = self.down_func(depth + 2 * growtha, depth + expand + 2 * growthb) elif self.down == 'interactive': self.down_res4 = self.down_func(depth, depth, 2, dstyle[0]) self.down_res3 = self.down_func(depth + growtha, depth + growtha, 2, dstyle[0]) self.down_res2 = self.down_func(depth + 2 * growtha, depth + 2 * growtha, 2, dstyle[0]) self.down_res4x = self.down_func(depth, depth, 4, dstyle[1]) if version == 1: self.comp_res4 = nn.Conv2d(depth * 2 + growtha, depth + expand, 1, 1, 0, bias=False) self.comp_res3 = nn.Conv2d(depth * 2 + 3 * growtha, depth + expand + growthb, 1, 1, 0, bias=False) self.comp_res2 = nn.Conv2d(depth * 2 + 2 * growtha, depth + expand + 2 * growthb, 1, 1, 0, bias=False) else: self.comp_res4 = [ nn.Conv2d(depth * 2 + growtha, depth + expand, 1, 1, 0, bias=False), ReturnX() ][depth * 2 + growtha == depth + expand] self.comp_res3 = [ nn.Conv2d(depth * 2 + 3 * growtha, depth + expand + growthb, 1, 1, 0, bias=False), ReturnX() ][depth * 2 + 3 * growtha == depth + expand + growthb] self.comp_res2 = \ [nn.Conv2d(depth * 2 + 2 * growtha, depth + expand + 2 * growthb, 1, 1, 0, bias=False), ReturnX()][depth * 2 + 2 * growtha == depth + expand + 2 * growthb] else: if self.last_down is True: if self.last_branch >= 1: self.down_last4 = self.last_dfuc(depth, depth + growthb) if self.last_branch >= 2: self.down_last3 = self.last_dfuc(depth + growtha, depth + growthb) if self.last_branch >= 3: self.down_last2 = self.last_dfuc(depth + 2 * growtha, depth + growthb) elif self.last_down is False: if self.classify > 0 and self.last_branch == 3: # 最后一个Couple的中间层被当做branch输出而对接在Summary上. # 因此,删除此Couple自带的Classifier,以免与Summary中的Classifier重复. delattr(self, 'classifier') self.classify = 0 print( '\nNote ****: 1 xfc will be deleted because of duplicate with the last-fc!\n' ) elif self.last_down is None: # 删除整个网络最末端的DoubleCouple中最后的2个DeConv层,分类器将直接扣在保留下的Conv层的输出上. units_in_last_couple = ['bn3', 'deconv3', 'bn4', 'deconv4'] for unit in units_in_last_couple: # setattr(self, unit, ReturnX()) delattr(self, unit)