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_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_message( 'ERROR_TF_NODES_NOT_FOUND_IN_GRAPH')) with session.graph.as_default(): tf.import_graph_def(graph_def, name="") return graph_def
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_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_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): 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_message('ERROR_TF_RESOLVE_EXTRACT_GLIMPSE_SIZE')) offsets = match['offsets'] offsets_value = graph_helper.evaluate_tensor_output(offsets.outputs[0]) if len(offsets_value.shape) != 2 or offsets_value.shape[1] != 2: raise ConverterError( code_to_message.get_message('ERROR_TF_RESOLVE_EXTRACT_GLIMPSE_OFFSETS')) 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], offsets_value, centered,normalized, uniform_noise, 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): pad_op = match['root'] 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_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_message('ERROR_TF_PAD_CONSTANT_NOT_SCALAR')) consumed_nodes = match.consumed_nodes pad_descriptor = PadLayerResolver.Descriptor( str(pad_op.name), consumed_nodes, paddings_tensor, snpe.modeltools.PADDING_CONSTANT, const_values, output_names=[str(pad_op.outputs[0].name)]) descriptors.extend([pad_descriptor]) 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: variance_op = match['variance'] epsilon_op = match['epsilon'] if variance_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_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_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_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_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_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): 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_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_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 _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_message( 'ERROR_TF_NO_INPUT_TO_CREATE_LAYER')(type(descriptor))) return builder_class()
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_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_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 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 """ input_names = self.get_input_names(converter_context, descriptor, input_descriptors) if len(input_names) < 2: raise ConverterError(code_to_message.get_message('ERROR_TF_ADD_N_NUM_OF_INPUTS')(descriptor.layer_name)) output_name = descriptor.output_names[0] current_input_names = [input_names[0], input_names[1]] current_output_name = descriptor.layer_name + '_unroll_1' converter_context.model.add_elementwise_sum_layer(descriptor.layer_name + '_unroll_1', [1.0 for _ in current_input_names], current_input_names, current_output_name) for input_index in range(2, len(input_names) - 1): current_input_names = [current_output_name, input_names[input_index]] current_output_name = descriptor.layer_name + '_unroll_' + str(input_index) converter_context.model.add_elementwise_sum_layer(descriptor.layer_name + '_unroll_' + str(input_index), [1.0 for _ in current_input_names], current_input_names, current_output_name) current_input_names = [current_output_name, input_names[-1]] return converter_context.model.add_elementwise_sum_layer(descriptor.layer_name, [1.0 for _ in current_input_names], current_input_names, output_name)
def _get_input_layers_output_tensors_for(self, operation): """ :type operation: tensorflow.Operation :rtype: list[tensorflow.Tensor] """ descriptor = self._topology_resolver.descriptor_ops_map.get( operation, None) if descriptor is None: raise ConverterError( 'Unable to find input layer for operation not in layer.') output_tensors = [] input_descriptors = self._topology_resolver.get_input_layers_for( descriptor) input_descriptors_outputs = [ o for d in input_descriptors for o in d.child_ops if d.is_output_op(o) ] visited = set() op_queue = [operation] while len(op_queue) > 0: next_op = op_queue.pop(0) visited.add(next_op) for input_tensor in next_op.inputs: input_op = input_tensor.op if input_op in input_descriptors_outputs: output_tensors.append(input_tensor) elif input_op not in visited: op_queue.insert(0, input_op) return uniques(output_tensors)
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_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 _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_message( 'ERROR_TF_INPUT_OPERATION_NOT_FOUND')(operation.name)) if len(ops) != 1: raise ConverterError( code_to_message.get_message( 'ERROR_TF_EXPECTED_SINGLE_OUTPUT_FROM_PREVIOUS_LAYER')) return ops[0]
def __init__(self, nodes): super(GraphSequence, self).__init__() self._output_nodes = [] for node in nodes: if node.identifier in self: raise ConverterError('Node with id already defined {}'.format( node.identifier)) self[node.identifier] = node
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']: raise ConverterError( code_to_message.get_message('ERROR_TF_CONV_RESOLVE_BIAS')( conv_op.name)) biases = graph_helper.evaluate_tensor_output(biases_tensor) return biases
def get_weights(self, graph_helper, conv_op): _, weights_tensor = GraphHelper.get_op_input_tensors( conv_op, ('?', '?')) if weights_tensor.op.type not in ['Identity', 'Const', 'Split']: raise ConverterError( code_to_message.get_message('ERROR_TF_CONV_RESOLVE_WEIGHTS')( conv_op.name)) weights = graph_helper.evaluate_tensor_output(weights_tensor) return weights
def resolve_layer(self, graph_matcher, graph_helper): descriptors = [] for match in graph_matcher.match_sequence(self.sequence): strided_slice_op = match['root'] input_op = match['input'] if input_op.type == "Const": continue begin_op = match['begin'] end_op = match['end'] strides_op = match['strides'] begin_tensor = graph_helper.evaluate_tensor_output( begin_op.outputs[0]) end_tensor = graph_helper.evaluate_tensor_output(end_op.outputs[0]) strides_tensor = graph_helper.evaluate_tensor_output( strides_op.outputs[0]) input_tensor = graph_helper.evaluate_tensor_output( input_op.outputs[0]) begin_shape = graph_helper.get_op_output_shape(begin_op) end_shape = graph_helper.get_op_output_shape(end_op) strides_shape = graph_helper.get_op_output_shape(strides_op) input_shape = graph_helper.get_op_output_shape(input_op) if begin_shape != end_shape or begin_shape != strides_shape: raise ConverterError( code_to_message.get_message( 'ERROR_TF_STRIDED_SLICE_SHAPE_MISMATCH')) begin_mask = strided_slice_op.get_attr("begin_mask") end_mask = strided_slice_op.get_attr("end_mask") ellipsis_mask = strided_slice_op.get_attr("ellipsis_mask") new_axis_mask = strided_slice_op.get_attr("new_axis_mask") shrink_axis_mask = strided_slice_op.get_attr("shrink_axis_mask") consumed_nodes = match.consumed_nodes pad_descriptor = StridedSliceLayerResolver.Descriptor( str(strided_slice_op.name), consumed_nodes, input_shape, begin_tensor, end_tensor, strides_tensor, begin_mask, end_mask, ellipsis_mask, new_axis_mask, shrink_axis_mask, output_names=[str(strided_slice_op.outputs[0].name)]) descriptors.extend([pad_descriptor]) return descriptors
def resolve_layer(self, graph_matcher, graph_helper): matches = graph_matcher.match_sequence(self.graph_sequence) if len(matches) == 0: return [] descriptor = [] for match in matches: conv_op = match['conv_op'] strides = conv_op.get_attr(self.TF_ATTRIBUTE_STRIDES) padding = conv_op.get_attr(self.TF_ATTRIBUTE_PADDING) weights = self.get_weights(graph_helper, conv_op) weights = np.transpose(weights, [0, 1, 3, 2]) consumed_nodes = match.consumed_nodes output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in self.graph_sequence.output_nodes ] try: batch_to_space_op = match['batch_to_space'] conv_output_ops = graph_helper.get_op_outputs( batch_to_space_op) bias_op = GraphHelper.filter_single_op_by_type( conv_output_ops, 'BiasAdd') biases = self.get_biases(graph_helper, conv_op, bias_op) consumed_nodes.append(bias_op) output_op_nodes_names = [str(bias_op.outputs[0].name)] except OperationNotFoundError: bias_op = None biases = np.zeros(np.shape(weights)[-1], dtype=np.float32) dilation_sizes = match['dilation_sizes'] dilation_sizes = graph_helper.evaluate_tensor_output( dilation_sizes.outputs[0]) if np.shape(dilation_sizes) != (2, ): raise ConverterError( code_to_message.get_message( 'ERROR_TF_CONV_RESOLVE_DILATION')(conv_op.name)) d = ConvolutionLayerResolver.Descriptor( str(conv_op.name), consumed_nodes, conv_op, bias_op, strides, padding, weights, biases, output_names=output_op_nodes_names) space_to_batch_op = match['space_to_batch'] d.groups = graph_helper.get_op_output_shape(space_to_batch_op)[-1] d.dilationY = int(dilation_sizes[0]) d.dilationX = int(dilation_sizes[1]) d.input_ops = [space_to_batch_op] descriptor.append(d) return descriptor
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, e: raise ConverterError( code_to_message.get_message( 'ERROR_TF_CANNOT_IMPORT_GRAPH_FROM_META')(e.message)) if saver is None: raise ConverterError( code_to_message.get_message('ERROR_TF_GRAPH_META_EMPTY')) saver.restore(session, graph_path)
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: matmul_op = match['matmul_op'] weights_op = match['weights'] if weights_op.type not in ['Identity', 'Const']: raise ConverterError( code_to_message.get_message( 'ERROR_TF_MATMUL_RESOLVE_WEIGHTS')(matmul_op.name)) weights = graph_helper.evaluate_tensor_output( weights_op.outputs[0]) bias_add_op = match['bias_op'] biases_op = match['biases'] if biases_op.type not in ['Identity', 'Const']: # do we still need this check ? raise ConverterError( code_to_message.get_message('ERROR_TF_MATMUL_RESOLVE_BIAS') (bias_add_op.name)) biases = graph_helper.evaluate_tensor_output(biases_op.outputs[0]) consumed_nodes = match.consumed_nodes output_op_nodes_names = [ str(match[node.identifier].outputs[0].name) for node in self.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 _assert_all_ops_consumed(self, descriptors, graph_ops): graph_ops = self._filter_unconsumed_ops(descriptors, graph_ops) def is_parameter_op(o): return o.type in ['Const', 'Identity', 'Variable'] remaining_ops = [op for op in graph_ops if not is_parameter_op(op)] for op in remaining_ops: self._logger.warning( code_to_message.get_warning_message( 'WARNING_TF_SCOPE_OP_NOT_CONSUMED')(op.name, op.type)) if len(remaining_ops) > 0: raise ConverterError( code_to_message.get_message( 'ERROR_TF_OPERATION_NOT_MAPPED_TO_LAYER'))
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: DeConvolutionLayerResolver.Descriptor :rtype: int """ input_dims = converter_context.graph_helper.get_op_output_shape( descriptor.input_tensor.op) if descriptor.bias_op: output_dims = converter_context.graph_helper.get_op_output_shape( descriptor.bias_op) else: output_dims = converter_context.graph_helper.get_op_output_shape( descriptor.deconv_op) pad_y, pad_x, padding_strategy = ConvolutionLayerBuilder.calculate_padding_size( input_size=output_dims[-3:-1], output_size=input_dims[-3:-1], strides=descriptor.strides[1:3], padding=descriptor.padding, filter_dims=descriptor.weights.shape, dilation=[1, 1]) if pad_y != pad_x: raise ConverterError( code_to_message.get_message( 'ERROR_TF_DECONV_NO_SUPPORT_RECT_PADDING')) weights = np.transpose(descriptor.weights, (0, 1, 3, 2)).copy() input_names = self.get_input_name(converter_context, descriptor, input_descriptors) return converter_context.model.add_deconvolution_layer( name=descriptor.layer_name, weights=weights, bias=descriptor.biases, stride=descriptor.strides[1], padding_size_strategy=padding_strategy, padding=pad_y, input_name=input_names, output_name=descriptor.output_names[0], output_width=output_dims[-2], output_height=output_dims[-3], groups=1)
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( code_to_message.get_message('ERROR_TF_CONCAT_INPUT')) input_names = self.get_input_names(converter_context, descriptor, input_descriptors) return converter_context.model.add_concatenation_layer( descriptor.layer_name, input_names, descriptor.output_names[0], descriptor.axis)
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_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 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_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 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: LstmLayerResolver.UnrolledTimeStepDescriptor :rtype: int """ if isinstance(descriptor, LstmLayerResolver.StateDescriptor): return input_descriptors = [ d for d in input_descriptors if not isinstance(d, LstmLayerResolver.StateDescriptor) ] if len(input_descriptors) not in [1, 3]: raise ConverterError('LSTM layer requires 1 or 3 inputs') input_shape = converter_context.graph_helper.get_op_output_shape( descriptor.cell_input_concat_op.inputs[0].op) state_shape = converter_context.graph_helper.get_op_output_shape( descriptor.cell_input_concat_op.inputs[1].op) gates_weights, input_weights = self._resolve_weights( descriptor, converter_context.graph_helper, state_shape) gates_biases = self._resolve_biases(descriptor, converter_context.graph_helper) def is_cell_input_descriptor(d): output_shape = [] output_ops = [op for op in d.child_ops if d.is_output_op(op)] if len(output_ops) > 0: output_shape = converter_context.graph_helper.get_op_output_shape( output_ops[0]) return len(output_shape ) == 2 and output_shape[1] == descriptor.time_steps() cell_input_descriptors = filter(is_cell_input_descriptor, input_descriptors) cell_state_descriptors = [ d for d in input_descriptors if d not in cell_input_descriptors ] user_initial_state = len(cell_state_descriptors) == 2 is_stacked_above_cell = self.is_stacked_cell(input_descriptors) if not is_stacked_above_cell: if len(cell_input_descriptors) != 1: raise ConverterError( 'Unable to resolve LSTM input layer name.') cell_input_name = cell_input_descriptors[0].output_names[0] input_layer_name = self._add_reshape_to_restore_time_dimension( converter_context, descriptor, cell_input_name, input_shape) else: input_layer_name = input_descriptors[0].output_names[0] is_stacked_below_cell = self.is_stacked_cell(output_descriptors) descriptor.set_is_stacked_cell(is_stacked_below_cell) output_names = [descriptor.stacked_cell_output_name] if user_initial_state or (not is_stacked_below_cell and len(output_descriptors) > 0): output_names.append('{}_state'.format(descriptor.output_names[0])) output_names.append(descriptor.output_names[0]) h_0_input_name = cell_state_descriptors[0].output_names[ 0] if user_initial_state else '' c_0_input_name = cell_state_descriptors[1].output_names[ 0] if user_initial_state else '' return converter_context.model.add_lstm_layer( name=descriptor.output_names[0], w_xc=input_weights, b_c=gates_biases, w_hc=gates_weights, w_xc_static=None, backward=False, reset_state_at_time_step_0=not user_initial_state, input_name=input_layer_name, sequence_continuation_input_name='', x_static_input_name='', c_0_input_name=c_0_input_name, h_0_input_name=h_0_input_name, output_names=output_names)
def resolve_layer(self, graph_matcher, graph_helper): matches = graph_matcher.match_sequence(self.graph_sequence) if len(matches) == 0: return [] descriptors = [] for match in matches: conv_op = match['conv_op'] strides = conv_op.get_attr(self.TF_ATTRIBUTE_STRIDES) padding = conv_op.get_attr(self.TF_ATTRIBUTE_PADDING) weights = self.get_weights(graph_helper, conv_op) weights = np.transpose(weights, [0, 1, 3, 2]) consumed_nodes = match.consumed_nodes output_op_nodes_names = [str(match[node.identifier].outputs[0].name) for node in self.graph_sequence.output_nodes] try: batch_to_space_op = match['batch_to_space'] conv_output_ops = graph_helper.get_op_outputs(batch_to_space_op) bias_op = GraphHelper.filter_single_op_by_type(conv_output_ops, 'BiasAdd') biases = self.get_biases(graph_helper, conv_op, bias_op) consumed_nodes.append(bias_op) output_op_nodes_names = [str(bias_op.outputs[0].name)] except OperationNotFoundError: bias_op = None biases = np.zeros(np.shape(weights)[-1], dtype=np.float32) dilation_sizes = match['dilation_sizes'] dilation_sizes = graph_helper.evaluate_tensor_output(dilation_sizes.outputs[0]) if np.shape(dilation_sizes) != (2,): raise ConverterError(code_to_message.get_message('ERROR_TF_CONV_RESOLVE_DILATION')(conv_op.name)) space_to_batch_op = match['space_to_batch'] paddings_op = match['paddings'] paddings_tensor = graph_helper.evaluate_tensor_output(paddings_op.outputs[0]) input_op = conv_op batch_to_space_op = match['batch_to_space'] crop_op = match['crops'] crops_tensor = graph_helper.evaluate_tensor_output(crop_op.outputs[0]) output_names = [str(conv_op.outputs[0].name)] if paddings_tensor.any() and not np.array_equal(paddings_tensor, crops_tensor): paddings_tensor = np.pad(paddings_tensor, ((1, 1), (0, 0)), 'constant') pad_descriptor = PadLayerResolver.Descriptor( str(space_to_batch_op.name), [match['space_to_batch'], match['dilation_sizes'], match['paddings']], paddings_tensor, snpe.modeltools.PADDING_CONSTANT, 0.0, output_names=[str(space_to_batch_op.outputs[0].name)]) descriptors.append(pad_descriptor) else: consumed_nodes.extend([space_to_batch_op, paddings_op, match['dilation_sizes']]) input_op = space_to_batch_op if crops_tensor.any() and not np.array_equal(paddings_tensor, crops_tensor): crops_tensor = np.pad(crops_tensor, ((1, 1), (0, 0)), 'constant') offsets = crops_tensor[:, 0] size = np.array(graph_helper.get_op_output_shape(match['batch_to_space']), dtype=np.int32) crop_descriptor = CropLayerResolver.Descriptor( str(match['batch_to_space'].name), [match['batch_to_space'], match['block_shape_out'], match['crops']], offsets, size, output_names=[str(match['batch_to_space'].outputs[0].name)]) descriptors.append(crop_descriptor) else: consumed_nodes.extend([batch_to_space_op, crop_op, match['block_shape_out']]) output_names = output_op_nodes_names d = ConvolutionLayerResolver.Descriptor(str(conv_op.name), consumed_nodes, conv_op, bias_op, strides, padding, weights, biases, output_names=output_names) d.groups = graph_helper.get_op_output_shape(space_to_batch_op)[-1] d.dilationY = int(dilation_sizes[0]) d.dilationX = int(dilation_sizes[1]) d.input_ops = [input_op] descriptors.append(d) return descriptors
def _broadcast_tensor(self, tensor, shape): raise ConverterError('ElementWise resolver must implement broadcast method.')
def resolve_layer(self, graph_matcher, graph_helper): raise ConverterError('Constant layers are resolved by other resolvers!')
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_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)