convert.py 11.2 KB
Newer Older
1
# Copyright (c) 2020  PaddlePaddle Authors. All Rights Reserved.
J
jiangjiajun 已提交
2 3 4 5 6 7 8 9 10 11 12 13
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
S
SunAhong1993 已提交
14

15
from six import text_type as _text_type
S
SunAhong1993 已提交
16
from x2paddle import program
17
import argparse
J
jiangjiajun 已提交
18
import sys
19

J
jiangjiajun 已提交
20

21 22
def arg_parser():
    parser = argparse.ArgumentParser()
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    parser.add_argument(
        "--model",
        "-m",
        type=_text_type,
        default=None,
        help="define model file path for tensorflow or onnx")
    parser.add_argument(
        "--prototxt",
        "-p",
        type=_text_type,
        default=None,
        help="prototxt file of caffe model")
    parser.add_argument(
        "--weight",
        "-w",
        type=_text_type,
        default=None,
        help="weight file of caffe model")
    parser.add_argument(
        "--save_dir",
        "-s",
        type=_text_type,
        default=None,
        help="path to save translated model")
J
upgrade  
jiangjiajun 已提交
47 48 49 50 51
    parser.add_argument(
        "--framework",
        "-f",
        type=_text_type,
        default=None,
52 53
        help="define which deeplearning framework(tensorflow/caffe/onnx/paddle2onnx)"
    )
S
SunAhong1993 已提交
54 55 56 57 58
    parser.add_argument(
        "--caffe_proto",
        "-c",
        type=_text_type,
        default=None,
J
upgrade  
jiangjiajun 已提交
59 60
        help="optional: the .py file compiled by caffe proto file of caffe model"
    )
61 62 63 64 65 66
    parser.add_argument(
        "--version",
        "-v",
        action="store_true",
        default=False,
        help="get version of x2paddle")
67 68 69
    parser.add_argument(
        "--without_data_format_optimization",
        "-wo",
S
SunAhong1993 已提交
70 71
        type=_text_type,
        default="True",
72
        help="tf model conversion without data format optimization")
73 74 75 76 77 78
    parser.add_argument(
        "--define_input_shape",
        "-d",
        action="store_true",
        default=False,
        help="define input shape for tf model")
C
Channingss 已提交
79 80 81 82 83 84
    parser.add_argument(
        "--onnx_opset",
        "-oo",
        type=int,
        default=10,
        help="when paddle2onnx set onnx opset version to export")
85 86 87 88 89 90
    parser.add_argument(
        "--params_merge",
        "-pm",
        action="store_true",
        default=False,
        help="define whether merge the params")
S
SunAhong1993 已提交
91
    parser.add_argument(
S
SunAhong1993 已提交
92 93 94 95 96 97 98 99
        "--jit_type",
        "-jt",
        type=_text_type,
        default="script",
        help="define the jit type of pytorch Module.")
    parser.add_argument(
        "--input_files",
        "-if",
S
SunAhong1993 已提交
100 101
        action='append',
        default=None,
S
SunAhong1993 已提交
102 103 104 105 106 107 108 109 110
        help="define the inputs' file path")
    parser.add_argument(
        "--paddle_type",
        "-pt",
        type=_text_type,
        default="dygraph",
        help="define the paddle model type after converting(dygraph/static)"
    )
    
111
    return parser
J
jiangjiajun 已提交
112

C
Channingss 已提交
113

114 115
def tf2paddle(model_path,
              save_dir,
J
jiangjiajun 已提交
116
              without_data_format_optimization=False,
M
mamingjie-China 已提交
117
              define_input_shape=False,
M
mamingjie-China 已提交
118
              params_merge=False):
J
jiangjiajun 已提交
119 120
    # check tensorflow installation and version
    try:
121 122
        import os
        os.environ["TF_CPP_MIN_LOG_LEVEL"] = '3'
