def infer_shape_conv_pool_shape(self, op): input_shape = self._output_shape_cache[op.input[0]] output_shape = np.zeros_like(input_shape) if op.type == MaceOp.Pooling: filter_shape = list( ConverterUtil.get_arg(op, MaceKeyword.mace_kernel_str).ints) if ConverterUtil.data_format(op) == DataFormat.NCHW: filter_shape = [input_shape[1], input_shape[1]] + filter_shape if ConverterUtil.get_arg(op, MaceKeyword.mace_global_pooling_str) \ is not None: filter_shape[2] = input_shape[2] filter_shape[3] = input_shape[3] else: # NHWC filter_shape = filter_shape + [input_shape[1], input_shape[1]] if ConverterUtil.get_arg(op, MaceKeyword.mace_global_pooling_str) \ is not None: filter_shape[0] = input_shape[1] filter_shape[1] = input_shape[2] else: filter_shape = self._output_shape_cache[op.input[1]] paddings = ConverterUtil.get_arg( op, MaceKeyword.mace_padding_values_str).ints # noqa strides = ConverterUtil.get_arg(op, MaceKeyword.mace_strides_str).ints dilations_arg = ConverterUtil.get_arg(op, MaceKeyword.mace_dilations_str) if dilations_arg is not None: dilations = dilations_arg.ints else: dilations = [1, 1] if op.type == MaceOp.Pooling: round_func = math.ceil else: round_func = math.floor output_shape[0] = input_shape[0] if ConverterUtil.data_format(op) == DataFormat.NCHW \ and ConverterUtil.filter_format(self._net) == DataFormat.OIHW: # noqa # filter format: OIHW if op.type == MaceOp.DepthwiseConv2d.name: output_shape[1] = filter_shape[0] * filter_shape[1] else: output_shape[1] = filter_shape[0] output_shape[2] = int( round_func((input_shape[2] + paddings[0] - filter_shape[2] - (filter_shape[2] - 1) * (dilations[0] - 1)) / float(strides[0]))) + 1 output_shape[3] = int( round_func((input_shape[3] + paddings[1] - filter_shape[3] - (filter_shape[3] - 1) * (dilations[1] - 1)) / float(strides[1]))) + 1 else: mace_check( False, "Mace can only infer shape for" " NCHW input and OIHW filter") self.add_output_shape(op, [output_shape])
def infer_shape_fully_connected(self, op): input_shape = self._output_shape_cache[op.input[0]] weight_shape = self._output_shape_cache[op.input[1]] if ConverterUtil.data_format(op) == DataFormat.NCHW: output_shape = [input_shape[0], weight_shape[0], 1, 1] else: mace_check( False, "format %s is not supported" % ConverterUtil.data_format(op)) self.add_output_shape(op, [output_shape])
def infer_shape_resize_bilinear(self, op): input_shape = self._output_shape_cache[op.input[0]] size = ConverterUtil.get_arg(op, MaceKeyword.mace_resize_size_str).ints if ConverterUtil.data_format(op) == DataFormat.NCHW: output_shape = [input_shape[0], input_shape[1], size[0], size[1]] elif ConverterUtil.data_format(op) == DataFormat.NHWC: output_shape = [input_shape[0], size[0], size[1], input_shape[3]] else: output_shape = [] mace_check( False, "format %s is not supported" % ConverterUtil.data_format(op)) self.add_output_shape(op, [output_shape])
def infer_shape_fully_connected(self, op): input_shape = self._output_shape_cache[op.input[0]] weight_shape = self._output_shape_cache[op.input[1]] data_format = ConverterUtil.data_format(op) mace_check(data_format == DataFormat.NCHW, "format {} is not supported".format(data_format)) output_shape = [input_shape[0], weight_shape[0], 1, 1] self.add_output_shape(op, [output_shape])
def common_check(self): for op in self._model.op: mace_check( len(op.input) >= 1, op.name + ': apu does not support op with 0 input') mace_check( len(op.output) == 1, op.name + ': apu only support single output op') mace_check( len(op.output) == len(op.output_shape), op.name + ': length of output and output_shape not' ' match') mace_check( len(op.output_shape[0].dims) <= 4, op.name + ': apu only support 1D~4D tensor') if op.output_type[0] == mace_pb2.DT_UINT8 \ or op.output_type[0] == mace_pb2.DT_INT16: mace_check( len(op.output) == len(op.quantize_info), op.name + ': length of output and quantize_info not' ' match') data_format = ConverterUtil.data_format(op) if data_format is not None and len(op.output_shape[0].dims) == 4: mace_check((data_format == DataFormat.NHWC) or (data_format == DataFormat.AUTO), op.name + ': apu only support 4D tensor with NHWC' ' or AUTO format but find ' + str(data_format)) act_mode_arg = ConverterUtil.get_arg( op, MaceKeyword.mace_activation_type_str) if act_mode_arg is not None: mace_check( act_mode_arg.s == b'PRELU' or act_mode_arg.s == b'RELU' or act_mode_arg.s == b'RELUX' or act_mode_arg.s == b'TANH' or act_mode_arg.s == b'SIGMOID', op.name + ': apu only support activation RELU,' ' RELUX, TANH and SIGMOID') for tensor in self._model.tensors: mace_check( len(tensor.dims) <= 4, tensor.name + ': apu only support 1D~4D tensor') for input_info in self._model.input_info: mace_check( len(input_info.dims) <= 4, input_info.name + ': apu only support 1D~4D tensor') mace_check( input_info.data_type == mace_pb2.DT_FLOAT or input_info.data_type == mace_pb2.DT_INT16 or input_info.data_type == mace_pb2.DT_UINT8, input_info.name + ': apu only support ' 'float/uint8/int16 input') if len(input_info.dims) == 4: mace_check( input_info.data_format == DataFormat.NHWC.value, input_info.name + ': apu only support 4D tensor' ' with NHWC format')
def infer_shape_nearest_neighbor(self, op): input_shape = self._output_shape_cache[op.input[0]] height_scale = \ ConverterUtil.get_arg(op, MaceKeyword.mace_height_scale_str).f width_scale = \ ConverterUtil.get_arg(op, MaceKeyword.mace_width_scale_str).f if ConverterUtil.data_format(op) == DataFormat.NCHW: output_shape = [ input_shape[0], input_shape[1], int(input_shape[2] * height_scale), int(input_shape[3] * width_scale) ] elif ConverterUtil.data_format(op) == DataFormat.NHWC: output_shape = [ input_shape[0], int(input_shape[2] * height_scale), int(input_shape[3] * width_scale), input_shape[3] ] else: output_shape = [] mace_check( False, "format %s is not supported" % ConverterUtil.data_format(op)) self.add_output_shape(op, [output_shape])
def infer_shape_deconv(self, op): input_shape = self._output_shape_cache[op.input[0]] output_shape = np.zeros_like(input_shape) filter_shape = self._output_shape_cache[op.input[1]] paddings = ConverterUtil.get_arg( op, MaceKeyword.mace_padding_values_str).ints # noqa strides = ConverterUtil.get_arg(op, MaceKeyword.mace_strides_str).ints dilations_arg = ConverterUtil.get_arg(op, MaceKeyword.mace_dilations_str) if dilations_arg is not None: dilations = dilations_arg.ints else: dilations = [1, 1] round_func = math.floor group_arg = ConverterUtil.get_arg(op, MaceKeyword.mace_group_str) output_shape[0] = input_shape[0] if ConverterUtil.data_format(op) == DataFormat.NCHW \ and ConverterUtil.filter_format(self._net) == DataFormat.OIHW: # noqa # filter format: IOHW output_shape[1] = filter_shape[1] if group_arg is not None and group_arg.i > 1: output_shape[1] = group_arg.i * filter_shape[1] output_shape[2] = int( round_func((input_shape[2] - 1) * strides[0] + (filter_shape[2] - 1) * (dilations[0] - 1) + filter_shape[2] - paddings[0])) output_shape[3] = int( round_func((input_shape[3] - 1) * strides[1] + (filter_shape[3] - 1) * (dilations[1] - 1) + filter_shape[3] - paddings[1])) else: mace_check( False, "Mace can only infer shape for" " NCHW input and OIHW filter") print("deconv layer %s (%s) input:%s filter:%s output:%s" % (op.name, op.type, input_shape, filter_shape, output_shape)) self.add_output_shape(op, [output_shape])
def infer_shape_conv2d_pool(self, op): input_shape = self._output_shape_cache[op.input[0]] output_shape = np.zeros_like(input_shape) if not op.type == MaceOp.Pooling: filter_shape = self._output_shape_cache[op.input[1]] paddings = ConverterUtil.get_arg( op, MaceKeyword.mace_padding_values_str).ints # noqa strides = ConverterUtil.get_arg(op, MaceKeyword.mace_strides_str).ints dilations_arg = ConverterUtil.get_arg(op, MaceKeyword.mace_dilations_str) if dilations_arg is not None: dilations = dilations_arg.ints else: dilations = [1, 1] # MACE pooling has no dilation if op.type == MaceOp.Pooling.name: kernels = ConverterUtil.get_arg(op, MaceKeyword.mace_kernel_str).ints if ConverterUtil.get_arg( op, MaceKeyword.mace_global_pooling_str) is not None: kernels[0] = input_shape[2] kernels[1] = input_shape[3] round_func = math.floor round_mode_arg = ConverterUtil.get_arg(op, MaceKeyword.mace_round_mode_str) if round_mode_arg is not None and \ round_mode_arg.i == RoundMode.CEIL.value: round_func = math.ceil # N_o = N_i output_shape[0] = input_shape[0] mace_check( ConverterUtil.data_format(op) == DataFormat.NCHW and ConverterUtil.filter_format(self._mace_net_def) == DataFormat.OIHW, "MACE can only infer shape for NCHW input and OIHW filter") # noqa # get C_{out} if op.type == MaceOp.DepthwiseConv2d.name: # 1CHW for depthwise, here C=C_{out} output_shape[1] = filter_shape[1] elif op.type == MaceOp.Conv2D.name: # filter format: OIHW output_shape[1] = filter_shape[0] else: output_shape[1] = input_shape[1] # H_{out} p, d, s = paddings[0], dilations[0], strides[0] k = kernels[0] if op.type == MaceOp.Pooling.name \ else filter_shape[2] # https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html output_shape[2] = int( round_func( float(input_shape[2] + p - d * (k - 1) - 1) / float(s) + 1)) # W_{out} p, d, s = paddings[1], dilations[1], strides[1] k = kernels[1] if op.type == MaceOp.Pooling.name \ else filter_shape[3] output_shape[3] = int( round_func( float(input_shape[3] + p - d * (k - 1) - 1) / float(s) + 1)) self.add_output_shape(op, [output_shape])