Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
X2Paddle
提交
f729a29c
X
X2Paddle
项目概览
PaddlePaddle
/
X2Paddle
大约 1 年 前同步成功
通知
328
Star
698
Fork
167
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
26
列表
看板
标记
里程碑
合并请求
4
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
X2Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
26
Issue
26
列表
看板
标记
里程碑
合并请求
4
合并请求
4
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
f729a29c
编写于
12月 10, 2020
作者:
S
SunAhong1993
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix the docs
上级
fd3c33a8
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
403 addition
and
16 deletion
+403
-16
caffe_custom_layer.md
caffe_custom_layer.md
+0
-14
docs/introduction/op_list.md
docs/introduction/op_list.md
+46
-1
docs/introduction/x2paddle_model_zoo.md
docs/introduction/x2paddle_model_zoo.md
+22
-0
docs/user_guides/FAQ.md
docs/user_guides/FAQ.md
+17
-0
docs/user_guides/add_caffe_custom_layer.md
docs/user_guides/add_caffe_custom_layer.md
+205
-0
docs/user_guides/export_tf_model.md
docs/user_guides/export_tf_model.md
+112
-0
docs/user_guides/pytorch2onnx.md
docs/user_guides/pytorch2onnx.md
+0
-0
docs/user_guides/pytorch2paddle.md
docs/user_guides/pytorch2paddle.md
+1
-1
未找到文件。
caffe_custom_layer.md
已删除
100644 → 0
浏览文件 @
fd3c33a8
目前,代码中已经提供了10个非官方op(不在
[
官网
](
http://caffe.berkeleyvision.org/tutorial/layers
)
上的op)的转换,这些op对应的Caffe实现源码如下:
| op | 该版本实现源码 |
|-------|--------|
| PriorBox |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/prior_box_layer.cpp
)
|
| DetectionOutput |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/detection_output_layer.cpp
)
|
| ConvolutionDepthwise |
[
code
](
https://github.com/farmingyard/caffe-mobilenet/blob/master/conv_dw_layer.cpp
)
|
| ShuffleChannel |
[
code
](
https://github.com/farmingyard/ShuffleNet/blob/master/shuffle_channel_layer.cpp
)
|
| Permute |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/permute_layer.cpp
)
|
| Normalize |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/normalize_layer.cpp
)
|
| ROIPooling |
[
code
](
https://github.com/rbgirshick/caffe-fast-rcnn/blob/0dcd397b29507b8314e252e850518c5695efbb83/src/caffe/layers/roi_pooling_layer.cpp
)
|
| Axpy |
[
code
](
https://github.com/hujie-frank/SENet/blob/master/src/caffe/layers/axpy_layer.cpp
)
|
| ReLU6 |
[
code
](
https://github.com/chuanqi305/ssd/blob/ssd/src/caffe/layers/relu6_layer.cpp
)
|
| Upsample |
[
code
](
https://github.com/eric612/MobileNet-YOLO/blob/master/src/caffe/layers/upsample_layer.cpp
)
|
op_list.md
→
docs/introduction/
op_list.md
浏览文件 @
f729a29c
...
...
@@ -24,7 +24,11 @@
| 57 | Sqrt | 58 | Softplus | 59 | Erf | 60 | AddV2 |
| 61 | LessEqual | 62 | BatchMatMul | 63 | BatchMatMulV2 | 64 | ExpandDims |
| 65 | BatchToSpaceND | 66 | SpaceToBatchND | 67 | OneHot | 68 | Pow |
| 69 | All | 70 | GatherV2 | 71 | IteratorV2 | | |
| 69 | All | 70 | GatherV2 | 71 | IteratorV2 | 72 | Neg |
| 73 | Greater | 74 | FloorMod | 75 | LogicalAdd | 76 | Prod |
| 77 | Equal | 78 | Conv3D | 79 | Ceil | 80 | AddN |
| 81 | DivNoNan | 82 | Where | 83 | MirrorPad | 84 | Size |
| 85 | TopKv2 | | | | | | |
## Caffe
...
...
@@ -58,3 +62,44 @@
| 45 | Squeeze | 46 | Equal | 47 | Identity | 48 | GlobalAveragePool |
| 49 | MaxPool | 50 | Conv | 51 | Gemm | 52 | NonZero |
| 53 | Abs | 54 | Floor |
## PyTorch
Aten:
| 序号 | OP | 序号 | OP | 序号 | OP | 序号 | OP |
|------|------|------|------|------|------|------|------|
| 1 | aten::abs | 2 | aten::adaptive_avg_pool2d | 3 | aten::addmm | 4 | aten::add |
| 5 | aten::add
\_
| 6 | aten::
\_\_
and
\_\_
| 7 | aten::append | 8 | aten::arange |
| 9 | aten::avg
\_
pool2d | 10 | aten::avg
\_
pool3d | 11 | aten::avg_pool1d | 12 | aten::batch_norm |
| 13 | aten::cat | 14 | aten::chunk | 15 | aten::clamp | 16 | aten::
\_\_
contains
\_\_
|
| 17 | aten::constant
\_
pad
\_
nd | 18 | aten::contiguous | 19 | aten::conv2d | 20 | aten::
\_
convolution |
| 21 | aten::conv_transpose2d | 22 | aten::cos | 23 | aten::cumsum | 24 | aten::detach |
| 25 | aten::dict | 26 | aten::dim | 27 | aten::div
\_
| 28 | aten::div |
| 29 | aten::dropout | 30 | aten::dropout_ | 31 | aten::embedding | 32 | aten::eq |
| 33 | aten::exp | 34 | aten::expand | 35 | aten::expand_as | 36 | aten::eye |
| 37 | aten::feature_dropout | 38 | aten::flatten | 39 | aten::Float | 40 | aten::floor |
| 41 | aten::floordiv | 42 | aten::floor_divide | 43 | aten::full_like | 44 | aten::gather |
| 45 | aten::gelu | 46 | aten::
\_\_
getitem
\_\_
| 47 | aten::gt | 48 | aten::hardtanh
\_
|
| 49 | aten::index
\_
select | 50 | aten::Int | 51 | aten::
\_\_
is
\_\_
| 52 | aten::
\_\_
isnot
\_\_
|
| 53 | aten::layer
\_
norm | 54 | aten::le |55|aten::leaky
\_
relu
\_
|56|aten::len|
| 57 | aten::log | 58 | aten::lt |59|aten::masked
\_
fil
\l
_|60|aten::masked
\_
fill|
| 61 | aten::max | 62 | aten::max
\_
pool2d |63|aten::matmul|64|aten
\_
min|
| 65 | aten::mean | 66 | aten::meshgrid |67|aten::mul|68|aten::mul
\_
|
| 69 | aten::ne | 70 | aten::neg |71|aten::
\_\_
not
\_\_
|72|aten::ones|
| 73 | aten::permute | 74 | aten::pow |75|aten::relu|76|aten::relu
\_
|
| 77 | aten::relu6 | 78 | aten::repeat |79|aten::reshape|80|aten::rsub|
| 81 | aten::ScalarImplicit | 82 | aten::select |83|aten::
\_
set
\_
item|84|aten::sigmoid|
| 85 | aten::sin | 86 | aten::size |87|aten::slice|88|aten::softmax|
| 89 | aten::softplus | 90 | aten::sqrt |91|aten::squeeze|92|aten::stack|
| 93 | aten::sub | 94 | aten::t |95|aten::tanh|96|aten::split|
| 97 | aten::transpose | 98 | aten::to |99|aten::type
\_
as|100|aten::unsqueeze|
| 101 | aten::upsample
\_
bilinear2d | 102 | aten::values |103|aten::view|104|aten::warn|
| 105 | aten::where | 106 | aten::zeros |107|aten::zeros
\_
like|||
Prim:
| 序号 | OP | 序号 | OP | 序号 | OP | 序号 | OP |
|------|------|------|------|------|------|------|------|
| 1 | prim::Constant | 2 | prim::data | 3 | prim::DictConstruct | 4 | prim::GetAttr |
| 5 | prim::If | 6 | prim::ListConstruct | 7 | prim::ListUnpack | 8 | prim::Loop |
| 9 | prim::min | 10 | prim::NumToTensor | 11 | prim::RaiseException | 12 | prim::requires
\_
grad |
| 13 | prim::SetAttr | 14 | prim::shape | 15 | prim::TupleConstruct | 16 | prim::TupleUnpack |
| 17 | prim::unchecked
\_
cast | 18 | prim::Uninitialized | ||||
x2paddle_model_zoo.md
→
docs/introduction/
x2paddle_model_zoo.md
浏览文件 @
f729a29c
...
...
@@ -74,3 +74,25 @@
|Ultra-Light-Fast-Generic-Face-Detector-1MB|
[
onnx_model
](
https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB/tree/master/models/onnx
)
|9 |
|BERT|
[
pytorch(huggingface)
](
https://github.com/huggingface/transformers/blob/master/notebooks/04-onnx-export.ipynb
)
|11|转换时需指定input shape,见
[
文档Q3
](
FAQ.md
)
|
|GPT2|
[
pytorch(huggingface)
](
https://github.com/huggingface/transformers/blob/master/notebooks/04-onnx-export.ipynb
)
|11|转换时需指定input shape,见
[
文档Q3
](
FAQ.md
)
|
## PyTorch
| 模型 | 代码 | 备注 |
|------|----------|------|
| AlexNet |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/alexnet.py
)
|-|
| MNasNet |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/mnasnet.py
)
|-|
| MobileNetV2 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/mobilenet.py
)
|-|
| ResNet18 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py
)
|-|
| ShuffleNetV2 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/shufflenet.py
)
|-|
| SqueezeNet |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/squeezenet.py
)
|-|
| VGG16 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py
)
|-|
| InceptionV3 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/inception.py
)
|-|
| DeepLabv3_ResNet50 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/segmentation/deeplabv3.py
)
|-|
| FCN_ResNet50 |
[
code
](
https://github.com/pytorch/vision/blob/master/torchvision/models/segmentation/fcn.py
)
|-|
| CamembertForQuestionAnswering |
[
code
](
https://huggingface.co/transformers/model_doc/camembert.html
)
|只支持trace模式|
| DPRContextEncoder |
[
code
](
https://huggingface.co/transformers/model_doc/dpr.html
)
|只支持trace模式|
| ElectraModel |
[
code
](
https://huggingface.co/transformers/model_doc/electra.html
)
|只支持trace模式|
| FlaubertModel |
[
code
](
https://huggingface.co/transformers/model_doc/flaubert.html
)
|只支持trace模式|
| Roberta|
[
code
](
https://huggingface.co/transformers/model_doc/roberta.html
)
|只支持trace模式|
| XLMRobertaForTokenClassification|
[
code
](
https://huggingface.co/transformers/model_doc/xlmroberta.html
)
|只支持trace模式|
FAQ.md
→
docs/user_guides/
FAQ.md
浏览文件 @
f729a29c
...
...
@@ -23,3 +23,20 @@ A: 此提示为错误信息,表示该模型的转换需要固定的输入大
> 1. 模型来源于PaddleX导出,可以在导出的命令中,指定--fixed_input_shape=[Height,Width],详情可见:[PaddleX模型导出文档](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/deploy/export_model.md)。
> 2. 模型来源于PaddleDetection导出,可以在导出模型的时候,指定 TestReader.inputs_def.image_shape=[Channel,Height,Width], 详情可见:[PaddleDetection模型导出文档](https://github.com/PaddlePaddle/PaddleDetection/blob/master/docs/advanced_tutorials/deploy/EXPORT_MODEL.md#设置导出模型的输入大小)。
> 3. 模型来源于自己构建,可在网络构建的`fluid.data(shape=[])`中,指定shape参数来固定模型的输入大小。
**Q6. 进行动态图转换时,提示『Fail to generate inference model! Problem happend while export inference model from python code...』**
A: 此提示为无法将动态图代码转换为静态图模型,有两种可能:
> 使用动态图代码确认转换后的代码是否正确,可使用如下代码进行确认:
```
import paddle
import numpy as np
np.random.seed(6)
# ipt为输入数据
ipt = np.random.rand(1, 3, 224, 224).astype("float32")
paddle.disable_static()
# pd_model_dygraph为保存路径(其中的”/“用”.“替换)
from pd_model_dygraph.x2paddle_code import main
out =main(ipt)
```
> 若运行代码无误,则说明代码中有op不支持动转静,我们将会再未来支持;若报错,则说明pytorch2paddle转换出错,请提issue,我们将及时回复。
\ No newline at end of file
docs/user_guides/add_caffe_custom_layer.md
0 → 100644
浏览文件 @
f729a29c
## 如何转换Caffe自定义Layer
本文档介绍如何将Caffe自定义Layer转换为PaddlePaddle模型中的对应实现, 用户可根据自己需要,添加代码实现自定义层,从而支持模型的完整转换。
目前,代码中已经提供了10个非官方op(不在
[
官网
](
http://caffe.berkeleyvision.org/tutorial/layers
)
上的op)的转换,这些op对应的Caffe实现源码如下:
| op | 该版本实现源码 |
|-------|--------|
| PriorBox |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/prior_box_layer.cpp
)
|
| DetectionOutput |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/detection_output_layer.cpp
)
|
| ConvolutionDepthwise |
[
code
](
https://github.com/farmingyard/caffe-mobilenet/blob/master/conv_dw_layer.cpp
)
|
| ShuffleChannel |
[
code
](
https://github.com/farmingyard/ShuffleNet/blob/master/shuffle_channel_layer.cpp
)
|
| Permute |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/permute_layer.cpp
)
|
| Normalize |
[
code
](
https://github.com/weiliu89/caffe/blob/ssd/src/caffe/layers/normalize_layer.cpp
)
|
| ROIPooling |
[
code
](
https://github.com/rbgirshick/caffe-fast-rcnn/blob/0dcd397b29507b8314e252e850518c5695efbb83/src/caffe/layers/roi_pooling_layer.cpp
)
|
| Axpy |
[
code
](
https://github.com/hujie-frank/SENet/blob/master/src/caffe/layers/axpy_layer.cpp
)
|
| ReLU6 |
[
code
](
https://github.com/chuanqi305/ssd/blob/ssd/src/caffe/layers/relu6_layer.cpp
)
|
| Upsample |
[
code
](
https://github.com/eric612/MobileNet-YOLO/blob/master/src/caffe/layers/upsample_layer.cpp
)
|
添加代码实现自定义层的步骤如下:
***步骤一 下载代码**
*
此处涉及修改源码,应先卸载x2paddle,并且下载源码,主要有以下两步完成:
```
pip uninstall x2paddle
pip install git+https://github.com/PaddlePaddle/X2Paddle.git@develop
```
***步骤二 编译caffe.proto**
*
该步骤依赖protobuf编译器,其安装过程有以下两种方式:
> 选择一:pip install protobuf (protobuf >= 3.6.0)
> 选择二:使用[官方源码](https://github.com/protocolbuffers/protobuf)进行编译
使用脚本./tools/compile.sh将caffe.proto(包含所需的自定义Layer信息)编译成我们所需的目标语言(Python)
使用方式:
```
bash ./toos/compile.sh /home/root/caffe/src/caffe/proto
# /home/root/caffe/src/caffe/proto为caffe.proto的存放路径,生成的caffe_pb2.py也将保存在该路径下
```
***步骤三 添加自定义Layer的实现代码**
*
**静态图方式:**
-
进入./x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer,创建.py文件,例如mylayer.py
-
仿照./x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer中的其他文件,在mylayer.py中主要需要实现3个函数,下面以roipooling.py为例分析代码:
1.
`def roipooling_shape(input_shape, pooled_w=None, pooled_h=None)`
参数:
1.
input_shape(list):其中每个元素代表该层每个输入数据的shape,为必须传入的参数
2.
pooled_w(int):代表ROI Pooling的kernel的宽,其命名与.prototxt中roi_pooling_param中的key一致
3.
pooled_h(int):代表ROI Pooling的kernel的高,其命名与.prototxt中roi_pooling_param中的key一致
功能:计算出进行ROI Pooling后的shape
返回:一个list,其中每个元素代表每个输出数据的shape,由于ROI Pooling的输出数据只有一个,所以其list长度为1
2.
`def roipooling_layer(inputs, input_shape=None, name=None, pooled_w=None, pooled_h=None, spatial_scale=None)`
参数:
1. inputs(list):其中每个元素代表该层每个输入数据,为必须传入的参数
2. input_shape(list):其中每个元素代表该层每个输入数据的shape,为必须传入的参数
3. name(str):ROI Pooling层的名字,为必须传入的参数
4. pooled_w(int):代表ROI Pooling的kernel的宽,其命名与.prototxt中roi_pooling_param中的key一致
5. pooled_h(int):代表ROI Pooling的kernel的高,其命名与.prototxt中roi_pooling_param中的key一致
6. spatial_scale(float):用于将ROI坐标从输入比例转换为池化时使用的比例,其命名与.prototxt中roi_pooling_param中的key一致
功能:运用PaddlePaddle完成组网来实现`roipooling_layer`的功能
返回:一个Variable,为组网后的结果
3.
`def roipooling_weights(name, data=None)`
参数:
1. name(str):ROI Pooling层的名字,为必须传入的参数
2. data(list):由Caffe模型.caffemodel获得的关于roipooling的参数,roipooling的参数为None
功能:为每个参数(例如kernel、bias等)命名;同时,若Caffe中该层参数与PaddlePaddle中参数的格式不一致,则变换操作也在该函数中实现。
返回:一个list,包含每个参数的名字。
-
在roipooling.py中注册
`roipooling`
,主要运用下述代码实现:
```
register(kind='ROIPooling', shape=roipooling_shape, layer=roipooling_layer, weights=roipooling_weights)
# kind为在model.prototxt中roipooling的type
```
-
在./x2paddle/op_mapper/caffe_custom_layer/
\_\_
init
\_\_
.py中引入该层的使用
```
from . import roipooling
```
**动态图方式:**
> 【注意】若Caffe自定义layer与Paddle的op一一对应,使用方式一,否则使用方式二。
-
方式一:
1.
仿照./x2paddle/op_mapper/dygraph/caffe2paddle/caffe_op_mapper.py中的CaffeOpMapper类中的映射方法(输入为self和node),实现类似的映射方法,以下述的映射方法为例:
```
python
def
Permute
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of Permute node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
permute_param
order
=
list
(
params
.
order
)
self
.
paddle_graph
.
add_layer
(
"paddle.transpose"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
layer_name
],
perm
=
order
)
```
>需完成的步骤:
> a. 获取Caffe Layer的属性,并对应转换为Paddle的属性。
> b. 获取当前Layer的输入。
> c. 使用self.paddle_graph.add_layer为PaddleGraph添加layer。其中,第一个参数代表Paddle的kernel;inputs是一个字典,用于存储paddle中的输入的key与其输入名字;outputs是一个列表,用于存储输出的名字;其余参数为属性对应关系。
2.
仿照./x2paddle/decoder/caffe_shape_inference.py中的shape_xx方法,实现获取当前Layer输出大小的函数,以下述方法为例:
```
python
def
shape_permute
(
layer
,
input_shape
):
order
=
layer
.
permute_param
.
order
inshape
=
input_shape
[
0
]
output_shape
=
[]
order
=
list
(
order
)
for
ii
in
order
:
assert
ii
<
len
(
inshape
),
"invalid order for permute[%s]"
%
(
name
)
output_shape
.
append
(
inshape
[
ii
])
return
[
output_shape
]
```
>参数:
> layer (caffe_pb2.LayerParameter): caffe的Layer,可用于获取当前Layer的属性。
> input_shape (list): 其中每个元素代表该层每个输入数据的大小。
-
方式二:
1.
进入./x2paddle/op_mapper/dygraph/caffe2paddle/caffe_custom_layer,创建.py文件,例如mylayer.py
2.
仿照./x2paddle/op_mapper/dygraph/caffe2paddle/caffe_custom_layer中的其他文件,在mylayer.py中主要需要实现1个类,下面以roipooling.py为例分析代码:
```
python
class
ROIPooling
(
object
):
def
__init__
(
self
,
pooled_height
,
pooled_width
,
spatial_scale
):
self
.
roipooling_layer_attrs
=
{
"pooled_height"
:
pooled_height
,
"pooled_width"
:
pooled_width
,
"spatial_scale"
:
spatial_scale
}
def
__call__
(
self
,
x0
,
x1
):
slice_x1
=
paddle
.
slice
(
input
=
x1
,
axes
=
[
1
],
starts
=
[
1
],
ends
=
[
5
])
out
=
fluid
.
layers
.
roi_pool
(
input
=
x0
,
rois
=
slice_x1
,
**
self
.
roipooling_layer_attrs
)
return
out
```
>\_\_init\_\_函数:用于初始化各个属性
>\_\_call\_\_函数:用于组合实现当前Layer的前向,输入为当前Layer所需要的输入
3.
仿照./x2paddle/op_mapper/dygraph/caffe2paddle/caffe_op_mapper.py中的CaffeOpMapper类中的映射方法(输入为self和node),实现类似的映射方法,以下述的映射方法为例:
```
python
def
ROIPooling
(
self
,
node
):
roipooling_name
=
name_generator
(
"roipooling"
,
self
.
nn_name2id
)
output_name
=
node
.
layer_name
layer_outputs
=
[
roipooling_name
,
output_name
]
assert
len
(
node
.
inputs
)
==
2
,
"The count of ROIPooling node
\'
s input is not 2."
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
inputs_dict
=
{}
inputs_dict
[
"x0"
]
=
input0
.
name
inputs_dict
[
"x1"
]
=
input1
.
name
params
=
node
.
layer
.
roi_pooling_param
layer_attrs
=
{
"pooled_height"
:
params
.
pooled_h
,
"pooled_width"
:
params
.
pooled_w
,
"spatial_scale"
:
params
.
spatial_scale
}
self
.
paddle_graph
.
add_layer
(
"custom_layer:ROIPooling"
,
inputs
=
inputs_dict
,
outputs
=
layer_outputs
,
**
layer_attrs
)
```
>需完成的步骤:
> a. 获取Caffe Layer的属性,并对应转换为Paddle的属性。
> b. 获取当前Layer的输入。
> c. 使用self.paddle_graph.add_layer为PaddleGraph添加layer。其中,第一个参数代表Paddle的kernel(此处kernel必须以“custom_layer:“开头);inputs是一个字典,用于存储paddle中的输入的key与其输入名字;outputs是一个列表,用于存储输出的名字;其余参数为属性对应关系。
4.
仿照./x2paddle/decoder/caffe_shape_inference.py中的shape_xx方法,实现获取当前Layer输出大小的函数,以下述方法为例:
```
python
def
shape_roipooling
(
layer
,
input_shape
):
pooled_w
=
layer
.
roi_pooling_param
.
pooled_w
pooled_h
=
layer
.
roi_pooling_param
.
pooled_h
base_fea_shape
=
input_shapes
[
0
]
rois_shape
=
input_shapes
[
1
]
output_shape
=
base_fea_shape
output_shape
[
0
]
=
rois_shape
[
0
]
output_shape
[
2
]
=
pooled_h
output_shape
[
3
]
=
pooled_w
return
[
output_shape
]
```
>参数:
> layer (caffe_pb2.LayerParameter): caffe的Layer,可用于获取当前Layer的属性。
> input_shape (list): 其中每个元素代表该层每个输入数据的大小。
***步骤四 运行转换代码**
*
```
# 在X2Paddle目录下安装x2paddle
python setup.py install
# 运行转换代码
x2paddle --framework=caffe
--prototxt=deploy.proto
--weight=deploy.caffemodel
--save_dir=pd_model
--caffe_proto=/home/root/caffe/src/caffe/proto/caffe_pb2.py
```
export_tf_model.md
→
docs/user_guides/
export_tf_model.md
浏览文件 @
f729a29c
## 如何导出TensorFlow模型
本文档介绍如何将TensorFlow模型导出为X2Paddle支持的模型格式。
TensorFlow目前一般分为3种保存格式(checkpoint、FrozenModel、SavedModel),X2Paddle支持的是FrozenModel(将网络参数和网络结构同时保存到同一个文件中,并且只保存指定的前向计算子图),下面示例展示了如何导出X2Paddle支持的模型格式。
TensorFlow提供了接口可将网络参数和网络结构同时保存到同一个文件中,并且只保存指定的前向计算子图,下面示例展示了如何导出tensorflow/models下的VGG16模型
***下列代码Tensorflow 1.X下使用**
*
-
checkpoint模型+代码
步骤一 下载模型参数文件
```
wget http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz
...
...
@@ -42,3 +43,70 @@ load_model(sess)
# 导出模型
freeze_model(sess, ["vgg_16/fc8/squeezed"], "vgg16.pb")
```
-
纯checkpoint模型
文件结构:
> |--- checkpoint
> |--- model.ckpt-240000.data-00000-of-00001
> |--- model.ckpt-240000.index
> |--- model.ckpt-240000.meta
加载和导出模型:
```
python
#coding: utf-8
from
tensorflow.python.framework
import
graph_util
import
tensorflow
as
tf
# 固化模型函数
# output_tensor_names: list,指定模型的输出tensor的name
# freeze_model_path: 模型导出的文件路径
def
freeze_model
(
sess
,
output_tensor_names
,
freeze_model_path
):
out_graph
=
graph_util
.
convert_variables_to_constants
(
sess
,
sess
.
graph
.
as_graph_def
(),
output_tensor_names
)
with
tf
.
gfile
.
GFile
(
freeze_model_path
,
'wb'
)
as
f
:
f
.
write
(
out_graph
.
SerializeToString
())
print
(
"freeze model saved in {}"
.
format
(
freeze_model_path
))
# 加载模型参数
# 此处需要修改input_checkpoint(checkpoint的前缀)和save_pb_file(模型导出的文件路径)
input_checkpoint
=
"./tfhub_models/save/model.ckpt"
save_pb_file
=
"./tfhub_models/save.pb"
sess
=
tf
.
Session
()
saver
=
tf
.
train
.
import_meta_graph
(
input_checkpoint
+
'.meta'
,
clear_devices
=
True
)
saver
.
restore
(
sess
,
input_checkpoint
)
# 此处需要修改freeze_model的第二个参数,指定模型的输出tensor的name
freeze_model
(
sess
,
[
"vgg_16/fc8/squeezed"
],
save_pb_file
)
```
-
SavedModel模型
文件结构:
> |-- variables
> |------ variables.data-00000-of-00001
> |------ variables.data-00000-of-00001
> |-- saved_model.pb
加载和导出模型:
```
python
#coding: utf-8
import
tensorflow
as
tf
sess
=
tf
.
Session
(
graph
=
tf
.
Graph
())
# tf.saved_model.loader.load最后一个参数代表saved_model的保存路径
tf
.
saved_model
.
loader
.
load
(
sess
,
{},
"/mnt/saved_model"
)
graph
=
tf
.
get_default_graph
()
from
tensorflow.python.framework
import
graph_util
# 固化模型函数
# output_tensor_names: list,指定模型的输出tensor的name
# freeze_model_path: 模型导出的文件路径
def
freeze_model
(
sess
,
output_tensor_names
,
freeze_model_path
):
out_graph
=
graph_util
.
convert_variables_to_constants
(
sess
,
sess
.
graph
.
as_graph_def
(),
output_tensor_names
)
with
tf
.
gfile
.
GFile
(
freeze_model_path
,
'wb'
)
as
f
:
f
.
write
(
out_graph
.
SerializeToString
())
print
(
"freeze model saved in {}"
.
format
(
freeze_model_path
))
# 导出模型
freeze_model
(
sess
,
[
"logits"
],
"model.pb"
)
```
\ No newline at end of file
pytorch_to_
onnx.md
→
docs/user_guides/pytorch2
onnx.md
浏览文件 @
f729a29c
文件已移动
pytorch2paddle.md
→
docs/user_guides/
pytorch2paddle.md
浏览文件 @
f729a29c
...
...
@@ -46,7 +46,7 @@ torch_module.load_state_dict(torch_state_dict)
torch_module
.
eval
()
# 进行转换
from
x2paddle.convert
import
pytorch2paddle
pytorch2paddle
(
torch_mod
el
,
pytorch2paddle
(
torch_mod
ule
,
save_dir
=
"pd_model_trace"
,
jit_type
=
"trace"
,
input_examples
=
[
torch
.
tensor
(
input_data
)])
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录