J
jiangjiajun 已提交
123 124 125 126
        import tensorflow as tf
        version = tf.__version__
        if version >= '2.0.0' or version < '1.0.0':
            print(
J
jiangjiajun@baidu.com 已提交
127
                "[ERROR] 1.0.0<=tensorflow<2.0.0 is required, and v1.14.0 is recommended"
J
jiangjiajun 已提交
128 129 130
            )
            return
    except:
J
jiangjiajun@baidu.com 已提交
131 132 133
        print(
            "[ERROR] Tensorflow is not installed, use \"pip install tensorflow\"."
        )
J
jiangjiajun 已提交
134
        return
S
SunAhong1993 已提交
135

J
jiangjiajun 已提交
136
    from x2paddle.decoder.tf_decoder import TFDecoder
J
jiangjiajun 已提交
137
    from x2paddle.op_mapper.tf_op_mapper import TFOpMapper
S
SunAhong1993 已提交
138 139 140
    from x2paddle.optimizer.tensorflow.bias import BiasOpt
    from x2paddle.optimizer.tensorflow.transpose import TransposeOpt
    from x2paddle.optimizer.tensorflow.batch_norm import BatchNormOpt
J
jiangjiajun 已提交
141 142

    print("Now translating model from tensorflow to paddle.")
143
    model = TFDecoder(model_path, define_input_shape=define_input_shape)
S
SunAhong1993 已提交
144

S
SunAhong1993 已提交
145
    mapper = TFOpMapper(model)
J
jiangjiajun 已提交
146
    program.build()
S
SunAhong1993 已提交
147 148 149 150 151 152
    bias_opt = BiasOpt()
    transpose_opt = TransposeOpt()
    batch_norm_opt = BatchNormOpt()
    bias_opt.run(program)
    batch_norm_opt.run(program)
    transpose_opt.run(program)
J
jiangjiajun 已提交
153
    program.gen_model(save_dir)
154 155


S
SunAhong1993 已提交
156 157 158 159 160 161 162
def caffe2paddle(proto, weight, save_dir, caffe_proto, 
                 paddle_type, params_merge=False):
    from x2paddle.caffe_convert import Decoder
    if paddle_type == "dygraph":
        from x2paddle.caffe_convert import DygraphOpMapper as OpMapper
    else:
        from x2paddle.caffe_convert import StaticOpMapper as OpMapper
S
SunAhong1993 已提交
163
    import google.protobuf as gpb
S
SunAhong1993 已提交
164 165 166 167 168
    ver_part = gpb.__version__.split('.')
    version_satisfy = False
    if (int(ver_part[0]) == 3 and int(ver_part[1]) >= 6) \
        or (int(ver_part[0]) > 3):
        version_satisfy = True
J
jiangjiajun@baidu.com 已提交
169
    assert version_satisfy, '[ERROR] google.protobuf >= 3.6.0 is required'
J
jiangjiajun 已提交
170
    print("Now translating model from caffe to paddle.")
S
SunAhong1993 已提交
171 172 173 174
    model = Decoder(proto, weight, caffe_proto)
    mapper = OpMapper(model)
    mapper.pd_graph.build()
    mapper.pd_graph.gen_model(save_dir)
175 176


M
mamingjie-China 已提交
177
def onnx2paddle(model_path, save_dir, params_merge=False):
C
update  
channingss 已提交
178 179 180 181
    # check onnx installation and version
    try:
        import onnx
        version = onnx.version.version
S
SunAhong1993 已提交
182 183
        if version < '1.6.0':
            print("[ERROR] onnx>=1.6.0 is required")
C
update  
channingss 已提交
184 185
            return
    except:
J
jiangjiajun@baidu.com 已提交
186
        print("[ERROR] onnx is not installed, use \"pip install onnx==1.6.0\".")
C
update  
channingss 已提交
187
        return
C
channingss 已提交
188
    print("Now translating model from onnx to paddle.")
