def test_permute_begin_end_ellipsis(self): # Testing constant path case graph = build_graph(nodes_attributes, [('input', 'data_1'), ('data_1', 'strided_slice'), ('begin', 'begin_data'), ('begin_data', 'strided_slice'), ('end', 'end_data'), ('end_data', 'strided_slice'), ('stride', 'stride_data'), ('stride_data', 'strided_slice'), ('strided_slice', 'data_2')], {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, 'begin': {'value': [0, 1], 'shape': [2]}, 'end': {'value': [1, 0], 'shape': [2]}, 'stride': {'value': [1, 2], 'shape': [2]}, 'strided_slice': {'begin_mask': np.array([0, 0]), 'end_mask': np.array([1, 0]), 'new_axis_mask': np.array([0]), 'shrink_axis_mask': [0], 'ellipsis_mask': np.array([1, 0])}, 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, }) slice_node = Node(graph, 'strided_slice') slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], slice_node['shrink_axis_mask'], 4, list(slice_node['begin_mask']), 0)) permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([0, 0, 0, 0]))) slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], slice_node['shrink_axis_mask'], 4, list(slice_node['end_mask']), 0)) permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') self.assertTrue(np.array_equal(slice_node.end_mask, np.array([1, 0, 0, 0])))
def tf_matmul_infer(node): assert (len(node.in_nodes()) == 2) shapes = [node.in_node(i).shape.copy() for i in range(2)] log.debug('matmul shapes: {}'.format(shapes)) if any(s is None or len(s) < 2 for s in shapes): log.error("MatMul wasn't able to infer shape") return if node.transpose_a: perm = np.array(range(len(node.in_node(0).shape)), dtype=np.int64) perm[-1], perm[-2] = perm[-2], perm[-1] inv = PermuteAttrs.get_inverse_permutation(perm) permutation = PermuteAttrs.Permutation(perm=perm, inv=int64_array(inv)) PermuteAttrs.set_permutation(node.in_node(0), node, permutation) shapes[0] = shapes[0][perm] if node.transpose_b: perm = np.array(range(len(node.in_node(1).shape)), dtype=np.int64) perm[-1], perm[-2] = perm[-2], perm[-1] inv = PermuteAttrs.get_inverse_permutation(perm) permutation = PermuteAttrs.Permutation(perm=perm, inv=int64_array(inv)) PermuteAttrs.set_permutation(node.in_node(1), node, permutation) shapes[1] = shapes[1][perm] if any(shapes[0][:-2] != shapes[1][:-2]) or shapes[0][-1] != shapes[1][-2]: log.error( "MatMul wasn't able to infer shape because input dimensions are not compatible" ) return shape_tuple = (np.array(shapes[0][:-1], dtype=np.int64), np.array([shapes[1][-1]], dtype=np.int64)) if len(shapes[0]) > 2: # TODO Investigate case when MatMul have inputs with not matching output dimensions # It looks to be a practical case and if we add outer dimensions of the first argument # it will lead to incorrect model sometimes. TF documentation is unclear. log.warning( 'Ignored outer dimensions of input tensor for MatMul node: {}'. format(node.name)) # shape_tuple = (shapes[0][:-2], *shape_tuple) log.debug('shape_tuple: {}'.format(shape_tuple)) node.out_node().shape = np.concatenate(shape_tuple) node['channel_dims'] = node.out_node().shape.size - 1 log.debug('matmul shape: {}'.format(node.out_node().shape))
def extract(node): attrs = tf_create_attrs(node, 4, 3) attrs.update({'op': __class__.op, 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([4, 3, 0, 1, 2]), inv=int64_array([2, 3, 4, 1, 0])) }) # update the attributes of the node Deconvolution.update_node_stat(node, attrs) return __class__.enabled
def extract(cls, node): attrs = tf_create_attrs(node, 4, 3) attrs.update({'op': cls.op, 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([4, 3, 0, 1, 2]), inv=int64_array([2, 3, 4, 1, 0])), 'swap_0_and_2_inputs': True, 'shape_input': True, }) # update the attributes of the node Deconvolution.update_node_stat(node, attrs) return cls.enabled
def test_permute_begin_end_shrink(self): # Testing constant path case graph = build_graph( nodes_attributes, [('data_1', 'strided_slice'), ('begin', 'strided_slice'), ('end', 'strided_slice'), ('stride', 'strided_slice'), ('strided_slice', 'data_2')], { 'data_1': { 'shape': np.array([1, 2, 3, 4]), 'value': None }, 'strided_slice': { 'begin_mask': np.array([1, 0, 0, 1]), 'end_mask': np.array([0, 1, 0, 1]), 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [1, 0, 0], 'ellipsis_mask': np.array([0, 0, 0]) }, 'data_2': { 'shape': np.array([2, 3, 4]), 'value': None }, }) slice_node = Node(graph, 'strided_slice') permute_masks( slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') self.assertTrue( np.array_equal(slice_node.begin_mask, np.array([1, 1, 0, 0]))) permute_masks( slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') self.assertTrue( np.array_equal(slice_node.end_mask, np.array([0, 1, 1, 0])))
def replace_pattern(self, graph: Graph, match: dict): if not match['input_0'].has_valid('value') and not match['input_1'].has_valid('value') or \ not match['input_0'].has_valid('value') and match['input_1'].has_valid('value') and match[ 'input_1'].shape.size > 2: match['fc']['type'] = 'GEMM' elif not match['input_0'].has_valid('value') and match['input_1'].has_valid('value'): match['fc']['type'] = 'FullyConnected' node = match['fc'] mark_input_bins(node) weights_node = match['input_1'] assign_dims_to_weights(weights_node, None, 0, 1, 2) PermuteAttrs.set_permutation(weights_node, node, PermuteAttrs.Permutation(perm=int64_array([1, 0]), inv=int64_array([0, 1]))) weights_shape = weights_node.shape node['out-size'] = weights_shape[1]
def extract(cls, node): attrs = tf_create_attrs(node, 3, 4) attrs.update({ 'op': __class__.op, 'get_group': lambda node: 1, 'get_output_feature_dim': lambda node: node.kernel_shape[node.output_feature_channel], 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([4, 3, 0, 1, 2]), inv=int64_array([2, 3, 4, 1, 0])) }) # update the attributes of the node Convolution.update_node_stat(node, attrs) return cls.enabled
def extract(cls, node): attrs = tf_create_attrs(node, 2, 2) attrs.update({ 'op': __class__.op, 'kernel_spatial_idx': np.array([0, 1], dtype=np.int64), 'get_group': lambda node: node.kernel_shape[node.output_feature_channel], 'get_output_feature_dim': lambda node: node.kernel_shape[-1] * node.kernel_shape[-2], 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([2, 3, 0, 1]), inv=int64_array([2, 3, 0, 1])) }) # update the attributes of the node Convolution.update_node_stat(node, attrs) return cls.enabled
def extract(cls, node): attrs = tf_create_attrs(node, 2, 3) attrs.update({ 'op': __class__.op, 'get_group': lambda node: node.group if 'group' in node and node.group is not None else node.in_node(0). shape[node.channel_dims] // node.kernel_shape[ node.input_feature_channel], 'get_output_feature_dim': lambda node: node.kernel_shape[node.output_feature_channel], 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([3, 2, 0, 1]), inv=int64_array([2, 3, 1, 0])) }) # update the attributes of the node Convolution.update_node_stat(node, attrs) return cls.enabled
**shaped_data('split_1_data1', [1, 4, 10, 10]), **shaped_data('split_1_data2', [1, 4, 10, 10]), **shaped_data('split_1_data3', [1, 4, 10, 10]), **shaped_data('split_1_data4', [1, 4, 10, 10]), **shaped_const_with_data('split_2_in_const_weights', int64_array([3, 3, 4, 16]), {'type': 'Const'}), **regular_op('split_2', {'type': 'Split'}), **valued_data('split_2_data1', np.zeros([3, 3, 4, 4])), **valued_data('split_2_data2', np.zeros([3, 3, 4, 4])), **valued_data('split_2_data3', np.zeros([3, 3, 4, 4])), **valued_data('split_2_data4', np.zeros([3, 3, 4, 4])), **regular_op_with_shaped_data('conv2d_1', [1, 4, 8, 8], {'type': 'Convolution', 'channel_dims': np.array([1]), 'pad': np.array([2, 2]), 'stride': np.array([2, 2]), 'get_weights_permute': PermuteAttrs.Permutation(perm=int64_array([3, 2, 0, 1]), inv=int64_array([2, 3, 1, 0])), 'group': 1, 'output': 4, 'output_shape': [1, 4, 8, 8], 'can_be_fused': True}), **regular_op_with_shaped_data('conv2d_2', [1, 4, 8, 8], {'type': 'Convolution', 'pad': np.array([2, 2]), 'stride': np.array([2, 2]), 'can_be_fused': True}), **regular_op_with_shaped_data('conv2d_3', [1, 4, 8, 8], {'type': 'Convolution', 'pad': np.array([2, 2]), 'stride': np.array([2, 2]), 'can_be_fused': True}), **regular_op_with_shaped_data('conv2d_4', [1, 4, 8, 8], {'type': 'Convolution', 'pad': np.array([2, 2]), 'stride': np.array([2, 2]), 'can_be_fused': True}), **regular_op_with_shaped_data('concat', [1, 16, 8, 8], {'type': 'Concat', 'axis': np.array(1)}), **regular_op_with_shaped_data('fused_group_conv', [1, 16, 8, 8], {'type': 'Convolution', 'channel_dims': np.array([1]), 'pad': np.array([2, 2]),