Repository: PaddlePaddle/models

Issue:
How to use a model from TF
How to use a model from TF


Discussion:

Resolving patch:
diff --git a/image_classification/tf2paddle/tf2paddle.py b/image_classification/tf2paddle/tf2paddle.py
new file mode 100644
--- /dev/null
+++ b/image_classification/tf2paddle/tf2paddle.py
@@ -0,0 +1,177 @@
+import os
+import re
+import collections
+import struct
+import gzip
+import tarfile
+import cStringIO
+import numpy as np
+
+import tensorflow as tf
+
+from paddle.proto.ParameterConfig_pb2 import ParameterConfig
+from paddle.trainer_config_helpers.default_decorators import wrap_name_default
+
+
+class ModelConverter(object):
+    def __init__(self,
+                 paddle_tar_name,
+                 param_name_map=None,
+                 layer_name_map=None,
+                 layer_type_map=None):
+        self.tar_name = paddle_tar_name
+        self.param_name_map = param_name_map
+        self.layer_name_map = layer_name_map
+        self.layer_type_map = layer_type_map
+        self.params = dict()
+
+    def convert(self):
+        layers_params = self.arrange_layer_params()
+        for layer_name in layers_params.keys():
+            layer_params, layer_params_names, layer_type = layers_params[
+                layer_name]
+            if len(layer_params) > 0:
+                if not layer_type:
+                    assert layer_type_map and (
+                        layer_type_map.get(layer_name) in ["conv", "bn", "fc"])
+                    layer_type = layer_type_map[layer_name]
+                self.pre_layer_name = getattr(
+                    self, "convert_" + layer_type + "_layer")(
+                        layer_params,
+                        params_names=[
+                            self.param_name_map.get(name)
+                            if self.param_name_map else None
+                            for name in layer_params_names
+                        ],
+                        name=None if self.layer_name_map == None else
+                        self.layer_name_map.get(layer_name))
+        with gzip.open(self.tar_name, 'w') as f:
+            self.to_tar(f)
+        return
+
+    def to_tar(self, f):
+        tar = tarfile.TarFile(fileobj=f, mode='w')
+        for param_name in self.params.keys():
+            param_conf, param_data = self.params[param_name]
+
+            confStr = param_conf.SerializeToString()
+            tarinfo = tarfile.TarInfo(name="%s.protobuf" % param_name)
+            tarinfo.size = len(confStr)
+            buf = cStringIO.StringIO(confStr)
+            buf.seek(0)
+            tar.addfile(tarinfo, fileobj=buf)
+
+            buf = cStringIO.StringIO()
+            self.serialize(param_data, buf)
+            tarinfo = tarfile.TarInfo(name=param_name)
+            buf.seek(0)
+            tarinfo.size = len(buf.getvalue())
+            tar.addfile(tarinfo, buf)
+
+    @staticmethod
+    def serialize(data, f):
+        f.write(struct.pack("IIQ", 0, 4, data.size))
+        f.write(data.tobytes())
+
+
+class TFModelConverter(ModelConverter):
+    def __init__(self,
+                 tf_net,
+                 paddle_tar_name,
+                 param_name_map=None,
+                 layer_name_map=None,
+                 layer_type_map=None):
+        super(TFModelConverter, self).__init__(paddle_tar_name, param_name_map,
+                                               layer_name_map, layer_type_map)
+        self.sess = __import__(tf_net).build_model()
+
+    def arrange_layer_params(self):
+        all_vars = tf.global_variables()
+        layers_params = collections.OrderedDict()
+        for var in all_vars:
+            var_name = var.name
+            scope_pos = var_name.rfind('/')
+            if scope_pos != -1:
+                layer_scope = var_name[:scope_pos]
+                if layers_params.has_key(layer_scope):
+                    layer_params, layer_params_names, layer_type = layers_params[
+                        layer_scope]
+                    layer_params.append(var.eval(self.sess))
+                    layer_params_names.append(var_name)
+                else:
+                    layer_type = re.search('conv|bn|fc', layer_scope)
+                    layers_params[layer_scope] = ([var.eval(self.sess)],
+                                                  [var_name], layer_type.group()
+                                                  if layer_type else None)
+        return layers_params
+
+    @wrap_name_default("conv")
+    def convert_conv_layer(self, params, params_names=None, name=None):
+        for i in range(len(params)):
+            data = np.transpose(params[i], (
+                3, 2, 0, 1)) if len(params[i].shape) == 4 else params[i]
+            if len(params) == 2:
+                suffix = "0" if i == 0 else "bias"
+                file_name = "_%s.w%s" % (name, suffix) if not (
+                    params_names and params_names[i]) else params_names[i]
+            else:
+                file_name = "_%s.w%s" % (name, str(i)) if not (
+                    params_names and params_names[i]) else params_names[i]
+            param_conf = ParameterConfig()
+            param_conf.name = file_name
+            dims = list(data.shape)
+            if len(dims) == 1:
+                dims.insert(1, 1)
+                param_conf.dims.extend(dims)
+            param_conf.size = reduce(lambda a, b: a * b, data.shape)
+            self.params[file_name] = (param_conf, data.flatten())
+
+    @wrap_name_default("fc_layer")
+    def convert_fc_layer(self, params, params_names=None, name=None):
+        for i in range(len(params)):
+            data = params[i]
+            if len(params) == 2:
+                suffix = "0" if i == 0 else "bias"
+                file_name = "_%s.w%s" % (name, suffix) if not (
+                    params_names and params_names[i]) else params_names[i]
+            else:
+                file_name = "_%s.w%s" % (name, str(i)) if not (
+                    params_names and params_names[i]) else params_names[i]
+            param_conf = ParameterConfig()
+            param_conf.name = file_name
+            dims = list(data.shape)
+            if len(dims) < 2:
+                dims.insert(0, 1)
+            param_conf.size = reduce(lambda a, b: a * b, dims)
+            param_conf.dims.extend(dims)
+            self.params[file_name] = (param_conf, data.flatten())
+        return name
+
+    @wrap_name_default("batch_norm")
+    def convert_bn_layer(self, params, params_names=None, name=None):
+        params = [params[i] for i in (0, 2, 3, 1)]
+        params_names = [params_names[i]
+                        for i in (0, 2, 3, 1)] if params_names else params_names
+        for i in range(len(params)):
+            data = params[i]
+            file_name = "_%s.w%s" % (name, str(i)) if i < 3 else "_%s.w%s" % (
+                name, "bias")
+            file_name = file_name if not (params_names and
+                                          params_names[i]) else params_names[i]
+            param_conf = ParameterConfig()
+            param_conf.name = file_name
+            dims = list(data.shape)
+            assert len(dims) == 1
+            dims.insert(0, 1)
+            param_conf.size = reduce(lambda a, b: a * b, dims)
+            param_conf.dims.extend(dims)
+            self.params[file_name] = (param_conf, data.flatten())
+        return name
+
+
+if __name__ == "__main__":
+    tf_net = "TF_ResNet"
+    paddle_tar_name = "Paddle_ResNet50.tar.gz"
+
+    converter = TFModelConverter(tf_net=tf_net, paddle_tar_name=paddle_tar_name)
+    converter.convert()


Test patch: