"""This file contains helper functions for building the model and for loading model parameters.These helper functions are built to mirror those in the official TensorFlow implementation."""import reimport mathimport collectionsimport torchfrom torch import nnfrom torch.nn import functional as Ffrom torch.utils import model_zoo####################################################################################### HELPERS FUNCTIONS FOR MODEL ARCHITECTURE ######################################################################################## Parameters for the entire model (stem, all blocks, and head)GlobalParams = collections.namedtuple('GlobalParams', ['batch_norm_momentum', 'batch_norm_epsilon', 'dropout_rate','num_classes', 'width_coefficient', 'depth_coefficient','depth_divisor', 'min_depth', 'drop_connect_rate',])# Parameters for an individual model blockBlockArgs = collections.namedtuple('BlockArgs', ['kernel_size', 'num_repeat', 'input_filters', 'output_filters','expand_ratio', 'id_skip', 'stride', 'se_ratio'])# Change namedtuple defaultsGlobalParams.__new__.__defaults__ = (None,) * len(GlobalParams._fields)BlockArgs.__new__.__defaults__ = (None,) * len(BlockArgs._fields)def relu_fn(x):""" Swish activation function """return x * torch.sigmoid(x)def round_filters(filters, global_params):""" Calculate and round number of filters based on depth multiplier. """multiplier = global_params.width_coefficientif not multiplier:return filtersdivisor = global_params.depth_divisormin_depth = global_params.min_depthfilters *= multipliermin_depth = min_depth or divisornew_filters = max(min_depth, int(filters + divisor / 2) // divisor * divisor)if new_filters < 0.9 * filters: # prevent rounding by more than 10%new_filters += divisorreturn int(new_filters)def round_repeats(repeats, global_params):""" Round number of filters based on depth multiplier. """multiplier = global_params.depth_coefficientif not multiplier:return repeatsreturn int(math.ceil(multiplier * repeats))def drop_connect(inputs, p, training):""" Drop connect. """if not training: return inputsbatch_size = inputs.shape[0]keep_prob = 1 - prandom_tensor = keep_probrandom_tensor += torch.rand([batch_size, 1, 1, 1], dtype=inputs.dtype) # uniform [0,1)binary_tensor = torch.floor(random_tensor)output = inputs / keep_prob * binary_tensorreturn outputclass Conv2dSamePadding(nn.Conv2d):""" 2D Convolutions like TensorFlow """def __init__(self, in_channels, out_channels, kernel_size, stride=1, dilation=1, groups=1, bias=True):super().__init__(in_channels, out_channels, kernel_size, stride, 0, dilation, groups, bias)self.stride = self.stride if len(self.stride) == 2 else [self.stride[0]]*2def forward(self, x):ih, iw = x.size()[-2:]kh, kw = self.weight.size()[-2:]sh, sw = self.strideoh, ow = math.ceil(ih / sh), math.ceil(iw / sw)pad_h = max((oh - 1) * self.stride[0] + (kh - 1) * self.dilation[0] + 1 - ih, 0)pad_w = max((ow - 1) * self.stride[1] + (kw - 1) * self.dilation[1] + 1 - iw, 0)if pad_h > 0 or pad_w > 0:x = F.pad(x, [pad_w//2, pad_w - pad_w//2, pad_h//2, pad_h - pad_h//2])return F.conv2d(x, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)###################################################################################### HELPERS FUNCTIONS FOR LOADING MODEL PARAMS ######################################################################################def efficientnet_params(model_name):""" Map EfficientNet model name to parameter coefficients. """params_dict = {# Coefficients: width,depth,res,dropout'efficientnet-b0': (1.0, 1.0, 224, 0.2),'efficientnet-b1': (1.0, 1.1, 240, 0.2),'efficientnet-b2': (1.1, 1.2, 260, 0.3),'efficientnet-b3': (1.2, 1.4, 300, 0.3),'efficientnet-b4': (1.4, 1.8, 380, 0.4),'efficientnet-b5': (1.6, 2.2, 456, 0.4),'efficientnet-b6': (1.8, 2.6, 528, 0.5),'efficientnet-b7': (2.0, 3.1, 600, 0.5),}return params_dict[model_name]class BlockDecoder(object):""" Block Decoder for readability, straight from the official TensorFlow repository """@staticmethoddef _decode_block_string(block_string):""" Gets a block through a string notation of arguments. """assert isinstance(block_string, str)ops = block_string.split('_')options = {}for op in ops:splits = re.split(r'(\d.*)', op)if len(splits) >= 2:key, value = splits[:2]options[key] = value# Check strideassert (('s' in options and len(options['s']) == 1) or(len(options['s']) == 2 and options['s'][0] == options['s'][1]))return BlockArgs(kernel_size=int(options['k']),num_repeat=int(options['r']),input_filters=int(options['i']),output_filters=int(options['o']),expand_ratio=int(options['e']),id_skip=('noskip' not in block_string),se_ratio=float(options['se']) if 'se' in options else None,stride=[int(options['s'][0])])@staticmethoddef _encode_block_string(block):"""Encodes a block to a string."""args = ['r%d' % block.num_repeat,'k%d' % block.kernel_size,'s%d%d' % (block.strides[0], block.strides[1]),'e%s' % block.expand_ratio,'i%d' % block.input_filters,'o%d' % block.output_filters]if 0 < block.se_ratio <= 1:args.append('se%s' % block.se_ratio)if block.id_skip is False:args.append('noskip')return '_'.join(args)@staticmethoddef decode(string_list):"""Decodes a list of string notations to specify blocks inside the network.:param string_list: a list of strings, each string is a notation of block:return: a list of BlockArgs namedtuples of block args"""assert isinstance(string_list, list)blocks_args = []for block_string in string_list:blocks_args.append(BlockDecoder._decode_block_string(block_string))return blocks_args@staticmethoddef encode(blocks_args):"""Encodes a list of BlockArgs to a list of strings.:param blocks_args: a list of BlockArgs namedtuples of block args:return: a list of strings, each string is a notation of block"""block_strings = []for block in blocks_args:block_strings.append(BlockDecoder._encode_block_string(block))return block_stringsdef efficientnet(width_coefficient=None, depth_coefficient=None,dropout_rate=0.2, drop_connect_rate=0.2):""" Creates a efficientnet model. """blocks_args = ['r1_k3_s11_e1_i32_o16_se0.25', 'r2_k3_s22_e6_i16_o24_se0.25','r2_k5_s22_e6_i24_o40_se0.25', 'r3_k3_s22_e6_i40_o80_se0.25','r3_k5_s11_e6_i80_o112_se0.25', 'r4_k5_s22_e6_i112_o192_se0.25','r1_k3_s11_e6_i192_o320_se0.25',]blocks_args = BlockDecoder.decode(blocks_args)global_params = GlobalParams(batch_norm_momentum=0.99,batch_norm_epsilon=1e-3,dropout_rate=dropout_rate,drop_connect_rate=drop_connect_rate,# data_format='channels_last', # removed, this is always true in PyTorchnum_classes=1000,width_coefficient=width_coefficient,depth_coefficient=depth_coefficient,depth_divisor=8,min_depth=None)return blocks_args, global_paramsdef get_model_params(model_name, override_params):""" Get the block args and global params for a given model """if model_name.startswith('efficientnet'):w, d, _, p = efficientnet_params(model_name)# note: all models have drop connect rate = 0.2blocks_args, global_params = efficientnet(width_coefficient=w, depth_coefficient=d, dropout_rate=p)else:raise NotImplementedError('model name is not pre-defined: %s' % model_name)if override_params:# ValueError will be raised here if override_params has fields not included in global_params.global_params = global_params._replace(**override_params)return blocks_args, global_paramsurl_map = {'efficientnet-b0': 'http://storage.googleapis.com/public-models/efficientnet-b0-08094119.pth','efficientnet-b1': 'http://storage.googleapis.com/public-models/efficientnet-b1-dbc7070a.pth','efficientnet-b2': 'http://storage.googleapis.com/public-models/efficientnet-b2-27687264.pth','efficientnet-b3': 'http://storage.googleapis.com/public-models/efficientnet-b3-c8376fa2.pth',}def load_pretrained_weights(model, model_name):""" Loads pretrained weights, and downloads if loading for the first time. """state_dict = model_zoo.load_url(url_map[model_name])model.load_state_dict(state_dict)print('Loaded pretrained weights for {}'.format(model_name))
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。