diff --git a/mace/python/tools/converter_tool/transformer.py b/mace/python/tools/converter_tool/transformer.py index 6b0c030658bd99c4da6eaa4200ce9985d8ee9f7e..152995ec65c13392b2c95d56ed9fbdd1cc73971b 100644 --- a/mace/python/tools/converter_tool/transformer.py +++ b/mace/python/tools/converter_tool/transformer.py @@ -210,7 +210,7 @@ class Transformer(base_converter.ConverterInterface): return False - def safe_remove_node(self, op, replace_op): + def safe_remove_node(self, op, replace_op, remove_input_tensor=False): """remove op. 1. change the inputs of its consumers to the outputs of replace_op 2. if the op is output node, change output node to replace op""" @@ -250,6 +250,12 @@ class Transformer(base_converter.ConverterInterface): op.output[i]) replace_op.output[i] = op.output[i] + if remove_input_tensor: + for input_name in op.input: + if input_name in self._consts: + const_tensor = self._consts[input_name] + self._model.tensors.remove(const_tensor) + self._model.op.remove(op) def add_in_out_tensor_info(self): @@ -900,6 +906,14 @@ class Transformer(base_converter.ConverterInterface): filter_data = filter_data.transpose(3, 2, 0, 1) filter.float_data[:] = filter_data.flat filter.dims[:] = filter_data.shape + if op.type == MaceOp.FullyConnected.name: + weight = self._consts[op.input[1]] + if len(weight.dims) == 4: + weight_data = np.array(weight.float_data).reshape( + weight.dims) + weight_data = weight_data.transpose(3, 2, 0, 1) + weight.float_data[:] = weight_data.flat + weight.dims[:] = weight_data.shape self.set_filter_format(FilterFormat.OIHW) for op in net.op: @@ -919,12 +933,13 @@ class Transformer(base_converter.ConverterInterface): for op in net.op: if op.type == MaceOp.FullyConnected.name: weight = self._consts[op.input[1]] - input_op = self._producer[op.input[0]] - input_shape = list(input_op.output_shape[0].dims) - input_data_format = ConverterUtil.data_format(input_op) - weight.dims[:] = [weight.dims[0]] + input_shape[1:] - if input_data_format == DataFormat.NHWC: - self.transpose_shape(weight.dims, [0, 3, 1, 2]) + if len(weight.dims) == 2: + input_op = self._producer[op.input[0]] + input_shape = list(input_op.output_shape[0].dims) + input_data_format = ConverterUtil.data_format(input_op) + weight.dims[:] = [weight.dims[0]] + input_shape[1:] + if input_data_format == DataFormat.NHWC: + self.transpose_shape(weight.dims, [0, 3, 1, 2]) return False @@ -1078,34 +1093,57 @@ class Transformer(base_converter.ConverterInterface): and self._producer[consumer.input[1]].type == 'Shape'): self.safe_remove_node( - self._producer[consumer.input[1]], None) + self._producer[consumer.input[1]], None, + remove_input_tensor=True) # remove consumer reshape - self.safe_remove_node(consumer, op) + self.safe_remove_node(consumer, op, + remove_input_tensor=True) # remove producer reshape self.safe_remove_node(producer, self._producer.get(producer.input[0], - None)) + None), + remove_input_tensor=True) return True return False def transform_matmul_to_fc(self): net = self._model + filter_format = self.filter_format() for op in net.op: - if op.type == MaceOp.MatMul.name: - input_shape = self.get_tensor_shape(op.input[0]) - if len(input_shape) == 4: - _, h, w, _ = self.sort_feature_map_shape(input_shape, - ConverterUtil.data_format(self._producer[op.input[0]])) # noqa - if h == 1 and w == 1 and op.input[1] in self._consts: - weight = self._consts[op.input[1]] - if len(weight.dims) == 2: - op.type = MaceOp.FullyConnected.name - weight_data = np.array(weight.float_data).reshape( - weight.dims) - weight_data = weight_data.transpose(1, 0) - weight.float_data[:] = weight_data.flat - weight.dims[:] = weight_data.shape + # transform reshape + matmul -> fc + # work for TensorFlow + if op.type == MaceOp.MatMul.name and \ + filter_format == FilterFormat.HWIO: + producer = self._producer[op.input[0]] + weight = self._consts[op.input[1]] + if len(weight.dims) == 2 \ + and producer.type == MaceOp.Reshape.name \ + and len(producer.output) == 1 \ + and producer.input[1] in self._consts \ + and len(producer.output_shape[0].dims) == 2: + input_op = self._producer[producer.input[0]] + input_shape = input_op.output_shape[0].dims + feature_size = np.prod(input_shape[1:]) + self.safe_remove_node(producer, input_op, + remove_input_tensor=True) + if feature_size == producer.output_shape[0].dims[1]: + print 'convert reshape and matmul to fc' + op.type = MaceOp.FullyConnected.name + weight_data = np.array(weight.float_data).reshape( + weight.dims) + weight.dims[:] = input_shape[1:] + \ + [weight_data.shape[1]] + return True + elif len(weight.dims) == 2 and \ + len(producer.output_shape[0].dims) == 2 and \ + weight.dims[0] == producer.output_shape[0].dims[1]: + print 'convert matmul to fc' + op.type = MaceOp.FullyConnected.name + weight_data = np.array(weight.float_data).reshape( + weight.dims) + weight.dims[:] = [1, 1] + list(weight_data.shape) + return True return False @@ -1144,9 +1182,6 @@ class Transformer(base_converter.ConverterInterface): print("transform global conv to fc %s(%s)" % (op.name, op.type)) op.type = MaceOp.FullyConnected.name - filter.dims[:] = [out_channels, - in_channels * filter_width - * filter_height][:] def add_device(self): # TODO(liuqi) add device definition in OperatorDef diff --git a/repository/git/git_configure.bzl b/repository/git/git_configure.bzl index 9ef9838f0721af41c6ed765648e716636a1f45ec..d5e98ff73cd93fbda2bf242e15232fea2ffb5540 100644 --- a/repository/git/git_configure.bzl +++ b/repository/git/git_configure.bzl @@ -9,8 +9,12 @@ def _git_version_conf_impl(repository_ctx): generated_files_path = repository_ctx.path("gen") - unused_var = repository_ctx.path(Label("//:.git/HEAD")) - unused_var = repository_ctx.path(Label("//:.git/refs/heads/master")) + ret = repository_ctx.execute( + ["test", "-f", "%s/.git/logs/HEAD" % mace_root_path]) + + if ret.return_code == 0: + unused_var = repository_ctx.path(Label("//:.git/HEAD")) + unused_var = repository_ctx.path(Label("//:.git/refs/heads/master")) repository_ctx.execute([ 'bash', '%s/mace/tools/git/gen_version_source.sh' % mace_root_path diff --git a/repository/opencl-kernel/opencl_kernel_configure.bzl b/repository/opencl-kernel/opencl_kernel_configure.bzl index 1e650b4f64c01a193f1bf1b209dd12ad8d6be211..0365fc8447ef5f260a053c6ba61ec566bef90e3c 100644 --- a/repository/opencl-kernel/opencl_kernel_configure.bzl +++ b/repository/opencl-kernel/opencl_kernel_configure.bzl @@ -5,8 +5,15 @@ def _opencl_encrypt_kernel_impl(repository_ctx): "BUILD", Label("//repository/opencl-kernel:BUILD.tpl")) - unused_var = repository_ctx.path(Label("//:.git/HEAD")) - unused_var = repository_ctx.path(Label("//:.git/refs/heads/master")) + mace_root_path = str(repository_ctx.path(Label("@mace//:BUILD")))[:-len("BUILD")] + + ret = repository_ctx.execute( + ["test", "-f", "%s/.git/logs/HEAD" % mace_root_path]) + + if ret.return_code == 0: + unused_var = repository_ctx.path(Label("//:.git/HEAD")) + unused_var = repository_ctx.path(Label("//:.git/refs/heads/master")) + unused_var = repository_ctx.path(Label("//:mace/kernels/opencl/cl/activation.cl")) unused_var = repository_ctx.path(Label("//:mace/kernels/opencl/cl/addn.cl")) unused_var = repository_ctx.path(Label("//:mace/kernels/opencl/cl/batch_norm.cl")) @@ -33,7 +40,6 @@ def _opencl_encrypt_kernel_impl(repository_ctx): unused_var = repository_ctx.path(Label("//:mace/kernels/opencl/cl/space_to_batch.cl")) unused_var = repository_ctx.path(Label("//:mace/kernels/opencl/cl/winograd_transform.cl")) - mace_root_path = str(repository_ctx.path(Label("@mace//:BUILD")))[:-len("BUILD")] generated_files_path = repository_ctx.path("gen")