def __import_graph(cls, graph_path, session, out_nodes_names): """ :type graph_path: str :type session: tensorflow.Session :type out_nodes_names: list[str] :rtype: tf.GraphDef """ if not os.path.exists(graph_path): raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_GRAPH_FILE_DOES_NOT_EXIST')(graph_path)) graph_path = os.path.abspath(graph_path) if graph_path.endswith('.meta'): checkpoint = graph_path.split('.meta')[0] graph_def = cls.__import_from_meta_graph(graph_path, checkpoint, out_nodes_names) else: graph_def = cls.__import_from_frozen_graph(graph_path) if len(graph_def.node) == 0: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_NODES_NOT_FOUND_IN_GRAPH')) with session.graph.as_default(): tf.import_graph_def(graph_def, name="") return graph_def
def axes_to_spatial_first_order(self, node, graph): input_name = node.input_names[0] input_buf = graph.get_buffer(input_name) # force convergence if necessary # use the 'backwards' permute orders because they are self-inverses. if input_buf.axis_format == AxisTracker.AxisFormat.NSC: AxisTracker.inject_implicit_permute( graph, input_name, AxisTracker.AxisFormat.NCS, AxisTracker.AxisFormat.NSC_TO_NCS, [node.op.name]) elif input_buf.axis_format == AxisTracker.AxisFormat.BTF: AxisTracker.inject_implicit_permute( graph, input_name, AxisTracker.AxisFormat.TBF, AxisTracker.AxisFormat.TBF_TO_BTF, [node.op.name]) elif input_buf.axis_format == AxisTracker.AxisFormat.NONTRIVIAL: pass elif input_buf.axis_format == AxisTracker.AxisFormat.FEATURE: pass else: raise ValueError( code_to_message.get_error_message( "ERROR_RESHAPE_UNEXPECTED_INPUT_ORDER")( input_buf.axis_format)) output_buf = graph.get_output_buffers(node)[0] if output_buf.rank() > 4: log_assert( self.product(output_buf.shape[:-4]) == 1, code_to_message.get_error_message( "ERROR_RESHAPE_BATCH_UNSUPPORTED")) output_buf.shape = output_buf.shape[-4:] output_buf.axis_format = AxisTracker.AxisFormat.NONTRIVIAL
def __import_from_meta_graph(cls, meta_graph_path, graph_path, out_nodes_names): """ :type meta_graph_path: str :type graph_path: str :type out_nodes_names: list[str] :rtype: tensorflow.GraphDef """ session = tf.Session(graph=tf.Graph()) with session.graph.as_default(): try: saver = tf.train.import_meta_graph(meta_graph_path) except AssertionError as e: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_CANNOT_IMPORT_GRAPH_FROM_META')(e.message)) if saver is None: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_GRAPH_META_EMPTY')) saver.restore(session, graph_path) graph_def = session.graph.as_graph_def(add_shapes=True) return cls.__freeze_graph(session, graph_def, out_nodes_names)
def get_input_name(cls, converter_context, descriptor, input_descriptors): """ :type converter_context: converters.tensorflow.converter.ConverterContext :type input_descriptors: [LayerDescriptor] :type descriptor: LayerDescriptor :rtype: str """ if len(input_descriptors) > 1: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_LAYER_INPUT_COUNT_ERROR')( input_descriptors[0].layer_type, 1, len(input_descriptors))) input_names = cls.get_input_names(converter_context, descriptor, input_descriptors) if len(input_names) == 0: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_LAYER_NO_INPUT_FOUND')(descriptor.layer_type, descriptor.layer_name)) if len(input_names) > 1: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_LAYER_INPUT_COUNT_ERROR')( input_descriptors[0].layer_type, 1, len(input_descriptors))) return input_names[0]
def _convert_input_layers(self): """ :rtype: None """ for model_input in self._context.inputs: input_operation = self._context.graph.get_operation_by_name( model_input.name) shape = self._graph_helper.get_op_output_shape(input_operation) if None in shape: message = code_to_message.get_error_message( 'ERROR_TF_UNABLE_TO_RESOLVE_GRAPH_INPUT_DIMS') raise ConverterError(message(model_input.name)) if model_input.shape != shape: message = code_to_message.get_error_message( 'ERROR_TF_UNEXPECTED_INPUT_SHAPE') raise ConverterError(message(model_input.shape, shape)) self._logger.info( code_to_message.get_progress_message( 'INFO_TF_BUILDING_INPUT_LAYER')(input_operation.name, shape)) layer_name = str(input_operation.outputs[0].name) descriptor = InputLayerDescriptor(layer_name, [input_operation]) self._input_descriptors.append(descriptor) self._ops.remove(input_operation) self._context.model.add_data_layer(descriptor.output_names[0], shape, 'rgb', 'rgb', model_input.type)
def resolve_layer(self, graph_matcher, graph_helper): matches = graph_matcher.match_sequence(self.sequence) if len(matches) == 0: return [] descriptors = [] for match in matches: variance_op = match['variance'] epsilon_op = match['epsilon'] if variance_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_RESOLVE_VARIANCE')) variance = graph_helper.evaluate_tensor_output( variance_op.outputs[0]) if epsilon_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_RESOLVE_EPSILON')) epsilon = graph_helper.evaluate_tensor_output( epsilon_op.outputs[0]) scale_op = match['scale'] if scale_op.type not in ['Identity', 'Const', 'Fill']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_RESOLVE_SCALE')) scale = graph_helper.evaluate_tensor_output(scale_op.outputs[0]) mean_op = match['mean'] if mean_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_RESOLVE_MEAN')) mean = graph_helper.evaluate_tensor_output(mean_op.outputs[0]) beta_op = match['beta'] if beta_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_RESOLVE_BETA')) beta = graph_helper.evaluate_tensor_output(beta_op.outputs[0]) output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in self.sequence.output_nodes ] descriptors.append( BatchNormLayerResolver.Descriptor( str(match['d'].name), match.consumed_nodes, bn_mul_op=match['d'], mean=mean, variance=variance, epsilon=epsilon, scale=scale, beta=beta, output_names=output_op_nodes_names)) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for match in graph_matcher.match_sequence(self.sequence): input_op = match['input'] reshape_out_op = match['reshape_out'] reshape_in_op = match['reshape_in'] transpose_op = match['transpose'] input_shape = graph_helper.get_op_output_shape(input_op) reshape_in_shape = graph_helper.get_op_output_shape(reshape_in_op) transpose_shape = graph_helper.get_op_output_shape(transpose_op) reshape_out_shape = graph_helper.get_op_output_shape( reshape_out_op) if len(reshape_in_shape) < 2: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_CHANNEL_SHUFFLE_RESHAPE')) num_channels = input_shape[-1] num_groups = reshape_in_shape[-2] num_channels_prime = num_channels / num_groups if num_channels % num_groups != 0: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_CHANNEL_SHUFFLE')) is_channel_shuffle = True # first reshape must divide the channel dimension to [num_groups, num_channels_prime] is_channel_shuffle &= reshape_in_shape == input_shape[:-1] + [ num_groups, num_channels_prime ] # transpose must permute the last two dimensions only is_channel_shuffle &= transpose_shape == input_shape[:-1] + [ num_channels_prime, num_groups ] # output shape must be equal to the input shape is_channel_shuffle &= reshape_out_shape == input_shape if not is_channel_shuffle: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_CHANNEL_SHUFFLE_OUTPUT')) consumed_nodes = match.consumed_nodes descriptors.append( ChannelShuffleLayerResolver.Descriptor( str(reshape_out_op.name), consumed_nodes, num_groups, output_names=[str(reshape_out_op.outputs[0].name)])) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): matches = graph_matcher.match_sequence(self.sequence) if len(matches) == 0: return [] descriptors = [] for match in matches: conv_trans_op = match['root'] _, weights_tensor, input_tensor = GraphHelper.get_op_input_tensors( conv_trans_op, ('?', '?', '?')) if weights_tensor.op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_DECONV_CANT_FIND_WEIGHTS_NODE')) strides = conv_trans_op.get_attr('strides') padding = conv_trans_op.get_attr('padding') weights = graph_helper.evaluate_tensor_output(weights_tensor) consumed_nodes = match.consumed_nodes output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in self.sequence.output_nodes ] bias_op = None try: output_ops = graph_helper.get_op_outputs(conv_trans_op) bias_op = GraphHelper.filter_single_op_by_type( output_ops, 'BiasAdd') _, biases = GraphHelper.get_op_input_tensors( bias_op, ('?', '?')) if biases.op.type not in ['Const', 'Identity']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_DECONV_CANT_FIND_BIAS_NODE')) biases = graph_helper.evaluate_tensor_output(biases) consumed_nodes.append(bias_op) output_op_nodes_names = [str(bias_op.outputs[0].name)] except OperationNotFoundError: biases = np.zeros(np.shape(weights)[-2], dtype=np.float32) descriptors.append( DeConvolutionOptimizedLayerResolver.Descriptor( str(conv_trans_op.name), consumed_nodes, conv_trans_op, bias_op, weights, strides, padding, biases, input_tensor, output_names=output_op_nodes_names)) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for sequence in self.sequences: for match in graph_matcher.match_sequence(sequence): pad_op = None mode_values = modeltools.PADDING_CONSTANT if 'root' in match: pad_op = match['root'] if 'mirror_pad' in match: pad_op = match['mirror_pad'] mode = pad_op.get_attr(self.TF_ATTRIBUTE_MODE) if mode.decode() == "REFLECT": mode_values = modeltools.PADDING_REFLECT input_op = match['input'] paddings_op = match['paddings'] paddings_tensor = graph_helper.evaluate_tensor_output( paddings_op.outputs[0]) paddings_shape = graph_helper.get_op_output_shape(paddings_op) input_rank = len(graph_helper.get_op_output_shape(input_op)) if [input_rank, 2] != paddings_shape: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_PAD_INVALUD_PADDINGS')(str( [input_rank, 2]), str(paddings_shape))) if 'const_values' in match: const_values_op = match['const_values'] const_values = graph_helper.evaluate_tensor_output( const_values_op.outputs[0]) else: const_values = 0.0 if not np.isscalar(const_values): raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_PAD_CONSTANT_NOT_SCALAR')) consumed_nodes = match.consumed_nodes pad_descriptor = PadLayerResolver.Descriptor( str(pad_op.name), consumed_nodes, paddings_tensor, mode_values, const_values, output_names=[str(pad_op.outputs[0].name)]) descriptors.extend([pad_descriptor]) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for sequence in self.sequences: matches = graph_matcher.match_sequence(sequence) for match in matches: matmul_op = match['matmul_op'] weights_op = match['weights'] biases_op = None bias_add_op = None if weights_op.type not in [ 'Identity', 'Const', 'FakeQuantWithMinMaxVars' ]: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_MATMUL_RESOLVE_WEIGHTS')(matmul_op.name)) weights = graph_helper.evaluate_tensor_output( weights_op.outputs[0]) try: bias_add_op = match['bias_op'] biases_op = match['biases'] except KeyError: pass if biases_op is not None and bias_add_op is not None: if biases_op.type not in ['Identity', 'Const']: # do we still need this check ? raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_MATMUL_RESOLVE_BIAS')( bias_add_op.name)) biases = graph_helper.evaluate_tensor_output( biases_op.outputs[0]) else: biases = np.zeros(weights.shape[-1], dtype=np.float32) consumed_nodes = match.consumed_nodes output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in sequence.output_nodes ] descriptors.append( FullyConnectedLayerResolver.Descriptor( str(matmul_op.name), consumed_nodes, matmul_op, bias_add_op, weights, biases, output_names=output_op_nodes_names)) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): potential_descriptors = [] for sequence in self.sequences: matches = graph_matcher.match_sequence(sequence) for match in matches: extract_glimpse = match['extract_glimpse'] size = match['size'] size_value = graph_helper.evaluate_tensor_output( size.outputs[0]) if size_value.size != 2: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_RESOLVE_EXTRACT_GLIMPSE_SIZE')) output_op_nodes_names = [str(extract_glimpse.outputs[0].name)] consumed_nodes = match.consumed_nodes centered = bool(extract_glimpse.get_attr('centered')) normalized = bool(extract_glimpse.get_attr('normalized')) uniform_noise = bool(extract_glimpse.get_attr('uniform_noise')) potential_descriptors.append( ExtractGlimpseLayerResolver.Descriptor( str(extract_glimpse.name), consumed_nodes, size_value[1], size_value[0], centered, normalized, uniform_noise, output_names=output_op_nodes_names)) return potential_descriptors
def resolve_layer(self, graph_matcher, graph_helper): potential_descriptors = [] matches = graph_matcher.match_sequence(self.sequence) for match in matches: image_proj_transform = match['root'] output_op_nodes_names = [str(image_proj_transform.outputs[0].name)] consumed_nodes = match.consumed_nodes interpolation = str( image_proj_transform.get_attr('interpolation').decode('utf-8')) if interpolation == "BILINEAR": interpolation_mode = 0 elif interpolation == "NEAREST": interpolation_mode = 1 else: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_RESOLVE_IMAGE_TRANSFORM_INTERPOLATION')) potential_descriptors.append( ImageProjectiveTransformLayerResolver.Descriptor( str(image_proj_transform.name), consumed_nodes, interpolation_mode, output_names=output_op_nodes_names)) return potential_descriptors
def build_layer(self, converter_context, descriptor, input_descriptors, output_descriptors): """ :type input_descriptors: [converters.tensorflow.common.LayerDescriptor] :type output_descriptors: [converters.tensorflow.common.LayerDescriptor] :type converter_context: converters.tensorflow.converter.ConverterContext :type descriptor: ConcatLayerResolver.Descriptor :rtype: int """ output_name = descriptor.output_names[0] anchor_input = [ d for d in input_descriptors if isinstance(d, ConstantLayerResolver.Descriptor) ] boxes_input = [ d for d in input_descriptors if not isinstance(d, ConstantLayerResolver.Descriptor) ] if len(anchor_input) != 1: raise ConverterError( get_error_message('ERROR_TF_SSD_ANCHOR_INPUT_MISSING')) anchors_layer_name = anchor_input[0].output_names[0] boxes_layer_name = boxes_input[0].output_names[0] return converter_context.model.add_box_decoder_layer( output_name, [boxes_layer_name, anchors_layer_name], [output_name], scale_y=descriptor.scale_y, scale_x=descriptor.scale_y, scale_h=descriptor.scale_h, scale_w=descriptor.scale_w)
def _get_input_layer_output_op_for(self, operation): """ :type operation: tensorflow.Operation :rtype: tensorflow.Operation """ input_tensors = self._get_input_layers_output_tensors_for(operation) ops = uniques([t.op for t in input_tensors]) if len(ops) == 0: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_INPUT_OPERATION_NOT_FOUND')(operation.name)) if len(ops) != 1: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_EXPECTED_SINGLE_OUTPUT_FROM_PREVIOUS_LAYER')) return ops[0]
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for sequence in self.sequences: for match in graph_matcher.match_sequence(sequence): transpose_op = match['root'] input_op = match['input'] order_op = match['order'] order_tensor = graph_helper.evaluate_tensor_output( order_op.outputs[0]) input_shape = graph_helper.get_op_output_shape(input_op) order_shape = graph_helper.get_op_output_shape(order_op) input_rank = len(input_shape) order_rank = len(order_shape) try: assert order_rank == 1 for d in range(input_rank): assert d in order_tensor except AssertionError: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_PERMUTE_INVALID_ORDER_TENSOR')( str(order_tensor))) consumed_nodes = match.consumed_nodes permute_descriptor = PermuteLayerResolver.Descriptor( str(transpose_op.name), consumed_nodes, order_tensor, output_names=[str(transpose_op.outputs[0].name)]) descriptors.extend([permute_descriptor]) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): matches = graph_matcher.match_sequence(self.sequence) potential_descriptors = [] for match in matches: bn_op = match['root'] parameter_tensors = self._get_parameter_tensors( graph_helper, bn_op) if len(parameter_tensors) < 4: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_BATCHNORM_GLOBALNORMALIZATION_INPUT')) epsilon = bn_op.get_attr('epsilon') scale = parameter_tensors[0] beta = parameter_tensors[1] mean = parameter_tensors[2] variance = parameter_tensors[3] consumed_nodes = match.consumed_nodes potential_descriptors.append( FusedBatchNormNormLayerResolver.Descriptor(str(bn_op.name), consumed_nodes, bn_mul_op=bn_op, mean=mean, variance=variance, epsilon=epsilon, scale=scale, beta=beta)) return potential_descriptors
def _create_layer_builder(cls, descriptor): builder_class = layers.layer_builders.get(type(descriptor), None) if builder_class is None: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_NO_INPUT_TO_CREATE_LAYER')(type(descriptor))) return builder_class()
def resolve_layer(self, graph_matcher, graph_helper): potential_descriptors = [] for sequence in self.sequences: matches = graph_matcher.match_sequence(sequence) for match in matches: coefficients = match['alphas'] add_op = match['f'] if coefficients.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_RESOLVE_PRELU_COEFF')) output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in sequence.output_nodes ] consumed_nodes = match.consumed_nodes potential_descriptors.append( PReLuLayerResolver.Descriptor( str(add_op.name), consumed_nodes, graph_helper.evaluate_tensor_output( coefficients.outputs[0]), output_names=output_op_nodes_names)) return potential_descriptors
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for sequence in self.sequences: for match in graph_matcher.match_sequence(sequence): pow_op = match['pow'] const_values_op = match['const'] const_values = graph_helper.evaluate_tensor_output( const_values_op.outputs[0]) # only scalar power op is supported if not np.isscalar(const_values): raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_POW_CONSTANT_NOT_SCALAR')) consumed_nodes = match.consumed_nodes pow_descriptor = PowLayerResolver.Descriptor( str(pow_op.name), consumed_nodes, 1, 0, const_values, output_names=[str(pow_op.outputs[0].name)]) descriptors.extend([pow_descriptor]) return descriptors
def _convert_layers(self): """ :rtype: None """ graph_ops = list(self._ops) descriptors = self._resolve_descriptors_from_nodes(graph_ops) descriptors = self._resolve_hierarchical_resolution_conflicts( descriptors) original_descriptors = descriptors self._topology_resolver.resolve_topology(self._input_descriptors + descriptors) descriptors = self._topology_resolver.sort_descriptors_in_execution_order( descriptors, self._input_descriptors) descriptors = self._filter_disconnected_descriptors(descriptors) if self._strict_node_resolution: self._assert_all_ops_supported(original_descriptors, graph_ops) self._assert_all_descriptors_consumed(descriptors, original_descriptors) if self._all_ops_consumed is False: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_OPERATION_NOT_MAPPED_TO_LAYER')) self._transform_descriptors(descriptors) self._topology_resolver.resolve_topology(self._input_descriptors + descriptors) descriptors = [d for d in descriptors if not d.is_ignored] self._create_layers(descriptors)
def axes_to_spatial_first_order(self, node, graph): AxisTracker.log_axes_to_spatial_first_order(node, graph) input_buf = graph.get_input_buffers(node)[0] if input_buf.rank() == 4: AxisTracker.enforce_input_format(graph, input_buf.name, AxisTracker.AxisFormat.NSC, AxisTracker.AxisFormat.NCS_TO_NSC) # weights expect NCHW order, need to permute input_buf = graph.get_input_buffers(node)[0] batch, height, width, depth = input_buf.shape weights = node.op.weights_list[0] # TODO: this optimization was added based on onnx framework. Verify(Modify) if # change is needed for other frameworks # ONNX defines FC as W^Tx + b, # so the weights have shape (batch, input_size, output_size) input_size = weights.shape[0] output_size = weights.shape[1] log_assert( input_size == depth * height * width, code_to_message.get_error_message("ERROR_FC_WRONG_INPUT_SIZE")( node.op.name, input_size, (depth, height, width))) weights.shape = (depth, height, width, output_size) weights = numpy.transpose(weights, (3, 1, 2, 0)) weights = numpy.ascontiguousarray(weights, dtype=numpy.float32) weights.shape = (output_size, input_size) node.op.weights_list[0] = weights elif input_buf.rank() == 2: # again, need to transpose weights for spatial_first order weights = node.op.weights_list[0] weights = numpy.ascontiguousarray(numpy.transpose(weights, (1, 0))) node.op.weights_list[0] = weights output_buf = graph.get_output_buffers(node)[0] output_buf.axis_format = AxisTracker.AxisFormat.FEATURE
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for match in graph_matcher.match_sequence(self.sequence): argmax_op = match['root'] input_op = match['input'] axis_op = match['axis'] input_shape = graph_helper.get_op_output_shape(input_op) input_rank = len(input_shape) axis = int(graph_helper.evaluate_tensor_output(axis_op.outputs[0])) if axis < 0: axis += input_rank if axis < 0 or axis >= input_rank: raise ConverterError( code_to_message.get_error_message( 'ERROR_TF_ARGMAX_INVALID_AXIS')(axis, input_rank)) consumed_nodes = match.consumed_nodes argmax_descriptor = ArgMaxLayerResolver.Descriptor( str(argmax_op.name), consumed_nodes, axis, output_names=[str(argmax_op.outputs[0].name)]) descriptors.extend([argmax_descriptor]) return descriptors
def fetch(self, *keys, **kwargs): ret = [] # Prunable indicates whether the weights have been consumed in such a way as to # allow pruning of the node (eg Const ops that contain weights are consumed by # Conv/FC/etc and thus can be pruned from the network. Const ops that are inputs # to a node cannot consumed = kwargs.get('prunable', True) for key in keys: key = str(key) log_debug( code_to_message.get_debugging_message( "DEBUG_RETRIEVE_WEIGHTS, key")) if key not in self.weight_map: raise KeyError( code_to_message.get_error_message( "ERROR_WEIGHTS_MISSING_KEY")(key)) self.weight_map[key].consumed = consumed # Explicitly copy the data so if later ops modify it, the original data remains intact ret.append( numpy.require(self.weight_map[key].weights.copy(), dtype=numpy.float32)) if len(ret) == 1: return ret[0] else: return ret
def apply_method_to_all_ops(self, method_name, graph, *args, **kwargs): """ Runs the requested method on all ops in the given graph. i.e loops through the nodes in graph, gets the corresponding translation class for node and runs the given method with node and graph as args :param method_name: name of the method to call :param graph: the IR Opgraph to traverse :param args: required positional arguments that will be passed to method :param kwargs: keywords arguments to be used to pass fail_if_no_method to this function raises KeyError if method no found for an op_type translation unless fail_if_no_method is set to False in the kwargs argument """ for node in graph.list_nodes(): if node in graph.list_nodes( ): # this extra check is needed since an optimization applied to op below # can remove next node(s), so doing a dynamic check is needed translation = self.__get_translation(node.op.type) if translation.has_indexed_method(method_name): self.apply_method_to_op(node.op.type, method_name, node, graph, *args) else: fail_if_no_method = kwargs.get('fail_if_no_method', True) if fail_if_no_method: raise KeyError( code_to_message.get_error_message( "ERROR_METHOD_NOT_FOUND_FOR_OP_TYPE")( method_name, node.op.type))
def get_split_positions(cls, input_shape, split_count, split_sizes, split_axis): split_points = [] if len(split_sizes) > 0: if sum(split_sizes) != input_shape[split_axis]: raise ConverterError(code_to_message.get_error_message('ERROR_TF_SLICE_SIZE_MISMATCH')) split_index = split_sizes[0] for size in split_sizes[1:]: split_points.append(int(split_index)) split_index += size else: split_axis_dim = input_shape[split_axis] split_size = split_axis_dim // split_count if split_axis_dim % split_count: raise ConverterError(code_to_message.get_error_message('ERROR_TF_SLICE_UNEVEN_SPLIT')) for index in range(1, split_count): split_points.append(int(index * split_size)) return split_points
def build_layer(self, converter_context, descriptor, input_descriptors, output_descriptors): """ :type input_descriptors: [converters.tensorflow.common.LayerDescriptor] :type output_descriptors: [converters.tensorflow.common.LayerDescriptor] :type converter_context: converters.tensorflow.converter.ConverterContext :type descriptor: StridedSliceLayerResolver.Descriptor :rtype: int """ input_name = self.get_input_name(converter_context, descriptor, input_descriptors) output_name = descriptor.output_names[0] if descriptor.ellipsis_mask != 0 or descriptor.new_axis_mask != 0: raise ConverterError(code_to_message.get_error_message('ERROR_TF_STRIDED_SLICE_UNSUPPORTED_MASKS')) input_rank = len(descriptor.input_shape) strides_rank = descriptor.strides.shape[0] # Extend to match input rank begin = np.append(descriptor.begin, np.zeros(input_rank - strides_rank, dtype=np.int32)).tolist() strides = np.append(descriptor.strides, np.ones(input_rank - strides_rank, dtype=np.int32)).tolist() end = np.append(descriptor.end, descriptor.input_shape[strides_rank:]).astype(np.int32).tolist() # Apply the binary masks for i in range(len(strides)): begin_mask_bit = self.get_bit(descriptor.begin_mask, i) end_mask_bit = self.get_bit(descriptor.end_mask, i) shrink_mask_bit = self.get_bit(descriptor.shrink_axis_mask, i) # Convert negative indices if begin[i] < 0: begin[i] += descriptor.input_shape[i] if end[i] < 0: end[i] += descriptor.input_shape[i] # Apply mask bits if strides[i] > 0: if begin_mask_bit: begin[i] = 0 if end_mask_bit: end[i] = descriptor.input_shape[i] else: if begin_mask_bit: begin[i] = descriptor.input_shape[i] - 1 if end_mask_bit: end[i] = -1 # Apply shrink_axis_mask if shrink_mask_bit: strides[i] = 1 end[i] = begin[i] + strides[i] return converter_context.model.add_strided_slice_layer(name=descriptor.layer_name, input_name=input_name, output_name=output_name, begin=begin, end=end, strides=strides, shrink_axis_mask=descriptor.shrink_axis_mask)
def build_layer(self, converter_context, descriptor, input_descriptors, output_descriptors): """ :type input_descriptors: [converters.tensorflow.common.LayerDescriptor] :type output_descriptors: [converters.tensorflow.common.LayerDescriptor] :type converter_context: converters.tensorflow.converter.ConverterContext :type descriptor: ConcatLayerResolver.Descriptor :rtype: int """ if len(input_descriptors) != 2: raise ConverterError( get_error_message('ERROR_TF_SSD_NMS_REQUIRES_2_INPUTS')) input_names = [] input_shapes = [] for i in input_descriptors: tensors = converter_context.get_output_tensors_between( i, descriptor) if len(tensors) != 1: raise ConverterError( get_error_message( 'ERROR_TF_SSD_NMS_REQUIRES_SINGLE_INPUT_TENSOR')) input_shapes.append( converter_context.graph_helper.get_op_output_shape( tensors[0].op)) for index, shape in enumerate(input_shapes): output_names = input_descriptors[index].output_names if len(shape) == 3 and shape[-1] == 4: input_names = output_names + input_names else: input_names.extend(output_names) classes_shape = converter_context.graph_helper.get_op_output_shape( descriptor.classes_output_op) return converter_context.model.add_multi_class_nms_layer( name=descriptor.layer_name, input_names=input_names, output_names=descriptor.output_names, scoreThreshold=descriptor.score_threshold, iouThreshold=descriptor.iou_threshold, maxDetectionPerClass=classes_shape[-1], maxTotalDetections=classes_shape[-1])
def get_biases(self, graph_helper, conv_op, bias_op): _, biases_tensor = GraphHelper.get_op_input_tensors( bias_op, ('?', '?')) if biases_tensor.op.type not in ['Identity', 'Const'] and \ not graph_helper.check_tensor_const_origin(biases_tensor): raise ConverterError( code_to_message.get_error_message('ERROR_TF_CONV_RESOLVE_BIAS') (conv_op.name)) biases = graph_helper.evaluate_tensor_output(biases_tensor) return biases
def axes_to_spatial_first_order(self, node, graph): input_name = node.input_names[0] input_buf = graph.get_input_buffers(node)[0] output_buf = graph.get_output_buffers(node)[0] # check for trivial cases first, which will end up # in removal. Otherwise, just set output order to nontrivial if input_buf.axis_format == AxisTracker.AxisFormat.NSC: # special case: transforming to NSC, will become noop if node.op.order == [0, 2, 3, 1]: node.op.order = [0, 1, 2, 3] output_buf.axis_format = AxisTracker.AxisFormat.NSC return else: # going to nontrivial AxisTracker.inject_implicit_permute( graph, input_name, AxisTracker.AxisFormat.NCS, AxisTracker.AxisFormat.NSC_TO_NCS, [node.op.name]) output_buf.axis_format = AxisTracker.AxisFormat.NONTRIVIAL elif input_buf.axis_format == AxisTracker.AxisFormat.BTF: if node.op.order == [0, 2, 3, 1]: node.op.order = [0, 1, 2, 3] output_buf.axis_format = AxisTracker.AxisFormat.BTF else: AxisTracker.inject_implicit_permute( graph, input_name, AxisTracker.AxisFormat.TBF, AxisTracker.AxisFormat.TBF_TO_BTF, [node.op.name]) output_buf.axis_format = AxisTracker.AxisFormat.NONTRIVIAL elif input_buf.axis_format == AxisTracker.AxisFormat.NONTRIVIAL: if len(node.op.order) == 4: output_buf.axis_format = AxisTracker.AxisFormat.NONTRIVIAL elif len(node.op.order) > 4: raise ValueError( code_to_message.get_error_message( "ERROR_PERMUTE_TOO_MANY_DIMENSIONS")(node.op.order)) else: # nothing to be done output_buf.axis_format = AxisTracker.AxisFormat.NONTRIVIAL else: raise ValueError( code_to_message.get_error_message( "ERROR_PERMUTE_UNEXPECTED_INPUT_ORDER")( input_buf.axis_format))
def enforce_input_format(cls, graph, input_name, target_format, permute_order): input_buf = graph.get_buffer(input_name) if input_buf.axis_format == cls.AxisFormat.NONTRIVIAL: cls.inject_implicit_permute(graph, input_name, target_format, permute_order) elif input_buf.axis_format != target_format: raise ValueError( code_to_message.get_error_message( 'ERROR_INPUT_DATA_ORDER_UNEXPECTED')( input_name, target_format, input_buf.axis_format))