C
update  
channingss 已提交
189

C
Channingss 已提交
190
    from x2paddle.op_mapper.onnx2paddle.onnx_op_mapper import ONNXOpMapper
C
update  
channingss 已提交
191
    from x2paddle.decoder.onnx_decoder import ONNXDecoder
R
root 已提交
192 193
    from x2paddle.optimizer.onnx_optimizer import ONNXOptimizer
    model = ONNXDecoder(model_path)
C
Channingss 已提交
194
    mapper = ONNXOpMapper(model)
195
    print("Model optimizing ...")
C
update  
channingss 已提交
196
    optimizer = ONNXOptimizer(mapper)
C
Channingss 已提交
197
    optimizer.delete_redundance_code()
198
    print("Model optimized.")
C
channingss 已提交
199

200
    print("Paddle model and code generating ...")
M
mamingjie-China 已提交
201
    mapper.save_inference_model(save_dir, params_merge)
202
    print("Paddle model and code generated.")
C
Channingss 已提交
203 204


S
SunAhong1993 已提交
205
def pytorch2paddle(model_path, save_dir, jit_type, input_files):
S
SunAhong1993 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
    # check pytorch installation and version
    try:
        import torch
        version = torch.__version__
        ver_part = version.split('.')
        print(ver_part)
        if int(ver_part[1]) < 5:
            print("[ERROR] pytorch>=1.5.0 is required")
            return
    except:
        print(
            "[ERROR] Pytorch is not installed, use \"pip install torch==1.5.0 torchvision\"."
        )
        return
    print("Now translating model from pytorch to paddle.")

S
SunAhong1993 已提交
222
    from x2paddle.decoder.pytorch_decoder import ScriptDecoder, TraceDecoder
S
SunAhong1993 已提交
223
    from x2paddle.op_mapper.pytorch2paddle import pytorch_op_mapper
S
SunAhong1993 已提交
224 225 226 227
    if jit_type == "trace":
        model = TraceDecoder(model_path, input_files)
    else:
        model = ScriptDecoder(model_path)
S
SunAhong1993 已提交
228 229 230 231 232 233 234
    mapper = pytorch_op_mapper.PyTorchOpMapper(model)
    mapper.graph.build()
    print("Model optimizing ...")
    from x2paddle.optimizer.pytorch_optimizer.optimizer import GraphOptimizer
    graph_opt = GraphOptimizer()
    graph_opt.optimize(mapper.graph)
    print("Model optimized.")
S
SunAhong1993 已提交
235
    mapper.graph.gen_model(save_dir, jit_type, input_files)
S
SunAhong1993 已提交
236 237


J
Jason 已提交
238
def paddle2onnx(model_path, save_dir, opset_version=10):
S
SunAhong1993 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    import paddle.fluid as fluid
    try:
        import paddle2onnx
    except:
        print(
            "[ERROR] paddle2onnx not installed, use \"pip install paddle2onnx\"")

    import paddle2onnx as p2o
    model = p2o.PaddleDecoder(model_path, '__model__', '__params__')
    mapper = p2o.PaddleOpMapper()
    mapper.convert(
        model.program,
        save_dir,
        scope=fluid.global_scope(),
        opset_version=opset_version)
C
update  
channingss 已提交
254 255


256
def main():
J
jiangjiajun 已提交
257
    if len(sys.argv) < 2:
C
update  
channingss 已提交
258
        print("Use \"x2paddle -h\" to print the help information")
J
jiangjiajun 已提交
259 260
        print("For more information, please follow our github repo below:)")
        print("\nGithub: https://github.com/PaddlePaddle/X2Paddle.git\n")
J
jiangjiajun 已提交
261 262
        return

263 264 265
    parser = arg_parser()
    args = parser.parse_args()

J
jiangjiajun 已提交
266
    if args.version:
J
jiangjiajun 已提交
267
        import x2paddle
