diff --git a/image_classification/tf2paddle/README.md b/image_classification/tf2paddle/README.md index f9bb4e4d284003cdd8d4d3cf5c2787176c78be7f..e61a781c0538ac4e4fc009b01c45c8b48d5169f7 100644 --- a/image_classification/tf2paddle/README.md +++ b/image_classification/tf2paddle/README.md @@ -1,27 +1,40 @@ ## 使用说明 -`tf2paddle.py`提供了将TensorFlow训练的模型转换为PaddlePaddle可使用的模型的接口`TFModelConverter`,其封装了图像领域常用的Convolution、BatchNorm等layer的转换函数,可以完成VGG、ResNet等常用模型的转换。模型转换的基本过程是:基于TensorFlow的Python API获取variable,将各variable对应到PaddlePaddle中layer的参数,进行适配后序列化保存输出可以直接为PaddlePaddle的Python API加载使用的模型文件。 +`tf2paddle.py`脚本中的工具类`TFModelConverter`实现了将TensorFlow训练好的模型文件转换为PaddlePaddle可加载的模型文件。目前能够支持图像领域常用的:卷积(`Convolution`)层、`Batch Normalization`层和全连接(`Full Connection`)层。图像领域常用的 `ResNet` `VGG` 网络都以这些层此为基础,使用TensorFlow训练的`ResNet`和`VGG`模型能够被转换为PaddlePaddle可加载的模型,进一步用于预训练或是预测服务的开发等。 -为使TensorFlow模型中的variable能够正确对应到PaddlePaddle模型中layer的参数,正确完成转换,模型转换具有如下约束: +模型转换的基本流程是: +1. 将TensorFlow模型等价地使用PaddlePaddle Python API接口进行改写。 +1. 在TensorFlow中可学习参数用 `Variable` 表示,基于TensorFlow的Python API获取网络中的 Variable。 +1. 确定TensorFlow模型中`Variable`与PaddlePaddle中`paddle.layer`的可学习参数的对应关系。 +1. 对TensorFlow中的`Variable`进行一定的适配(详见下文),转化为PaddlePaddle中的参数存储格式并进行序列化保存。 -- 支持TensorFlow中conv2d,batchnorm,fc这三种带有trainable variable的Operator中参数的转换。 - TensorFlow配置中同一Operator内的variable属于相同的scope,以此将variable划分到不同的layer。 -- conv2d、batchnorm、fc的scope需分别包含conv、bn、fc,以此获取对应layer的type;亦可以通过为`TFModelConverter`传入`layer_type_map`的`dict`,将scope映射到对应的layer type来规避此项约束。 -- conv2d、fc中variable的顺序为先weight后bias,batchnorm中variable的顺序为scale、shift、mean、var,以此将variable对应到layer中相应位置的参数。 -- TensorFlow网络拓扑顺序需和PaddlePaddle网络拓扑顺序一致,尤其注意具有分支时左右分支的顺序。这是针对模型转换和PaddlePaddle网络配置均使用PaddlePaddle默认参数命名的情况,此时将根据拓扑顺序进行参数命名;若PaddlePaddle网络配置中自定义了param的name,可以通过为`TFModelConverter`传入`layer_name_map`或`param_name_map`的`dict`,在模型转换时将variable的name映射为PaddlePaddle配置中param的name。 +### 需要遵守的约定 -此外,要求提供`build_model`接口以从此构建TensorFlow网络,加载模型并返回session。可参照如下示例: +为使TensorFlow模型中的`Variable`能够正确对应到`paddle.layer`中的可学习参数,目前版本在使用时有如下约束需要遵守: -```python -def build_model(): - build_graph() - sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) - sess.run(tf.tables_initializer()) - saver = tf.train.Saver() - saver.restore(sess, 'model/model.ckpt') - return sess -``` +1. 目前仅支持将TensorFlow中 `conv2d`,`batchnorm`,`fc`这三种带有可学习`Variable`的Operator训练出的参数向PaddlePaddle模型参数转换。 +1. TensorFlow网络配置中同一Operator内的`Variable`属于相同的scope,以此为依据将`Variable`划分到不同的`paddle.layer`。 +1. `conv2d`、`batchnorm`、`fc`的scope需分别包含`conv`、`bn`、`fc`,以此获取对应`paddle.layer`的类型。也可以通过为`TFModelConverter`传入`layer_type_map`的`dict`,将scope映射到对应的`paddle.layer`的type来规避此项约束。 +1. `conv2d`、`fc`中`Variable`的顺序为:先可学习`Weight`后`Bias`;`batchnorm`中`Variable`的顺序为:`scale`、`shift`、`mean`、`var`,请注意参数存储的顺序将`Variable`对应到`paddle.layer.batch_norm`相应位置的参数。 +1. TensorFlow网络拓扑顺序需和PaddlePaddle网络拓扑顺序一致,尤其注意具有分支时左右分支的顺序。这是针对模型转换和PaddlePaddle网络配置均使用PaddlePaddle默认参数命名的情况,此时将根据拓扑顺序进行参数命名。 +1. 若PaddlePaddle网络配置中需要通过调用`param_attr=paddle.attr.Param(name="XX"))`显示地设置可学习参数名字,这时可通过为`TFModelConverter`传入`layer_name_map`或`param_name_map`字典(类型为Python `dict`),在模型转换时将`Variable`的名字映射为所对应的`paddle.layer.XX`中可学习参数的名字。 +1. 要求提供`build_model`接口以从此构建TensorFlow网络,加载模型并返回session。可参照如下示例进行编写: + + ```python + def build_model(): + build_graph() + sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) + sess.run(tf.tables_initializer()) + saver = tf.train.Saver() + saver.restore(sess, 'model/model.ckpt') + return sess + ``` -在完成以上内容后,`TFModelConverter`使用如下: +### 使用说明 + +按照以上原则操作后,`tf2paddle.py` 脚本的`main`函数提供了一个调用示例,将TensorFlow训练的`ResNet50`模型转换为PaddlePaddle可加载模型。若要对其它各种自定义的模型进行转换,只需修改相关变量的值,在终端执行`python tf2paddle.py`即可。 + +下面是一个简单的调用示例: ```python # 定义相关变量 @@ -35,8 +48,7 @@ converter = TFModelConverter(tf_net=tf_net, converter.convert() ``` -`tf2paddle.py`中已提供以上步骤,修改其中相关变量的值后执行`python tf2paddle.py`即可完成模型转换。 - -此外,在使用转换得到的模型时需要注意: +### 注意事项 -- 由于TensorFlow中的padding机制较为特殊,在编写PaddlePaddle网络配置时对conv这种需要padding的layer可能需要推算size后在conv外使用pad_layer进行padding。 - 与TensorFlow多使用NHWC的data_format不同,PaddlePaddle使用NCHW的输入数据。 +1. 由于TensorFlow中的padding机制较为特殊,在编写PaddlePaddle网络配置时,对`paddle.layer.conv`这种需要padding的层可能需要推算size后在`paddle.layer.conv`外使用`paddle.layer.pad`进行padding。 +1. 与TensorFlow图像输入多使用NHWC的数据组织格式有所不同,PaddlePaddle按照NCHW的格式组织图像输入数据。 diff --git a/image_classification/tf2paddle/tf2paddle.py b/image_classification/tf2paddle/tf2paddle.py index 4cc8b77097ec97fa04936f0e9a518f6a1602a06e..c4c18fad7bf96146685a20a5fc382611db71eceb 100644 --- a/image_classification/tf2paddle/tf2paddle.py +++ b/image_classification/tf2paddle/tf2paddle.py @@ -6,9 +6,11 @@ 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 -import tensorflow as tf class ModelConverter(object):