M
mamingjie-China 已提交
268
        print("x2paddle-{} with python>=3.5, paddlepaddle>=1.6.0\n".format(
J
jiangjiajun 已提交
269
            x2paddle.__version__))
J
jiangjiajun 已提交
270 271
        return

J
Jason 已提交
272
    assert args.framework is not None, "--framework is not defined(support tensorflow/caffe/onnx)"
273
    assert args.save_dir is not None, "--save_dir is not defined"
S
SunAhong1993 已提交
274
    assert args.paddle_type in ["dygraph", "static"], "--paddle_type must be 'dygraph' or 'static'"
M
mamingjie-China 已提交
275

M
mamingjie-China 已提交
276 277 278
    try:
        import paddle
        v0, v1, v2 = paddle.__version__.split('.')
279 280 281
        print("paddle.__version__ = {}".format(paddle.__version__))
        if v0 == '0' and v1 == '0' and v2 == '0':
            print("[WARNING] You are use develop version of paddlepaddle")
S
SunAhong1993 已提交
282 283
        elif int(v0) != 2 or int(v1) < 0:
            print("[ERROR] paddlepaddle>=2.0.0 is required")
M
mamingjie-China 已提交
284 285
            return
    except:
J
jiangjiajun@baidu.com 已提交
286 287 288
        print(
            "[ERROR] paddlepaddle not installed, use \"pip install paddlepaddle\""
        )
289 290

    if args.framework == "tensorflow":
J
jiangjiajun 已提交
291
        assert args.model is not None, "--model should be defined while translating tensorflow model"
S
SunAhong1993 已提交
292 293 294
        assert args.without_data_format_optimization in [
            "True", "False"
        ], "--the param without_data_format_optimization should be defined True or False"
295
        define_input_shape = False
M
mamingjie-China 已提交
296
        params_merge = False
S
SunAhong1993 已提交
297
        without_data_format_optimization = True if args.without_data_format_optimization == "True" else False
298 299
        if args.define_input_shape:
            define_input_shape = True
M
mamingjie-China 已提交
300 301
        if args.params_merge:
            params_merge = True
302
        tf2paddle(args.model, args.save_dir, without_data_format_optimization,
M
mamingjie-China 已提交
303
                  define_input_shape, params_merge)
304 305

    elif args.framework == "caffe":
S
SunAhong1993 已提交
306
        assert args.prototxt is not None and args.weight is not None, "--prototxt and --weight should be defined while translating caffe model"
M
mamingjie-China 已提交
307 308 309
        params_merge = False
        if args.params_merge:
            params_merge = True
S
SunAhong1993 已提交
310
        caffe2paddle(args.prototxt, args.weight, args.save_dir,
S
SunAhong1993 已提交
311
                     args.caffe_proto, args.paddle_type, params_merge)
C
update  
channingss 已提交
312 313
    elif args.framework == "onnx":
        assert args.model is not None, "--model should be defined while translating onnx model"
M
mamingjie-China 已提交
314
        params_merge = False
315

M
mamingjie-China 已提交
316 317 318
        if args.params_merge:
            params_merge = True
        onnx2paddle(args.model, args.save_dir, params_merge)
S
SunAhong1993 已提交
319 320 321 322
    elif args.framework == "pytorch":
        assert args.model is not None, "--model should be defined while translating pytorch model"
        pytorch2paddle(args.model, args.save_dir, args.jit_type, args.input_files)

323 324
    elif args.framework == "paddle2onnx":
        assert args.model is not None, "--model should be defined while translating paddle model to onnx"
S
SunAhong1993 已提交
325
        paddle2onnx(args.model, args.save_dir, opset_version=args.onnx_opset)
326

327
    else:
328 329
        raise Exception(
            "--framework only support tensorflow/caffe/onnx/paddle2onnx now")
330 331 332


if __name__ == "__main__":
C
Channingss 已提交
333
    main()