未验证 提交 6c07aac7 编写于 作者: S SunAhong1993 提交者: GitHub

去除Static部分代码 (#600)

* fix the code

* fix the visit_tuple

* Update stargan.md

* Update ultra_light_fast_generic_face_detector.md

* fix the docs

* remove static

* fix

* fix

* fix

* fix the docs
Co-authored-by: Nchanningss <chen_lingchi@163.com>
上级 8f3f7c16
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
该文档梳理了计算loss相关的PyTorch-PaddlePaddle API映射列表。 该文档梳理了计算loss相关的PyTorch-PaddlePaddle API映射列表。
| 序号 | PyTorch API | PaddlePaddle API | 备注 | | 序号 | PyTorch API | PaddlePaddle API | 备注 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1 | [torch.nn.L1Loss](https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html?highlight=l1loss#torch.nn.L1Loss) | [paddle.nn.loss.L1Loss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/L1Loss_cn.html#l1loss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 | | 1 | [torch.nn.L1Loss](https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html?highlight=l1loss#torch.nn.L1Loss) | [paddle.nn.L1Loss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/loss/L1Loss_cn.html#l1loss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 |
| 2 | [torch.nn.MSELoss](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html?highlight=mseloss#torch.nn.MSELoss) | [paddle.nn.MSELoss](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html?highlight=mseloss#torch.nn.MSELoss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 | | 2 | [torch.nn.MSELoss](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html?highlight=mseloss#torch.nn.MSELoss) | [paddle.nn.MSELoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MSELoss_cn.html#mseloss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 |
| 3 | [torch.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/CrossEntropyLoss_cn.html#crossentropyloss) | [paddle.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/CrossEntropyLoss_cn.html#crossentropyloss) | [差异对比](torch.nn.CrossEntropyLoss.md) | | 3 | [torch.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/CrossEntropyLoss_cn.html#crossentropyloss) | [paddle.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/CrossEntropyLoss_cn.html#crossentropyloss) | [差异对比](torch.nn.CrossEntropyLoss.md) |
| 4 | [torch.nn.KLDivLoss](https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html?highlight=kldivloss#torch.nn.KLDivLoss) | [paddle.nn.KLDivLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/KLDivLoss_cn.html) | [差异对比](torch.nn.KLDivLoss.md) | | 4 | [torch.nn.KLDivLoss](https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html?highlight=kldivloss#torch.nn.KLDivLoss) | [paddle.nn.KLDivLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/KLDivLoss_cn.html#kldivloss) | [差异对比](torch.nn.KLDivLoss.md) |
| 5 | [torch.nn.BCELoss](https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html?highlight=bceloss#torch.nn.BCELoss) | [paddle.nn.BCELoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/BCELoss_cn.html#bceloss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 | | 5 | [torch.nn.BCELoss](https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html?highlight=bceloss#torch.nn.BCELoss) | [paddle.nn.BCELoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BCELoss_cn.html#bceloss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 |
| 6 | [torch.nn.BCEWithLogitsLoss](https://pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html?highlight=bcewithlogitsloss#torch.nn.BCEWithLogitsLoss) | [paddle.nn.BCEWithLogitsLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/BCEWithLogitsLoss_cn.html#bcewithlogitsloss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 | | 6 | [torch.nn.BCEWithLogitsLoss](https://pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html?highlight=bcewithlogitsloss#torch.nn.BCEWithLogitsLoss) | [paddle.nn.BCEWithLogitsLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BCEWithLogitsLoss_cn.html#bcewithlogitsloss) | 功能一致,PyTroch存在废弃参数`size_average``reduce`。 |
| 7 | [torch.nn.SmoothL1Loss](https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html?highlight=torch%20nn%20smoothl1loss#torch.nn.SmoothL1Loss) | [paddle.nn.SmoothL1Loss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/SmoothL1Loss_cn.html#smoothl1loss) | 功能一致,参数名不一致,PyTroch存在废弃参数`size_average``reduce`。 | | 7 | [torch.nn.SmoothL1Loss](https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html?highlight=torch%20nn%20smoothl1loss#torch.nn.SmoothL1Loss) | [paddle.nn.SmoothL1Loss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/SmoothL1Loss_cn.html#smoothl1loss) | 功能一致,参数名不一致,PyTroch存在废弃参数`size_average``reduce`。 |
***持续更新...*** ***持续更新...***
...@@ -7,7 +7,7 @@ torch.nn.CrossEntropyLoss(weight=None, ...@@ -7,7 +7,7 @@ torch.nn.CrossEntropyLoss(weight=None,
reduce=None, reduce=None,
reduction='mean') reduction='mean')
``` ```
### [paddle.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/CrossEntropyLoss_cn.html#crossentropyloss) ### [paddle.nn.CrossEntropyLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/CrossEntropyLoss_cn.html#crossentropyloss)
```python ```python
paddle.nn.CrossEntropyLoss(weight=None, paddle.nn.CrossEntropyLoss(weight=None,
ignore_index=-100, ignore_index=-100,
......
...@@ -7,7 +7,7 @@ torch.nn.KLDivLoss(size_average=None, ...@@ -7,7 +7,7 @@ torch.nn.KLDivLoss(size_average=None,
log_target=False) log_target=False)
``` ```
### [paddle.nn.KLDivLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/loss/KLDivLoss_cn.html) ### [paddle.nn.KLDivLoss](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/KLDivLoss_cn.html#kldivloss)
```python ```python
paddle.nn.KLDivLoss(reduction='mean') paddle.nn.KLDivLoss(reduction='mean')
``` ```
......
...@@ -4,52 +4,52 @@ ...@@ -4,52 +4,52 @@
| 序号 | PyTorch API | PaddlePaddle API | 备注 | | 序号 | PyTorch API | PaddlePaddle API | 备注 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1 | [torch.nn.Conv1d](https://pytorch.org/docs/stable/generated/torch.nn.Conv1d.html?highlight=torch%20nn%20conv1d#torch.nn.Conv1d) | [paddle.nn.Conv1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv1D_cn.html#conv1d) | [差异对比](torch.nn.Conv1d.md) | | 1 | [torch.nn.Conv1d](https://pytorch.org/docs/stable/generated/torch.nn.Conv1d.html?highlight=torch%20nn%20conv1d#torch.nn.Conv1d) | [paddle.nn.Conv1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv1D_cn.html#conv1d) | [差异对比](torch.nn.Conv1d.md) |
| 2 | [torch.nn.Conv2d](https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html?highlight=conv2d#torch.nn.Conv2d) | [paddle.nn.Conv2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv2D_cn.html#conv2d) | [差异对比](torch.nn.Conv2d.md) | | 2 | [torch.nn.Conv2d](https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html?highlight=conv2d#torch.nn.Conv2d) | [paddle.nn.Conv2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv2D_cn.html#conv2d) | [差异对比](torch.nn.Conv2d.md) |
| 3 | [torch.nn.Conv3d](https://pytorch.org/docs/stable/generated/torch.nn.Conv3d.html?highlight=conv3d#torch.nn.Conv3d) | [paddle.nn.Conv3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv3D_cn.html#conv3d) | [差异对比](torch.nn.Conv3d.md) | | 3 | [torch.nn.Conv3d](https://pytorch.org/docs/stable/generated/torch.nn.Conv3d.html?highlight=conv3d#torch.nn.Conv3d) | [paddle.nn.Conv3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv3D_cn.html#conv3d) | [差异对比](torch.nn.Conv3d.md) |
| 4 | [torch.nn.ConvTranspose1d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose1d.html?highlight=torch%20nn%20convtranspose1d#torch.nn.ConvTranspose1d) | [paddle.nn.Conv1DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv1DTranspose_cn.html#conv1dtranspose) | [差异对比](torch.nn.ConvTranspose1d.md) | | 4 | [torch.nn.ConvTranspose1d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose1d.html?highlight=torch%20nn%20convtranspose1d#torch.nn.ConvTranspose1d) | [paddle.nn.Conv1DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv1DTranspose_cn.html#conv1dtranspose) | [差异对比](torch.nn.ConvTranspose1d.md) |
| 5 | [torch.nn.ConvTranspose2d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html?highlight=convtranspose2d#torch.nn.ConvTranspose2d) | [paddle.nn.Conv2DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv2DTranspose_cn.html#conv2dtranspose) | [差异对比](torch.nn.ConvTranspose2d.md) | | 5 | [torch.nn.ConvTranspose2d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html?highlight=convtranspose2d#torch.nn.ConvTranspose2d) | [paddle.nn.Conv2DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv2DTranspose_cn.html#conv2dtranspose) | [差异对比](torch.nn.ConvTranspose2d.md) |
| 6 | [torch.nn.ConvTranspose3d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose3d.html?highlight=convtranspose3d#torch.nn.ConvTranspose3d) | [paddle.nn.Conv3DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv3DTranspose_cn.html#conv3dtranspose) | [差异对比](torch.nn.ConvTranspose3d.md) | | 6 | [torch.nn.ConvTranspose3d](https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose3d.html?highlight=convtranspose3d#torch.nn.ConvTranspose3d) | [paddle.nn.Conv3DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv3DTranspose_cn.html#conv3dtranspose) | [差异对比](torch.nn.ConvTranspose3d.md) |
| 7 | [torch.nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html?highlight=linear#torch.nn.Linear) | [paddle.nn.Linear](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Linear_cn.html#linear) | [差异对比](torch.nn.Linear.md) | | 7 | [torch.nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html?highlight=linear#torch.nn.Linear) | [paddle.nn.Linear](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Linear_cn.html#linear) | [差异对比](torch.nn.Linear.md) |
| 8 | [torch.nn.MaxPool1d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool1d.html?highlight=maxpool1d#torch.nn.MaxPool1d) | [paddle.nn.MaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool1D_cn.html#maxpool1d) | [差异对比](torch.nn.MaxPool1d.md) | | 8 | [torch.nn.MaxPool1d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool1d.html?highlight=maxpool1d#torch.nn.MaxPool1d) | [paddle.nn.MaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool1D_cn.html#maxpool1d) | [差异对比](torch.nn.MaxPool1d.md) |
| 9 | [torch.nn.MaxPool2d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html?highlight=maxpool2d#torch.nn.MaxPool2d) | [paddle.nn.MaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool2D_cn.html#maxpool2d) | [差异对比](torch.nn.MaxPool2d.md) | | 9 | [torch.nn.MaxPool2d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html?highlight=maxpool2d#torch.nn.MaxPool2d) | [paddle.nn.MaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool2D_cn.html#maxpool2d) | [差异对比](torch.nn.MaxPool2d.md) |
| 10 | [torch.nn.MaxPool3d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool3d.html?highlight=maxpool3d#torch.nn.MaxPool3d) | [paddle.nn.MaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool3D_cn.html#maxpool3d) | [差异对比](torch.nn.MaxPool3d.md) | | 10 | [torch.nn.MaxPool3d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool3d.html?highlight=maxpool3d#torch.nn.MaxPool3d) | [paddle.nn.MaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool3D_cn.html#maxpool3d) | [差异对比](torch.nn.MaxPool3d.md) |
| 11 | [torch.nn.MaxUnpool1d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool1d.html?highlight=unpool#torch.nn.MaxUnpool1d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool1d.md) | | 11 | [torch.nn.MaxUnpool1d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool1d.html?highlight=unpool#torch.nn.MaxUnpool1d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool1d.md) |
| 12 | [torch.nn.MaxUnpool2d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool2d.html?highlight=unpool#torch.nn.MaxUnpool2d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool2d.md) | | 12 | [torch.nn.MaxUnpool2d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool2d.html?highlight=unpool#torch.nn.MaxUnpool2d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool2d.md) |
| 13 | [torch.nn.MaxUnpool3d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool3d.html?highlight=unpool#torch.nn.MaxUnpool3d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool3d.md) | | 13 | [torch.nn.MaxUnpool3d](https://pytorch.org/docs/stable/generated/torch.nn.MaxUnpool3d.html?highlight=unpool#torch.nn.MaxUnpool3d) | 无对应实现 | [组合实现](torch.nn.MaxUnpool3d.md) |
| 14 | [torch.nn.AvgPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool1d.html?highlight=avgpool1d#torch.nn.AvgPool1d) | [paddle.nn.AvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool1D_cn.html#avgpool1d) | [差异对比](torch.nn.AvgPool1d.md) | | 14 | [torch.nn.AvgPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool1d.html?highlight=avgpool1d#torch.nn.AvgPool1d) | [paddle.nn.AvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool1D_cn.html#avgpool1d) | [差异对比](torch.nn.AvgPool1d.md) |
| 15 | [torch.nn.AvgPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool2d.html?highlight=avgpool2d#torch.nn.AvgPool2d) | [paddle.nn.AvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool2D_cn.html#avgpool2d) | [差异对比](torch.nn.AvgPool2d.md) | | 15 | [torch.nn.AvgPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool2d.html?highlight=avgpool2d#torch.nn.AvgPool2d) | [paddle.nn.AvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool2D_cn.html#avgpool2d) | [差异对比](torch.nn.AvgPool2d.md) |
| 16 | [torch.nn.AvgPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool3d.html?highlight=avgpool3d#torch.nn.AvgPool3d) | [paddle.nn.AvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool3D_cn.html#avgpool3d) | [差异对比](torch.nn.AvgPool3d.md) | | 16 | [torch.nn.AvgPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AvgPool3d.html?highlight=avgpool3d#torch.nn.AvgPool3d) | [paddle.nn.AvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool3D_cn.html#avgpool3d) | [差异对比](torch.nn.AvgPool3d.md) |
| 17 | [torch.nn.AdaptiveMaxPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool1d.html?highlight=adaptivemaxpool1d#torch.nn.AdaptiveMaxPool1d) | [paddle.nn.AdaptiveMaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveMaxPool1D_cn.html#adaptivemaxpool1d) | 功能一致,参数名不一致 | | 17 | [torch.nn.AdaptiveMaxPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool1d.html?highlight=adaptivemaxpool1d#torch.nn.AdaptiveMaxPool1d) | [paddle.nn.AdaptiveMaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveMaxPool1D_cn.html#adaptivemaxpool1d) | 功能一致,参数名不一致 |
| 18 | [torch.nn.AdaptiveMaxPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool2d.html?highlight=adaptivemaxpool2d#torch.nn.AdaptiveMaxPool2d) | [paddle.nn.AdaptiveMaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveMaxPool2D_cn.html#adaptivemaxpool2d) | 功能一致,参数名不一致 | | 18 | [torch.nn.AdaptiveMaxPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool2d.html?highlight=adaptivemaxpool2d#torch.nn.AdaptiveMaxPool2d) | [paddle.nn.AdaptiveMaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveMaxPool2D_cn.html#adaptivemaxpool2d) | 功能一致,参数名不一致 |
| 19 | [torch.nn.AdaptiveMaxPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool3d.html?highlight=adaptivemaxpool3d#torch.nn.AdaptiveMaxPool3d) | [paddle.nn.AdaptiveMaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveMaxPool3D_cn.html#adaptivemaxpool3d) | 功能一致,参数名不一致 | | 19 | [torch.nn.AdaptiveMaxPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveMaxPool3d.html?highlight=adaptivemaxpool3d#torch.nn.AdaptiveMaxPool3d) | [paddle.nn.AdaptiveMaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveMaxPool3D_cn.html#adaptivemaxpool3d) | 功能一致,参数名不一致 |
| 20 | [torch.nn.AdaptiveAvgPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool1d.html?highlight=adaptiveavgpool1d#torch.nn.AdaptiveAvgPool1d) | [paddle.nn.AdaptiveAvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveAvgPool1D_cn.html#adaptiveavgpool1d) | 功能一致,参数名不一致 | | 20 | [torch.nn.AdaptiveAvgPool1d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool1d.html?highlight=adaptiveavgpool1d#torch.nn.AdaptiveAvgPool1d) | [paddle.nn.AdaptiveAvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveAvgPool1D_cn.html#adaptiveavgpool1d) | 功能一致,参数名不一致 |
| 21 | [torch.nn.AdaptiveAvgPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool2d.html?highlight=adaptiveavgpool2d#torch.nn.AdaptiveAvgPool2d) | [paddle.nn.AdaptiveAvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveAvgPool2D_cn.html#adaptiveavgpool2d) | 功能一致,参数名不一致 | | 21 | [torch.nn.AdaptiveAvgPool2d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool2d.html?highlight=adaptiveavgpool2d#torch.nn.AdaptiveAvgPool2d) | [paddle.nn.AdaptiveAvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveAvgPool2D_cn.html#adaptiveavgpool2d) | 功能一致,参数名不一致 |
| 22 | [torch.nn.AdaptiveAvgPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool3d.html?highlight=adaptiveavgpool3d#torch.nn.AdaptiveAvgPool3d) | [paddle.nn.AdaptiveAvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AdaptiveAvgPool3D_cn.html#adaptiveavgpool3d) | 功能一致,参数名不一致 | | 22 | [torch.nn.AdaptiveAvgPool3d](https://pytorch.org/docs/stable/generated/torch.nn.AdaptiveAvgPool3d.html?highlight=adaptiveavgpool3d#torch.nn.AdaptiveAvgPool3d) | [paddle.nn.AdaptiveAvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AdaptiveAvgPool3D_cn.html#adaptiveavgpool3d) | 功能一致,参数名不一致 |
| 23 | [torch.nn.ConstantPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad1d.html?highlight=pad#torch.nn.ConstantPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ConstantPad1d.md) | | 23 | [torch.nn.ConstantPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad1d.html?highlight=pad#torch.nn.ConstantPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ConstantPad1d.md) |
| 24 | [torch.nn.ConstantPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad2d.html?highlight=pad#torch.nn.ConstantPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ConstantPad2d.md) | | 24 | [torch.nn.ConstantPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad2d.html?highlight=pad#torch.nn.ConstantPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ConstantPad2d.md) |
| 25 | [torch.nn.ConstantPad3d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad3d.html?highlight=pad#torch.nn.ConstantPad3d) | [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad3D_cn.html#pad3d) | [差异对比](torch.nn.ConstantPad3d.md) | | 25 | [torch.nn.ConstantPad3d](https://pytorch.org/docs/stable/generated/torch.nn.ConstantPad3d.html?highlight=pad#torch.nn.ConstantPad3d) | [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad3D_cn.html#pad3d) | [差异对比](torch.nn.ConstantPad3d.md) |
| 26 | [torch.nn.ReflectionPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ReflectionPad1d.html?highlight=pad#torch.nn.ReflectionPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ReflectionPad1d.md) | | 26 | [torch.nn.ReflectionPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ReflectionPad1d.html?highlight=pad#torch.nn.ReflectionPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ReflectionPad1d.md) |
| 27 | [torch.nn.ReflectionPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ReflectionPad2d.html?highlight=pad#torch.nn.ReflectionPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ReflectionPad2d.md) | | 27 | [torch.nn.ReflectionPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ReflectionPad2d.html?highlight=pad#torch.nn.ReflectionPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ReflectionPad2d.md) |
| 28 | [torch.nn.ReplicationPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad1d.html?highlight=pad#torch.nn.ReplicationPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ReplicationPad1d.md) | | 28 | [torch.nn.ReplicationPad1d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad1d.html?highlight=pad#torch.nn.ReplicationPad1d) | [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d) | [差异对比](torch.nn.ReplicationPad1d.md) |
| 29 | [torch.nn.ReplicationPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad2d.html?highlight=pad#torch.nn.ReplicationPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ReplicationPad2d.md) | | 29 | [torch.nn.ReplicationPad2d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad2d.html?highlight=pad#torch.nn.ReplicationPad2d) | [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d) | [差异对比](torch.nn.ReplicationPad2d.md) |
| 30 | [torch.nn.ReplicationPad3d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad3d.html?highlight=pad#torch.nn.ReplicationPad3d) | [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad3D_cn.html#pad3d) | [差异对比](torch.nn.ReplicationPad3d.md) | | 30 | [torch.nn.ReplicationPad3d](https://pytorch.org/docs/stable/generated/torch.nn.ReplicationPad3d.html?highlight=pad#torch.nn.ReplicationPad3d) | [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad3D_cn.html#pad3d) | [差异对比](torch.nn.ReplicationPad3d.md) |
| 31 | [torch.nn.BatchNorm1d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm1d.html?highlight=torch%20nn%20batchnorm1d#torch.nn.BatchNorm1d) | [paddle.nn.BatchNorm1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm1D_cn.html#batchnorm1d) | [差异对比](torch.nn.BatchNorm1d.md) | | 31 | [torch.nn.BatchNorm1d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm1d.html?highlight=torch%20nn%20batchnorm1d#torch.nn.BatchNorm1d) | [paddle.nn.BatchNorm1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm1D_cn.html#batchnorm1d) | [差异对比](torch.nn.BatchNorm1d.md) |
| 32 | [torch.nn.BatchNorm2d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html?highlight=batchnorm2d#torch.nn.BatchNorm2d) | [paddle.nn.BatchNorm2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm2D_cn.html#batchnorm2d) | [差异对比](torch.nn.BatchNorm2d.md) | | 32 | [torch.nn.BatchNorm2d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html?highlight=batchnorm2d#torch.nn.BatchNorm2d) | [paddle.nn.BatchNorm2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm2D_cn.html#batchnorm2d) | [差异对比](torch.nn.BatchNorm2d.md) |
| 33 | [torch.nn.BatchNorm3d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm3d.html?highlight=torch%20nn%20batchnorm3d#torch.nn.BatchNorm3d) | [paddle.nn.BatchNorm3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm3D_cn.html#batchnorm3d) | [差异对比](torch.nn.BatchNorm3d.md) | | 33 | [torch.nn.BatchNorm3d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm3d.html?highlight=torch%20nn%20batchnorm3d#torch.nn.BatchNorm3d) | [paddle.nn.BatchNorm3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm3D_cn.html#batchnorm3d) | [差异对比](torch.nn.BatchNorm3d.md) |
| 34 | [torch.nn.Upsample](https://pytorch.org/docs/stable/generated/torch.nn.Upsample.html?highlight=upsample#torch.nn.Upsample) | [paddle.nn.Upsample](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Upsample_cn.html#upsample) | [差异对比](torch.nn.Upsample.md) | | 34 | [torch.nn.Upsample](https://pytorch.org/docs/stable/generated/torch.nn.Upsample.html?highlight=upsample#torch.nn.Upsample) | [paddle.nn.Upsample](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Upsample_cn.html#upsample) | [差异对比](torch.nn.Upsample.md) |
| 35 | [torch.nn.Dropout](https://pytorch.org/docs/stable/generated/torch.nn.Dropout.html?highlight=dropout#torch.nn.Dropout) | [paddle.nn.Dropout](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout_cn.html#dropout) | [差异对比](torch.nn.Dropout.md) | | 35 | [torch.nn.Dropout](https://pytorch.org/docs/stable/generated/torch.nn.Dropout.html?highlight=dropout#torch.nn.Dropout) | [paddle.nn.Dropout](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout_cn.html#dropout) | [差异对比](torch.nn.Dropout.md) |
| 36 | [torch.nn.Dropout2d](https://pytorch.org/docs/stable/generated/torch.nn.Dropout2d.html?highlight=dropout2d#torch.nn.Dropout2d) | [paddle.nn.Dropout2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout2D_cn.html#dropout2d) | [差异对比](torch.nn.Dropout2d.md) | | 36 | [torch.nn.Dropout2d](https://pytorch.org/docs/stable/generated/torch.nn.Dropout2d.html?highlight=dropout2d#torch.nn.Dropout2d) | [paddle.nn.Dropout2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout2D_cn.html#dropout2d) | [差异对比](torch.nn.Dropout2d.md) |
| 37 | [torch.nn.Dropout3d](https://pytorch.org/docs/stable/generated/torch.nn.Dropout3d.html?highlight=dropout3d#torch.nn.Dropout3d) | [paddle.nn.Dropout3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout3D_cn.html#dropout3d) | [差异对比](torch.nn.Dropout3d.md) | | 37 | [torch.nn.Dropout3d](https://pytorch.org/docs/stable/generated/torch.nn.Dropout3d.html?highlight=dropout3d#torch.nn.Dropout3d) | [paddle.nn.Dropout3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout3D_cn.html#dropout3d) | [差异对比](torch.nn.Dropout3d.md) |
| 38 | [torch.nn.LSTM](https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html?highlight=lstm#torch.nn.LSTM) | [paddle.nn.LSTM](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/rnn/LSTM_cn.html#lstm) | [差异对比](torch.nn.LSTM.md) | | 38 | [torch.nn.LSTM](https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html?highlight=lstm#torch.nn.LSTM) | [paddle.nn.LSTM](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/LSTM_cn.html#lstm) | [差异对比](torch.nn.LSTM.md) |
| 39 | [torch.nn.GRU](https://pytorch.org/docs/stable/generated/torch.nn.GRU.html?highlight=torch%20nn%20gru#torch.nn.GRU) | [paddle.nn.GRU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/rnn/GRU_cn.html#gru) | [差异对比](torch.nn.GRU.md) | | 39 | [torch.nn.GRU](https://pytorch.org/docs/stable/generated/torch.nn.GRU.html?highlight=torch%20nn%20gru#torch.nn.GRU) | [paddle.nn.GRU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/GRU_cn.html#gru) | [差异对比](torch.nn.GRU.md) |
| 40 | [torch.nn.Embedding](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html?highlight=embedding#torch.nn.Embedding) | [paddle.nn.Embedding](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Embedding_cn.html#embedding) | [差异对比](torch.nn.Embedding.md) | | 40 | [torch.nn.Embedding](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html?highlight=embedding#torch.nn.Embedding) | [paddle.nn.Embedding](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Embedding_cn.html#embedding) | [差异对比](torch.nn.Embedding.md) |
| 41 | [torch.nn.ELU](https://pytorch.org/docs/stable/generated/torch.nn.ELU.html?highlight=elu#torch.nn.ELU) | [paddle.nn.ELU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/ELU_cn.html#elu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 | | 41 | [torch.nn.ELU](https://pytorch.org/docs/stable/generated/torch.nn.ELU.html?highlight=elu#torch.nn.ELU) | [paddle.nn.ELU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/ELU_cn.html#elu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 |
| 42 | [torch.nn.Hardsigmoid](https://pytorch.org/docs/stable/generated/torch.nn.Hardsigmoid.html?highlight=hardsigmoid#torch.nn.Hardsigmoid) | [paddle.nn.Hardsigmoid](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/Hardsigmoid_cn.html#hardsigmoid) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 | | 42 | [torch.nn.Hardsigmoid](https://pytorch.org/docs/stable/generated/torch.nn.Hardsigmoid.html?highlight=hardsigmoid#torch.nn.Hardsigmoid) | [paddle.nn.Hardsigmoid](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Hardsigmoid_cn.html#hardsigmoid) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 |
| 43 | [torch.nn.LeakyReLU](https://pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html?highlight=leakyrelu#torch.nn.LeakyReLU) | [paddle.nn.LeakyReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/LeakyReLU_cn.html#leakyrelu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 | | 43 | [torch.nn.LeakyReLU](https://pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html?highlight=leakyrelu#torch.nn.LeakyReLU) | [paddle.nn.LeakyReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/LeakyReLU_cn.html#leakyrelu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 |
| 44 | [torch.nn.PReLU](https://pytorch.org/docs/stable/generated/torch.nn.PReLU.html?highlight=prelu#torch.nn.PReLU) | [paddle.nn.PReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/PReLU_cn.html#prelu) | 功能一致 | | 44 | [torch.nn.PReLU](https://pytorch.org/docs/stable/generated/torch.nn.PReLU.html?highlight=prelu#torch.nn.PReLU) | [paddle.nn.PReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/PReLU_cn.html#prelu) | 功能一致 |
| 45 | [torch.nn.ReLU](https://pytorch.org/docs/stable/generated/torch.nn.ReLU.html?highlight=relu#torch.nn.ReLU) | [paddle.nn.ReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/ReLU_cn.html#relu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 | | 45 | [torch.nn.ReLU](https://pytorch.org/docs/stable/generated/torch.nn.ReLU.html?highlight=relu#torch.nn.ReLU) | [paddle.nn.ReLU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/ReLU_cn.html#relu) | 功能一致,PaddlePaddle未定义`inplace`参数表示在不更改变量的内存地址的情况下,直接修改变量的值 |
| 46 | [torch.nn.Softmax](https://pytorch.org/docs/stable/generated/torch.nn.Softmax.html?highlight=softmax#torch.nn.Softmax) | [paddle.nn.Softmax](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/activation/Softmax_cn.html#softmax) | 功能一致,参数名不一致 | | 46 | [torch.nn.Softmax](https://pytorch.org/docs/stable/generated/torch.nn.Softmax.html?highlight=softmax#torch.nn.Softmax) | [paddle.nn.Softmax](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Softmax_cn.html#softmax) | 功能一致,参数名不一致 |
***持续更新...*** ***持续更新...***
...@@ -9,7 +9,7 @@ torch.nn.AvgPool1d(kernel_size, ...@@ -9,7 +9,7 @@ torch.nn.AvgPool1d(kernel_size,
count_include_pad=True) count_include_pad=True)
``` ```
### [paddle.nn.AvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool1D_cn.html#avgpool1d) ### [paddle.nn.AvgPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool1D_cn.html#avgpool1d)
```python ```python
paddle.nn.AvgPool1D(kernel_size, paddle.nn.AvgPool1D(kernel_size,
......
...@@ -10,7 +10,7 @@ torch.nn.AvgPool2d(kernel_size, ...@@ -10,7 +10,7 @@ torch.nn.AvgPool2d(kernel_size,
divisor_override=None) divisor_override=None)
``` ```
### [paddle.nn.AvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool2D_cn.html#avgpool2d) ### [paddle.nn.AvgPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool2D_cn.html#avgpool2d)
```python ```python
paddle.nn.AvgPool2D(kernel_size, paddle.nn.AvgPool2D(kernel_size,
......
...@@ -10,7 +10,7 @@ torch.nn.AvgPool3d(kernel_size, ...@@ -10,7 +10,7 @@ torch.nn.AvgPool3d(kernel_size,
divisor_override=None) divisor_override=None)
``` ```
### [paddle.nn.AvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/AvgPool3D_cn.html#avgpool3d) ### [paddle.nn.AvgPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/AvgPool3D_cn.html#avgpool3d)
```python ```python
paddle.nn.AvgPool3D(kernel_size, paddle.nn.AvgPool3D(kernel_size,
......
...@@ -7,7 +7,7 @@ torch.nn.BatchNorm1d(num_features, ...@@ -7,7 +7,7 @@ torch.nn.BatchNorm1d(num_features,
affine=True, affine=True,
track_running_stats=True) track_running_stats=True)
``` ```
### [paddle.nn.BatchNorm1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm1D_cn.html#batchnorm1d) ### [paddle.nn.BatchNorm1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm1D_cn.html#batchnorm1d)
```python ```python
paddle.nn.BatchNorm1D(num_features, paddle.nn.BatchNorm1D(num_features,
momentum=0.9, momentum=0.9,
......
...@@ -7,7 +7,7 @@ torch.nn.BatchNorm2d(num_features, ...@@ -7,7 +7,7 @@ torch.nn.BatchNorm2d(num_features,
affine=True, affine=True,
track_running_stats=True) track_running_stats=True)
``` ```
### [paddle.nn.BatchNorm2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm2D_cn.html#batchnorm2d) ### [paddle.nn.BatchNorm2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm2D_cn.html#batchnorm2d)
```python ```python
paddle.nn.BatchNorm2D(num_features, paddle.nn.BatchNorm2D(num_features,
momentum=0.9, momentum=0.9,
......
...@@ -7,7 +7,7 @@ torch.nn.BatchNorm3d(num_features, ...@@ -7,7 +7,7 @@ torch.nn.BatchNorm3d(num_features,
affine=True, affine=True,
track_running_stats=True) track_running_stats=True)
``` ```
### [paddle.nn.BatchNorm3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/norm/BatchNorm3D_cn.html#batchnorm3d) ### [paddle.nn.BatchNorm3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BatchNorm3D_cn.html#batchnorm3d)
```python ```python
paddle.nn.BatchNorm3D(num_features, paddle.nn.BatchNorm3D(num_features,
momentum=0.9, momentum=0.9,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.ConstantPad1d(padding, value) torch.nn.ConstantPad1d(padding, value)
``` ```
### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) ### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d)
```python ```python
paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None) paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None)
``` ```
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.ConstantPad2d(padding, value) torch.nn.ConstantPad2d(padding, value)
``` ```
### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) ### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d)
```python ```python
paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None) paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None)
``` ```
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.ConstantPad3d(padding, value) torch.nn.ConstantPad3d(padding, value)
``` ```
### [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad3D_cn.html#pad3d) ### [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad3D_cn.html#pad3d)
```python ```python
paddle.nn.Pad3D(padding, mode='constant', value=0.0, data_format='NCDHW', name=None) paddle.nn.Pad3D(padding, mode='constant', value=0.0, data_format='NCDHW', name=None)
``` ```
......
...@@ -13,7 +13,7 @@ torch.nn.Conv1d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.Conv1d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv1D_cn.html#conv1d) ### [paddle.nn.Conv1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv1D_cn.html#conv1d)
```python ```python
paddle.nn.Conv1D(in_channels, paddle.nn.Conv1D(in_channels,
...@@ -37,7 +37,7 @@ paddle.nn.Conv1D(in_channels, ...@@ -37,7 +37,7 @@ paddle.nn.Conv1D(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding的设置 #### padding的设置
***PyTorch***`padding`只能支持list或tuple类型。 ***PyTorch***`padding`只能支持list或tuple类型。
......
...@@ -13,7 +13,7 @@ torch.nn.Conv2d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.Conv2d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv2D_cn.html#conv2d) ### [paddle.nn.Conv2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv2D_cn.html#conv2d)
```python ```python
paddle.nn.Conv2D(in_channels, paddle.nn.Conv2D(in_channels,
...@@ -37,7 +37,7 @@ paddle.nn.Conv2D(in_channels, ...@@ -37,7 +37,7 @@ paddle.nn.Conv2D(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding的设置 #### padding的设置
***PyTorch***`padding`只能支持list或tuple类型。它可以有3种格式: ***PyTorch***`padding`只能支持list或tuple类型。它可以有3种格式:
......
...@@ -13,7 +13,7 @@ torch.nn.Conv3d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.Conv3d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv3D_cn.html#conv3d) ### [paddle.nn.Conv3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv3D_cn.html#conv3d)
```python ```python
paddle.nn.Conv3D(in_channels, paddle.nn.Conv3D(in_channels,
...@@ -37,7 +37,7 @@ paddle.nn.Conv3D(in_channels, ...@@ -37,7 +37,7 @@ paddle.nn.Conv3D(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding的设置 #### padding的设置
***PyTorch***`padding`只能支持list或tuple类型。它可以有3种格式: ***PyTorch***`padding`只能支持list或tuple类型。它可以有3种格式:
(1)包含4个二元组:\[\[0,0\], \[0,0\], \[padding_depth_front, padding_depth_back\], \[padding_height_top, padding_height_bottom\], \[padding_width_left, padding_width_right\]\],其中每个元组都可使用整数值替换,代表元组中的2个值相等; (1)包含4个二元组:\[\[0,0\], \[0,0\], \[padding_depth_front, padding_depth_back\], \[padding_height_top, padding_height_bottom\], \[padding_width_left, padding_width_right\]\],其中每个元组都可使用整数值替换,代表元组中的2个值相等;
......
...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv1DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv1DTranspose_cn.html#conv1dtranspose) ### [paddle.nn.Conv1DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv1DTranspose_cn.html#conv1dtranspose)
```python ```python
paddle.nn.Conv1DTranspose(in_channels, paddle.nn.Conv1DTranspose(in_channels,
out_channels, out_channels,
...@@ -34,7 +34,7 @@ paddle.nn.Conv1DTranspose(in_channels, ...@@ -34,7 +34,7 @@ paddle.nn.Conv1DTranspose(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding大小的设置 #### padding大小的设置
***PyTorch***`padding`只能支持list或tuple类型。 ***PyTorch***`padding`只能支持list或tuple类型。
......
...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv2DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv2DTranspose_cn.html#conv2dtranspose) ### [paddle.nn.Conv2DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv2DTranspose_cn.html#conv2dtranspose)
```python ```python
paddle.nn.Conv2DTranspose(in_channels, paddle.nn.Conv2DTranspose(in_channels,
out_channels, out_channels,
...@@ -34,7 +34,7 @@ paddle.nn.Conv2DTranspose(in_channels, ...@@ -34,7 +34,7 @@ paddle.nn.Conv2DTranspose(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding大小的设置 #### padding大小的设置
***PyTorch***`padding`只能支持list或tuple类型。 ***PyTorch***`padding`只能支持list或tuple类型。
......
...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels, ...@@ -13,7 +13,7 @@ torch.nn.ConvTranspose1d(in_channels,
padding_mode='zeros') padding_mode='zeros')
``` ```
### [paddle.nn.Conv3DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/conv/Conv3DTranspose_cn.html#conv3dtranspose) ### [paddle.nn.Conv3DTranspose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Conv3DTranspose_cn.html#conv3dtranspose)
```python ```python
paddle.nn.Conv2DTranspose(in_channels, paddle.nn.Conv2DTranspose(in_channels,
out_channels, out_channels,
...@@ -34,7 +34,7 @@ paddle.nn.Conv2DTranspose(in_channels, ...@@ -34,7 +34,7 @@ paddle.nn.Conv2DTranspose(in_channels,
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
#### padding大小的设置 #### padding大小的设置
***PyTorch***`padding`只能支持list或tuple类型。 ***PyTorch***`padding`只能支持list或tuple类型。
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.Dropout(p=0.5, inplace=False) torch.nn.Dropout(p=0.5, inplace=False)
``` ```
### [paddle.nn.Dropout](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout_cn.html#dropout) ### [paddle.nn.Dropout](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout_cn.html#dropout)
```python ```python
paddle.nn.Dropout(p=0.5, axis=None, mode="upscale_in_train”, name=None) paddle.nn.Dropout(p=0.5, axis=None, mode="upscale_in_train”, name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.nn.Dropout2d(p=0.5, inplace=False) torch.nn.Dropout2d(p=0.5, inplace=False)
``` ```
### [paddle.nn.Dropout2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout2D_cn.html#dropout2d) ### [paddle.nn.Dropout2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout2D_cn.html#dropout2d)
```python ```python
paddle.nn.Dropout2D(p=0.5, data_format='NCHW', name=None) paddle.nn.Dropout2D(p=0.5, data_format='NCHW', name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.nn.Dropout3d(p=0.5, inplace=False) torch.nn.Dropout3d(p=0.5, inplace=False)
``` ```
### [paddle.nn.Dropout3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Dropout3D_cn.html#dropout3d) ### [paddle.nn.Dropout3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Dropout3D_cn.html#dropout3d)
```python ```python
paddle.nn.Dropout3D(p=0.5, data_format='NCDHW', name=None) paddle.nn.Dropout3D(p=0.5, data_format='NCDHW', name=None)
``` ```
......
...@@ -9,7 +9,7 @@ torch.nn.Embedding(num_embeddings, ...@@ -9,7 +9,7 @@ torch.nn.Embedding(num_embeddings,
scale_grad_by_freq=False, scale_grad_by_freq=False,
sparse=False) sparse=False)
``` ```
### [paddle.nn.Embedding](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Embedding_cn.html#embedding) ### [paddle.nn.Embedding](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Embedding_cn.html#embedding)
```python ```python
paddle.nn.Embedding(num_embeddings, paddle.nn.Embedding(num_embeddings,
embedding_dim, embedding_dim,
......
...@@ -10,7 +10,7 @@ torch.nn.GRU(input_size, ...@@ -10,7 +10,7 @@ torch.nn.GRU(input_size,
bidirectional=False) bidirectional=False)
``` ```
### [paddle.nn.GRU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/rnn/GRU_cn.html#gru) ### [paddle.nn.GRU](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/GRU_cn.html#gru)
```python ```python
paddle.nn.GRU(input_size, paddle.nn.GRU(input_size,
hidden_size, hidden_size,
...@@ -33,4 +33,4 @@ paddle.nn.GRU(input_size, ...@@ -33,4 +33,4 @@ paddle.nn.GRU(input_size,
### 功能差异 ### 功能差异
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_ih_attr`/`weight_hh_attr`/`bias_ih_attr`/`bias_hh_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_ih_attr`/`bias_hh_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_ih_attr`/`weight_hh_attr`/`bias_ih_attr`/`bias_hh_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_ih_attr`/`bias_hh_attr`设置为bool类型与PyTorch的作用一致。
...@@ -11,7 +11,7 @@ torch.nn.LSTM(input_size, ...@@ -11,7 +11,7 @@ torch.nn.LSTM(input_size,
proj_size=0) proj_size=0)
``` ```
### [paddle.nn.LSTM](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/rnn/LSTM_cn.html#lstm) ### [paddle.nn.LSTM](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/LSTM_cn.html#lstm)
```python ```python
paddle.nn.LSTM(input_size, paddle.nn.LSTM(input_size,
hidden_size, hidden_size,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
torch.nn.Linear(in_features, out_features, bias=True) torch.nn.Linear(in_features, out_features, bias=True)
``` ```
### [paddle.nn.Linear](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Linear_cn.html#linear) ### [paddle.nn.Linear](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Linear_cn.html#linear)
```python ```python
paddle.nn.Linear(in_features, out_features, weight_attr=None, bias_attr=None, name=None) paddle.nn.Linear(in_features, out_features, weight_attr=None, bias_attr=None, name=None)
...@@ -15,4 +15,4 @@ torch.nn.Linear(in_features, out_features, bias=True) ...@@ -15,4 +15,4 @@ torch.nn.Linear(in_features, out_features, bias=True)
#### 更新参数设置 #### 更新参数设置
***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。 ***PyTorch***`bias`默认为True,表示使用可更新的偏置参数。
***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/param_attr/ParamAttr_cn.html#cn-api-fluid-paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。 ***PaddlePaddle***`weight_attr`/`bias_attr`默认使用默认的权重/偏置参数属性,否则为指定的权重/偏置参数属性,具体用法参见[ParamAttr](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ParamAttr_cn.html#paramattr);当`bias_attr`设置为bool类型与PyTorch的作用一致。
...@@ -10,7 +10,7 @@ torch.nn.MaxPool1d(kernel_size, ...@@ -10,7 +10,7 @@ torch.nn.MaxPool1d(kernel_size,
ceil_mode=False) ceil_mode=False)
``` ```
### [paddle.nn.MaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool1D_cn.html#maxpool1d) ### [paddle.nn.MaxPool1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool1D_cn.html#maxpool1d)
```python ```python
paddle.nn.MaxPool1D(kernel_size, paddle.nn.MaxPool1D(kernel_size,
......
...@@ -10,7 +10,7 @@ torch.nn.MaxPool2d(kernel_size, ...@@ -10,7 +10,7 @@ torch.nn.MaxPool2d(kernel_size,
ceil_mode=False) ceil_mode=False)
``` ```
### [paddle.nn.MaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool2D_cn.html#maxpool2d) ### [paddle.nn.MaxPool2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool2D_cn.html#maxpool2d)
```python ```python
paddle.nn.MaxPool2D(kernel_size, paddle.nn.MaxPool2D(kernel_size,
......
...@@ -10,7 +10,7 @@ torch.nn.MaxPool3d(kernel_size, ...@@ -10,7 +10,7 @@ torch.nn.MaxPool3d(kernel_size,
ceil_mode=False) ceil_mode=False)
``` ```
### [paddle.nn.MaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/pooling/MaxPool3D_cn.html#maxpool3d) ### [paddle.nn.MaxPool3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/MaxPool3D_cn.html#maxpool3d)
```python ```python
paddle.nn.MaxPool3D(kernel_size, paddle.nn.MaxPool3D(kernel_size,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.ReflectionPad1d(padding) torch.nn.ReflectionPad1d(padding)
``` ```
### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) ### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d)
```python ```python
paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None) paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None)
``` ```
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.ReflectionPad2d(padding) torch.nn.ReflectionPad2d(padding)
``` ```
### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) ### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d)
```python ```python
paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None) paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.nn.ReplicationPad1d(padding) torch.nn.ReplicationPad1d(padding)
``` ```
### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad1D_cn.html#pad1d) ### [paddle.nn.Pad1D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad1D_cn.html#pad1d)
```python ```python
paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None) paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.nn.ReplicationPad2d(padding) torch.nn.ReplicationPad2d(padding)
``` ```
### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad2D_cn.html#pad2d) ### [paddle.nn.Pad2D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad2D_cn.html#pad2d)
```python ```python
paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None) paddle.nn.Pad2D(padding, mode='constant', value=0.0, data_format='NCHW', name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.nn.ReplicationPad3d(padding) torch.nn.ReplicationPad3d(padding)
``` ```
### [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Pad3D_cn.html#pad3d) ### [paddle.nn.Pad3D](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Pad3D_cn.html#pad3d)
```python ```python
paddle.nn.Pad3D(padding, mode='constant', value=0.0, data_format='NCDHW', name=None) paddle.nn.Pad3D(padding, mode='constant', value=0.0, data_format='NCDHW', name=None)
``` ```
......
...@@ -6,7 +6,7 @@ torch.nn.Upsample(size=None, ...@@ -6,7 +6,7 @@ torch.nn.Upsample(size=None,
mode='nearest', mode='nearest',
align_corners=False) align_corners=False)
``` ```
### [paddle.nn.Upsample](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/layer/common/Upsample_cn.html#upsample) ### [paddle.nn.Upsample](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/Upsample_cn.html#upsample)
```python ```python
paddle.nn.Upsample(size=None, paddle.nn.Upsample(size=None,
scale_factor=None, scale_factor=None,
......
...@@ -3,92 +3,92 @@ ...@@ -3,92 +3,92 @@
| 序号 | PyTorch API | PaddlePaddle API | 备注 | | 序号 | PyTorch API | PaddlePaddle API | 备注 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1 | [torch.set\_default\_dtype](https://pytorch.org/docs/stable/generated/torch.set_default_dtype.html) | [paddle.set\_default\_dtype](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/set_default_dtype_cn.html) | 功能一致 | | 1 | [torch.set\_default\_dtype](https://pytorch.org/docs/stable/generated/torch.set_default_dtype.html) | [paddle.set\_default\_dtype](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/set_default_dtype_cn.html#set-default-dtype) | 功能一致 |
| 2 | [torch.get\_default\_dtype](https://pytorch.org/docs/stable/generated/torch.get_default_dtype.html) | [paddle.get\_default\_dtype](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/get_default_dtype_cn.html#get-default-dtype) | 功能一致 | | 2 | [torch.get\_default\_dtype](https://pytorch.org/docs/stable/generated/torch.get_default_dtype.html) | [paddle.get\_default\_dtype](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/get_default_dtype_cn.html#get-default-dtype) | 功能一致 |
| 3 | [torch.numel](https://pytorch.org/docs/stable/generated/torch.numel.html) | [paddle.numel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/stat/numel_cn.html#numel) | 功能一致,参数名不一致 | | 3 | [torch.numel](https://pytorch.org/docs/stable/generated/torch.numel.html) | [paddle.numel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/numel_cn.html#numel) | 功能一致,参数名不一致 |
| 4 | [torch.tensor](https://pytorch.org/docs/stable/generated/torch.tensor.html?highlight=tensor#torch.tensor) | [paddle.to\_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/to_tensor_cn.html#to-tensor) | [差异对比](torch.tensor.md) | | 4 | [torch.tensor](https://pytorch.org/docs/stable/generated/torch.tensor.html?highlight=tensor#torch.tensor) | [paddle.to\_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/to_tensor_cn.html#to-tensor) | [差异对比](torch.tensor.md) |
| 5 | [torch.from\_numpy](https://pytorch.org/docs/stable/generated/torch.from_numpy.html?highlight=from_numpy#torch.from_numpy) | [paddle.to\_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/to_tensor_cn.html#to-tensor) | [差异对比](torch.from_numpy.md) | | 5 | [torch.from\_numpy](https://pytorch.org/docs/stable/generated/torch.from_numpy.html?highlight=from_numpy#torch.from_numpy) | [paddle.to\_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/to_tensor_cn.html#to-tensor) | [差异对比](torch.from_numpy.md) |
| 6 | [torch.zeros](https://pytorch.org/docs/stable/generated/torch.zeros.html?highlight=zeros#torch.zeros) | [paddle.zeros](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/zeros_cn.html#zeros) | [差异对比](torch.zeros.md) | | 6 | [torch.zeros](https://pytorch.org/docs/stable/generated/torch.zeros.html?highlight=zeros#torch.zeros) | [paddle.zeros](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/zeros_cn.html#zeros) | [差异对比](torch.zeros.md) |
| 7 | [torch.zeros_like](https://pytorch.org/docs/stable/generated/torch.zeros_like.html?highlight=zeros_like#torch.zeros_like) | [paddle.zeros_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/zeros_like_cn.html#zeros-like) | [差异对比](torch.zeros_like.md) | | 7 | [torch.zeros_like](https://pytorch.org/docs/stable/generated/torch.zeros_like.html?highlight=zeros_like#torch.zeros_like) | [paddle.zeros_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/zeros_like_cn.html#zeros-like) | [差异对比](torch.zeros_like.md) |
| 8 | [torch.ones](https://pytorch.org/docs/stable/generated/torch.ones.html?highlight=ones#torch.ones) | [paddle.ones](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/ones_cn.html#ones) | [差异对比](torch.ones.md) | | 8 | [torch.ones](https://pytorch.org/docs/stable/generated/torch.ones.html?highlight=ones#torch.ones) | [paddle.ones](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ones_cn.html#ones) | [差异对比](torch.ones.md) |
| 9 | [torch.ones_like](https://pytorch.org/docs/stable/generated/torch.zeros_like.html?highlight=zeros_like#torch.zeros_like) | [paddle.ones_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/zeros_like_cn.html#zeros-like) | [差异对比](torch.ones_like.md) | | 9 | [torch.ones_like](https://pytorch.org/docs/stable/generated/torch.zeros_like.html?highlight=zeros_like#torch.zeros_like) | [paddle.ones_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ones_like_cn.html#ones-like) | [差异对比](torch.ones_like.md) |
| 10 | [torch.empty](https://pytorch.org/docs/stable/generated/torch.empty.html?highlight=empty#torch.empty) | [paddle.empty](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/empty_cn.html#empty) | [差异对比](torch.empty.md) | | 10 | [torch.empty](https://pytorch.org/docs/stable/generated/torch.empty.html?highlight=empty#torch.empty) | [paddle.empty](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/empty_cn.html#empty) | [差异对比](torch.empty.md) |
| 11 | [torch.empty_like](https://pytorch.org/docs/stable/generated/torch.empty_like.html?highlight=empty_like#torch.empty_like) | [paddle.empty_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/empty_like_cn.html#empty-like) | [差异对比](torch.empty_like.md) | | 11 | [torch.empty_like](https://pytorch.org/docs/stable/generated/torch.empty_like.html?highlight=empty_like#torch.empty_like) | [paddle.empty_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/empty_like_cn.html#empty-like) | [差异对比](torch.empty_like.md) |
| 12 | [torch.full](https://pytorch.org/docs/stable/generated/torch.full.html?highlight=full#torch.full) | [paddle.full](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/full_cn.html#full) | 功能一致,[参数不一致](torch.full.md) | | 12 | [torch.full](https://pytorch.org/docs/stable/generated/torch.full.html?highlight=full#torch.full) | [paddle.full](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/full_cn.html#full) | 功能一致,[参数不一致](torch.full.md) |
| 13 | [torch.full_like](https://pytorch.org/docs/stable/generated/torch.full_like.html?highlight=full_like#torch.full_like) | [paddle.full_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/full_like_cn.html#full-like) | [差异对比](torch.full_like.md) | | 13 | [torch.full_like](https://pytorch.org/docs/stable/generated/torch.full_like.html?highlight=full_like#torch.full_like) | [paddle.full_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/full_like_cn.html#full-like) | [差异对比](torch.full_like.md) |
| 14 | [torch.arange](https://pytorch.org/docs/stable/generated/torch.arange.html?highlight=arange#torch.arange) | [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/arange_cn.html#arange) | 功能一致,[参数不一致](torch.arange.md) | | 14 | [torch.arange](https://pytorch.org/docs/stable/generated/torch.arange.html?highlight=arange#torch.arange) | [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/arange_cn.html#arange) | 功能一致,[参数不一致](torch.arange.md) |
| 15 | [torch.range](https://pytorch.org/docs/stable/generated/torch.range.html?highlight=range#torch.range) | [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/arange_cn.html#arange) | 功能一致,[参数不一致](torch.range.md) | | 15 | [torch.range](https://pytorch.org/docs/stable/generated/torch.range.html?highlight=range#torch.range) | [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/arange_cn.html#arange) | 功能一致,[参数不一致](torch.range.md) |
| 16 | [torch.linspace](https://pytorch.org/docs/stable/generated/torch.linspace.html?highlight=linspace#torch.linspace) | [paddle.linspace](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/linspace_cn.html#linspace) | 功能一致,[参数不一致](torch.linspace.md) | | 16 | [torch.linspace](https://pytorch.org/docs/stable/generated/torch.linspace.html?highlight=linspace#torch.linspace) | [paddle.linspace](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/linspace_cn.html#linspace) | 功能一致,[参数不一致](torch.linspace.md) |
| 17 | [torch.eye](https://pytorch.org/docs/stable/generated/torch.eye.html?highlight=eye#torch.eye) | [paddle.eye](https://pytorch.org/docs/stable/generated/torch.eye.html?highlight=eye#torch.eye) | 功能一致,[参数不一致](torch.eye.md) | | 17 | [torch.eye](https://pytorch.org/docs/stable/generated/torch.eye.html?highlight=eye#torch.eye) | [paddle.eye](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/eye_cn.html#eye) | 功能一致,[参数不一致](torch.eye.md) |
| 18 | [torch.cat](https://pytorch.org/docs/stable/generated/torch.cat.html?highlight=torch%20cat#torch.cat) | [paddle.concat](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/concat_cn.html#concat) | 功能一致,参数名不一致 | | 18 | [torch.cat](https://pytorch.org/docs/stable/generated/torch.cat.html?highlight=torch%20cat#torch.cat) | [paddle.concat](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/concat_cn.html#concat) | 功能一致,参数名不一致 |
| 19 | [torch.chunk](https://pytorch.org/docs/stable/generated/torch.chunk.html?highlight=chunk#torch.chunk) | [paddle.chunk](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/chunk_cn.html#chunk) | 功能一致,参数名不一致 | | 19 | [torch.chunk](https://pytorch.org/docs/stable/generated/torch.chunk.html?highlight=chunk#torch.chunk) | [paddle.chunk](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/chunk_cn.html#chunk) | 功能一致,参数名不一致 |
| 20 | [torch.gather](https://pytorch.org/docs/stable/generated/torch.gather.html?highlight=gather#torch.gather) | [paddle.gather](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/gather_cn.html#gather) | [差异对比](torch.gather.md) | | 20 | [torch.gather](https://pytorch.org/docs/stable/generated/torch.gather.html?highlight=gather#torch.gather) | [paddle.gather](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/gather_cn.html#gather) | [差异对比](torch.gather.md) |
| 21 | [torch.index\_select](https://pytorch.org/docs/stable/generated/torch.index_select.html?highlight=index_select#torch.index_select) | [paddle.index\_select](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/index_select_cn.html#index-select) | 功能一致,参数名不一致 | | 21 | [torch.index\_select](https://pytorch.org/docs/stable/generated/torch.index_select.html?highlight=index_select#torch.index_select) | [paddle.index\_select](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/index_select_cn.html#index-select) | 功能一致,参数名不一致 |
| 22 | [torch.masked\_select](https://pytorch.org/docs/stable/generated/torch.masked_select.html?highlight=masked_sel#torch.masked_select) | [paddle.masked\_select](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/masked_select_cn.html#masked-select) | 功能一致,参数名不一致 | | 22 | [torch.masked\_select](https://pytorch.org/docs/stable/generated/torch.masked_select.html?highlight=masked_sel#torch.masked_select) | [paddle.masked\_select](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/masked_select_cn.html#masked-select) | 功能一致,参数名不一致 |
| 23 | [torch.narrow](https://pytorch.org/docs/stable/generated/torch.narrow.html?highlight=narrow#torch.narrow) | [paddle.slice](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/slice_cn.html#slice) | [差异对比](torch.narrow.md) | | 23 | [torch.narrow](https://pytorch.org/docs/stable/generated/torch.narrow.html?highlight=narrow#torch.narrow) | [paddle.slice](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/slice_cn.html#slice) | [差异对比](torch.narrow.md) |
| 24 | [torch.nonzero](https://pytorch.org/docs/stable/generated/torch.nonzero.html?highlight=nonzero#torch.nonzero) | [paddle.nonzero](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/nonzero_cn.html#nonzero) | 功能一致,参数名不一致 | | 24 | [torch.nonzero](https://pytorch.org/docs/stable/generated/torch.nonzero.html?highlight=nonzero#torch.nonzero) | [paddle.nonzero](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nonzero_cn.html#nonzero) | 功能一致,参数名不一致 |
| 25 | [torch.reshape](https://pytorch.org/docs/stable/generated/torch.reshape.html?highlight=reshape#torch.reshape) | [paddle.reshape](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/reshape_cn.html#reshape) | 功能一致,参数名不一致 | | 25 | [torch.reshape](https://pytorch.org/docs/stable/generated/torch.reshape.html?highlight=reshape#torch.reshape) | [paddle.reshape](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/reshape_cn.html#reshape) | 功能一致,参数名不一致 |
| 26 | [torch.split](https://pytorch.org/docs/stable/generated/torch.split.html?highlight=split#torch.split) | [paddle.split](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/split_cn.html#split) | 功能一致,参数名不一致 | | 26 | [torch.split](https://pytorch.org/docs/stable/generated/torch.split.html?highlight=split#torch.split) | [paddle.split](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/split_cn.html#split) | 功能一致,参数名不一致 |
| 27 | [torch.squeeze](https://pytorch.org/docs/stable/generated/torch.squeeze.html?highlight=squeeze#torch.squeeze) | [paddle.squeeze](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/squeeze_cn.html#squeeze) | 功能一致,参数名不一致 | | 27 | [torch.squeeze](https://pytorch.org/docs/stable/generated/torch.squeeze.html?highlight=squeeze#torch.squeeze) | [paddle.squeeze](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/squeeze_cn.html#squeeze) | 功能一致,参数名不一致 |
| 28 | [torch.stack](https://pytorch.org/docs/stable/generated/torch.stack.html?highlight=stack#torch.stack) | [paddle.stack](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/stack_cn.html#stack) | 功能一致,参数名不一致 | | 28 | [torch.stack](https://pytorch.org/docs/stable/generated/torch.stack.html?highlight=stack#torch.stack) | [paddle.stack](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/stack_cn.html#stack) | 功能一致,参数名不一致 |
| 29 | [torch.t](https://pytorch.org/docs/stable/generated/torch.t.html) | [paddle.t](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/linalg/t_cn.html#t) | 功能一致,参数名不一致 | | 29 | [torch.t](https://pytorch.org/docs/stable/generated/torch.t.html) | [paddle.t](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/t_cn.html#t) | 功能一致,参数名不一致 |
| 30 | [torch.transpose](https://pytorch.org/docs/stable/generated/torch.transpose.html?highlight=transpose#torch.transpose) | [paddle.transpose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/transpose_cn.html#transpose) | [差异对比](torch.transpose.md) | | 30 | [torch.transpose](https://pytorch.org/docs/stable/generated/torch.transpose.html?highlight=transpose#torch.transpose) | [paddle.transpose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/transpose_cn.html#transpose) | [差异对比](torch.transpose.md) |
| 31 | [torch.unbind](https://pytorch.org/docs/stable/generated/torch.unbind.html?highlight=unbind#torch.unbind) | [paddle.unbind](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/unbind_cn.html#unbind) | 功能一致,参数名不一致 | | 31 | [torch.unbind](https://pytorch.org/docs/stable/generated/torch.unbind.html?highlight=unbind#torch.unbind) | [paddle.unbind](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/unbind_cn.html#unbind) | 功能一致,参数名不一致 |
| 32 | [torch.unsqueeze](https://pytorch.org/docs/stable/generated/torch.unsqueeze.html?highlight=unsqueeze#torch.unsqueeze) | [paddle.unsqueeze](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/unsqueeze_cn.html#unsqueeze) | 功能一致,参数名不一致 | | 32 | [torch.unsqueeze](https://pytorch.org/docs/stable/generated/torch.unsqueeze.html?highlight=unsqueeze#torch.unsqueeze) | [paddle.unsqueeze](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/unsqueeze_cn.html#unsqueeze) | 功能一致,参数名不一致 |
| 33 | [torch.where](https://pytorch.org/docs/stable/generated/torch.where.html?highlight=where#torch.where) | [paddle.where](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/where_cn.html#where) | 功能一致 | | 33 | [torch.where](https://pytorch.org/docs/stable/generated/torch.where.html?highlight=where#torch.where) | [paddle.where](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/where_cn.html#where) | 功能一致 |
| 34 | [torch.bernoulli](https://pytorch.org/docs/stable/generated/torch.bernoulli.html?highlight=bernoulli#torch.bernoulli) | [paddle.bernoulli](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/bernoulli_cn.html#bernoulli) | 功能一致,[参数不一致](torch.bernoulli.md) | | 34 | [torch.bernoulli](https://pytorch.org/docs/stable/generated/torch.bernoulli.html?highlight=bernoulli#torch.bernoulli) | [paddle.bernoulli](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/bernoulli_cn.html#bernoulli) | 功能一致,[参数不一致](torch.bernoulli.md) |
| 35 | [torch.multinomial](https://pytorch.org/docs/stable/generated/torch.multinomial.html?highlight=multinomial#torch.multinomial) | [paddle.multinomial](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/multinomial_cn.html#multinomial) | 功能一致,[参数不一致](torch.multinomial.md) | | 35 | [torch.multinomial](https://pytorch.org/docs/stable/generated/torch.multinomial.html?highlight=multinomial#torch.multinomial) | [paddle.multinomial](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/multinomial_cn.html#multinomial) | 功能一致,[参数不一致](torch.multinomial.md) |
| 36 | [torch.normal](https://pytorch.org/docs/stable/generated/torch.normal.html?highlight=normal#torch.normal) | [paddle.normal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/normal_cn.html#normal) | [差异对比](torch.normal.md) | | 36 | [torch.normal](https://pytorch.org/docs/stable/generated/torch.normal.html?highlight=normal#torch.normal) | [paddle.normal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/normal_cn.html#normal) | [差异对比](torch.normal.md) |
| 37 | [torch.rand](https://pytorch.org/docs/stable/generated/torch.rand.html?highlight=rand#torch.rand) | [paddle.rand](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/rand_cn.html#rand) | [差异对比](torch.rand.md) | | 37 | [torch.rand](https://pytorch.org/docs/stable/generated/torch.rand.html?highlight=rand#torch.rand) | [paddle.rand](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/rand_cn.html#rand) | [差异对比](torch.rand.md) |
| 38 | [torch.randint](https://pytorch.org/docs/stable/generated/torch.randint.html?highlight=randint#torch.randint) | [paddle.randint](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/randint_cn.html#randint) | 功能一致,[参数不一致](torch.randint.md) | | 38 | [torch.randint](https://pytorch.org/docs/stable/generated/torch.randint.html?highlight=randint#torch.randint) | [paddle.randint](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randint_cn.html#randint) | 功能一致,[参数不一致](torch.randint.md) |
| 39 | [torch.randn](https://pytorch.org/docs/stable/generated/torch.randn.html?highlight=ran%20dn#torch.randn) | [paddle.randn](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/randn_cn.html#randn) | [差异对比](torch.randn.md) | | 39 | [torch.randn](https://pytorch.org/docs/stable/generated/torch.randn.html?highlight=ran%20dn#torch.randn) | [paddle.randn](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randn_cn.html#randn) | [差异对比](torch.randn.md) |
| 40 | [torch.randperm](https://pytorch.org/docs/stable/generated/torch.randperm.html?highlight=randperm#torch.randperm) | [paddle.randperm](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/randperm_cn.html#randperm) | 功能一致,[参数不一致](torch.randperm.md) | | 40 | [torch.randperm](https://pytorch.org/docs/stable/generated/torch.randperm.html?highlight=randperm#torch.randperm) | [paddle.randperm](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randperm_cn.html#randperm) | 功能一致,[参数不一致](torch.randperm.md) |
| 41 | [torch.save](https://pytorch.org/docs/stable/generated/torch.save.html?highlight=save#torch.save) | [paddle.save](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/io/save_cn.html#save) | [差异对比](torch.save.md) | | 41 | [torch.save](https://pytorch.org/docs/stable/generated/torch.save.html?highlight=save#torch.save) | [paddle.save](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/save_cn.html#save) | [差异对比](torch.save.md) |
| 42 | [torch.load](https://pytorch.org/docs/stable/generated/torch.load.html?highlight=load#torch.load) | [paddle.load](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/io/load_cn.html#load) | [差异对比](torch.load.md) | | 42 | [torch.load](https://pytorch.org/docs/stable/generated/torch.load.html?highlight=load#torch.load) | [paddle.load](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/load_cn.html#load) | [差异对比](torch.load.md) |
| 43 | [torch.abs](https://pytorch.org/docs/stable/generated/torch.abs.html?highlight=abs#torch.abs) | [paddle.abs](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/abs_cn.html#abs) | 功能一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 43 | [torch.abs](https://pytorch.org/docs/stable/generated/torch.abs.html?highlight=abs#torch.abs) | [paddle.abs](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/abs_cn.html#abs) | 功能一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 44 | [torch.absolute](https://pytorch.org/docs/stable/generated/torch.absolute.html?highlight=absolute#torch.absolute) | [paddle.abs](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/abs_cn.html#abs) | 功能一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 44 | [torch.absolute](https://pytorch.org/docs/stable/generated/torch.absolute.html?highlight=absolute#torch.absolute) | [paddle.abs](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/abs_cn.html#abs) | 功能一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 45 | [torch.acos](https://pytorch.org/docs/stable/generated/torch.acos.html?highlight=torch%20acos#torch.acos) | [paddle.acos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/acos_cn.html#acos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 45 | [torch.acos](https://pytorch.org/docs/stable/generated/torch.acos.html?highlight=torch%20acos#torch.acos) | [paddle.acos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/acos_cn.html#acos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 46 | [torch.arccos](https://pytorch.org/docs/stable/generated/torch.arccos.html?highlight=arccos#torch.arccos) | [paddle.acos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/acos_cn.html#acos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 46 | [torch.arccos](https://pytorch.org/docs/stable/generated/torch.arccos.html?highlight=arccos#torch.arccos) | [paddle.acos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/acos_cn.html#acos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 47 | [torch.add](https://pytorch.org/docs/stable/generated/torch.add.html?highlight=add#torch.add) | [padle.add](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/add_cn.html#add) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 47 | [torch.add](https://pytorch.org/docs/stable/generated/torch.add.html?highlight=add#torch.add) | [padle.add](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/add_cn.html#add) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 48 | [torch.asin](https://pytorch.org/docs/stable/generated/torch.asin.html?highlight=asin#torch.asin) | [paddle.asin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/asin_cn.html#asin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 48 | [torch.asin](https://pytorch.org/docs/stable/generated/torch.asin.html?highlight=asin#torch.asin) | [paddle.asin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/asin_cn.html#asin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 49 | [torch.arcsin](https://pytorch.org/docs/stable/generated/torch.arcsin.html?highlight=arcsin#torch.arcsin) | [paddle.asin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/asin_cn.html#asin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 49 | [torch.arcsin](https://pytorch.org/docs/stable/generated/torch.arcsin.html?highlight=arcsin#torch.arcsin) | [paddle.asin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/asin_cn.html#asin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 50 | [torch.atan](https://pytorch.org/docs/stable/generated/torch.atan.html?highlight=atan#torch.atan) | [paddle.atan](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/atan_cn.html#atan) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 50 | [torch.atan](https://pytorch.org/docs/stable/generated/torch.atan.html?highlight=atan#torch.atan) | [paddle.atan](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/atan_cn.html#atan) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 51 | [torch.arctan](https://pytorch.org/docs/stable/generated/torch.arctan.html?highlight=arctan#torch.arctan) | [paddle.atan](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/atan_cn.html#atan) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 51 | [torch.arctan](https://pytorch.org/docs/stable/generated/torch.arctan.html?highlight=arctan#torch.arctan) | [paddle.atan](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/atan_cn.html#atan) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 52 | [torch.ceil](https://pytorch.org/docs/stable/generated/torch.ceil.html?highlight=ceil#torch.ceil) | [paddle.ceil](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/ceil_cn.html#ceil) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 52 | [torch.ceil](https://pytorch.org/docs/stable/generated/torch.ceil.html?highlight=ceil#torch.ceil) | [paddle.ceil](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ceil_cn.html#ceil) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 53 | [torch.clamp](https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp) | [paddle.clip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/clip_cn.html#clip) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 53 | [torch.clamp](https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp) | [paddle.clip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/clip_cn.html#clip) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 54 | [torch.conj](https://pytorch.org/docs/stable/generated/torch.conj.html?highlight=conj#torch.conj) | [paddle.conj](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/conj_cn.html#conj) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 54 | [torch.conj](https://pytorch.org/docs/stable/generated/torch.conj.html?highlight=conj#torch.conj) | [paddle.conj](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/conj_cn.html#conj) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 55 | [torch.cos](https://pytorch.org/docs/stable/generated/torch.cos.html?highlight=cos#torch.cos) | [paddle.cos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/cos_cn.html#cos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 55 | [torch.cos](https://pytorch.org/docs/stable/generated/torch.cos.html?highlight=cos#torch.cos) | [paddle.cos](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/cos_cn.html#cos) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 56 | [torch.cosh](https://pytorch.org/docs/stable/generated/torch.cosh.html?highlight=cosh#torch.cosh) | [paddle.cosh](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/cosh_cn.html#cosh) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 56 | [torch.cosh](https://pytorch.org/docs/stable/generated/torch.cosh.html?highlight=cosh#torch.cosh) | [paddle.cosh](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/cosh_cn.html#cosh) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 57 | [torch.div](https://pytorch.org/docs/stable/generated/torch.div.html?highlight=div#torch.div) | [paddle.divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/divide_cn.html#divide) | [差异对比](torch.div.md) | | 57 | [torch.div](https://pytorch.org/docs/stable/generated/torch.div.html?highlight=div#torch.div) | [paddle.divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/divide_cn.html#divide) | [差异对比](torch.div.md) |
| 58 | [torch.divide](https://pytorch.org/docs/stable/generated/torch.divide.html?highlight=divide#torch.divide) | [paddle.divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/divide_cn.html#divide) | [差异对比](torch.divide.md) | | 58 | [torch.divide](https://pytorch.org/docs/stable/generated/torch.divide.html?highlight=divide#torch.divide) | [paddle.divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/divide_cn.html#divide) | [差异对比](torch.divide.md) |
| 59 | [torch.erf](https://pytorch.org/docs/stable/generated/torch.erf.html?highlight=erf#torch.erf) | [paddle.erf](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/erf_cn.html#erf) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 59 | [torch.erf](https://pytorch.org/docs/stable/generated/torch.erf.html?highlight=erf#torch.erf) | [paddle.erf](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/erf_cn.html#erf) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 60 | [torch.exp](https://pytorch.org/docs/stable/generated/torch.exp.html?highlight=exp#torch.exp) | [paddle.exp](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/exp_cn.html#exp) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 60 | [torch.exp](https://pytorch.org/docs/stable/generated/torch.exp.html?highlight=exp#torch.exp) | [paddle.exp](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/exp_cn.html#exp) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 61 | [torch.floor](https://pytorch.org/docs/stable/generated/torch.floor.html?highlight=floor#torch.floor) | [paddle.floor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/floor_cn.html#floor) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 61 | [torch.floor](https://pytorch.org/docs/stable/generated/torch.floor.html?highlight=floor#torch.floor) | [paddle.floor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/floor_cn.html#floor) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 62 | [torch.floor_divide](https://pytorch.org/docs/stable/generated/torch.floor_divide.html?highlight=floor_divide#torch.floor_divide) | [paddle.floor_divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/floor_divide_cn.html#floor-divide) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 62 | [torch.floor_divide](https://pytorch.org/docs/stable/generated/torch.floor_divide.html?highlight=floor_divide#torch.floor_divide) | [paddle.floor_divide](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/floor_divide_cn.html#floor-divide) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 63 | [torch.fmod](https://pytorch.org/docs/stable/generated/torch.fmod.html?highlight=fmod#torch.fmod) | [paddle.mod](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/remainder_cn.html#mod) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 63 | [torch.fmod](https://pytorch.org/docs/stable/generated/torch.fmod.html?highlight=fmod#torch.fmod) | [paddle.mod](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/mod_cn.html#mod) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 64 | [torch.log](https://pytorch.org/docs/stable/generated/torch.log.html?highlight=log#torch.log) | [paddle.log](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/log_cn.html#log) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 64 | [torch.log](https://pytorch.org/docs/stable/generated/torch.log.html?highlight=log#torch.log) | [paddle.log](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/log_cn.html#log) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 65 | [torch.log10](https://pytorch.org/docs/stable/generated/torch.log10.html?highlight=log10#torch.log10) | [paddle.log10](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/log10_cn.html#log10) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 65 | [torch.log10](https://pytorch.org/docs/stable/generated/torch.log10.html?highlight=log10#torch.log10) | [paddle.log10](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/log10_cn.html#log10) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 66 | [torch.log1p](https://pytorch.org/docs/stable/generated/torch.log1p.html?highlight=log1p#torch.log1p) | [paddle.log1p](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/log1p_cn.html#log1p) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 66 | [torch.log1p](https://pytorch.org/docs/stable/generated/torch.log1p.html?highlight=log1p#torch.log1p) | [paddle.log1p](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/log1p_cn.html#log1p) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 67 | [torch.log2](https://pytorch.org/docs/stable/generated/torch.log2.html?highlight=log2#torch.log2) | [paddle.log2](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/log2_cn.html#log2) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 67 | [torch.log2](https://pytorch.org/docs/stable/generated/torch.log2.html?highlight=log2#torch.log2) | [paddle.log2](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/log2_cn.html#log2) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 68 | [torch.logical_and](https://pytorch.org/docs/stable/generated/torch.logical_and.html?highlight=logical_and#torch.logical_and) | [paddle.logical_and](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/logical_and_cn.html#logical-and) | 功能一致,参数名不一致 | | 68 | [torch.logical_and](https://pytorch.org/docs/stable/generated/torch.logical_and.html?highlight=logical_and#torch.logical_and) | [paddle.logical_and](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/logical_and_cn.html#logical-and) | 功能一致,参数名不一致 |
| 69 | [torch.logical_not](https://pytorch.org/docs/stable/generated/torch.logical_not.html?highlight=logical_not#torch.logical_not) | [paddle.logical_not](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/logical_not_cn.html#logical-not) | 功能一致,参数名不一致 | | 69 | [torch.logical_not](https://pytorch.org/docs/stable/generated/torch.logical_not.html?highlight=logical_not#torch.logical_not) | [paddle.logical_not](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/logical_not_cn.html#logical-not) | 功能一致,参数名不一致 |
| 70 | [torch.logical_or](https://pytorch.org/docs/stable/generated/torch.logical_or.html?highlight=logical_or#torch.logical_or) | [paddle.logical_or](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/logical_or_cn.html#logical-or) | 功能一致,参数名不一致 | | 70 | [torch.logical_or](https://pytorch.org/docs/stable/generated/torch.logical_or.html?highlight=logical_or#torch.logical_or) | [paddle.logical_or](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/logical_or_cn.html#logical-or) | 功能一致,参数名不一致 |
| 71 | [torch.logical_xor](https://pytorch.org/docs/stable/generated/torch.logical_xor.html?highlight=logical_xor#torch.logical_xor) | [paddle.logical_xor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/logical_xor_cn.html#logical-xor) | 功能一致,参数名不一致 | | 71 | [torch.logical_xor](https://pytorch.org/docs/stable/generated/torch.logical_xor.html?highlight=logical_xor#torch.logical_xor) | [paddle.logical_xor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/logical_xor_cn.html#logical-xor) | 功能一致,参数名不一致 |
| 72 | [torch.mul](https://pytorch.org/docs/stable/generated/torch.mul.html?highlight=torch%20mul#torch.mul) | [paddle.multiply](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/multiply_cn.html#multiply) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 72 | [torch.mul](https://pytorch.org/docs/stable/generated/torch.mul.html?highlight=torch%20mul#torch.mul) | [paddle.multiply](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/multiply_cn.html#multiply) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 73 | [torch.multiply](https://pytorch.org/docs/stable/generated/torch.multiply.html?highlight=multiply#torch.multiply) | [paddle.multiply](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/multiply_cn.html#multiply) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 73 | [torch.multiply](https://pytorch.org/docs/stable/generated/torch.multiply.html?highlight=multiply#torch.multiply) | [paddle.multiply](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/multiply_cn.html#multiply) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 74 | [torch.pow](https://pytorch.org/docs/stable/generated/torch.pow.html?highlight=pow#torch.pow) | [paddle.pow](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/pow_cn.html#pow) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 74 | [torch.pow](https://pytorch.org/docs/stable/generated/torch.pow.html?highlight=pow#torch.pow) | [paddle.pow](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/pow_cn.html#pow) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 75 | [torch.real](https://pytorch.org/docs/stable/generated/torch.real.html?highlight=real#torch.real) | [paddle.real](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/attribute/real_cn.html#real) | 功能一致,参数名不一致 | | 75 | [torch.real](https://pytorch.org/docs/stable/generated/torch.real.html?highlight=real#torch.real) | [paddle.real](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/real_cn.html#real) | 功能一致,参数名不一致 |
| 76 | [torch.reciprocal](https://pytorch.org/docs/stable/generated/torch.reciprocal.html?highlight=reciprocal#torch.reciprocal) | [paddle.reciprocal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/reciprocal_cn.html#reciprocal) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 76 | [torch.reciprocal](https://pytorch.org/docs/stable/generated/torch.reciprocal.html?highlight=reciprocal#torch.reciprocal) | [paddle.reciprocal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/reciprocal_cn.html#reciprocal) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 77 | [torch.remainder](https://pytorch.org/docs/stable/generated/torch.remainder.html?highlight=remainder#torch.remainder) | [paddle.mod](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/remainder_cn.html#cn-api-tensor-remainder) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 77 | [torch.remainder](https://pytorch.org/docs/stable/generated/torch.remainder.html?highlight=remainder#torch.remainder) | [paddle.mod](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/mod_cn.html#mod) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 78 | [torch.round](https://pytorch.org/docs/stable/generated/torch.round.html?highlight=round#torch.round) | [paddle.round](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/round_cn.html#round) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 78 | [torch.round](https://pytorch.org/docs/stable/generated/torch.round.html?highlight=round#torch.round) | [paddle.round](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/round_cn.html#round) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 79 | [torch.rsqrt](https://pytorch.org/docs/stable/generated/torch.rsqrt.html?highlight=rsqrt#torch.rsqrt) | [paddle.rsqrt](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/rsqrt_cn.html#rsqrt) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 79 | [torch.rsqrt](https://pytorch.org/docs/stable/generated/torch.rsqrt.html?highlight=rsqrt#torch.rsqrt) | [paddle.rsqrt](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/rsqrt_cn.html#rsqrt) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 80 | [torch.sign](https://pytorch.org/docs/stable/generated/torch.sign.html?highlight=sign#torch.sign) | [paddle.sign](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/sign_cn.html#sign) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 80 | [torch.sign](https://pytorch.org/docs/stable/generated/torch.sign.html?highlight=sign#torch.sign) | [paddle.sign](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/sign_cn.html#sign) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 81 | [torch.sin](https://pytorch.org/docs/stable/generated/torch.sin.html?highlight=sin#torch.sin) | [paddle.sin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/sin_cn.html#sin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 81 | [torch.sin](https://pytorch.org/docs/stable/generated/torch.sin.html?highlight=sin#torch.sin) | [paddle.sin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/sin_cn.html#sin) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 82 | [torch.sinh](https://pytorch.org/docs/stable/generated/torch.sinh.html?highlight=sinh#torch.sinh) | [paddle.sinh](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/sinh_cn.html#sinh) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 82 | [torch.sinh](https://pytorch.org/docs/stable/generated/torch.sinh.html?highlight=sinh#torch.sinh) | [paddle.sinh](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/sinh_cn.html#sinh) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 83 | [torch.sqrt](https://pytorch.org/docs/stable/generated/torch.sqrt.html?highlight=sqrt#torch.sqrt) | [paddle.sqrt](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/sqrt_cn.html#sqrt) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 83 | [torch.sqrt](https://pytorch.org/docs/stable/generated/torch.sqrt.html?highlight=sqrt#torch.sqrt) | [paddle.sqrt](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/sqrt_cn.html#sqrt) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 84 | [torch.argmax](https://pytorch.org/docs/stable/generated/torch.argmax.html?highlight=argmax#torch.argmax) | [paddle.argmax](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/argmax_cn.html#argmax) | 功能一致,参数名不一致 | | 84 | [torch.argmax](https://pytorch.org/docs/stable/generated/torch.argmax.html?highlight=argmax#torch.argmax) | [paddle.argmax](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/argmax_cn.html#argmax) | 功能一致,参数名不一致 |
| 85 | [torch.argmin](https://pytorch.org/docs/stable/generated/torch.argmin.html?highlight=argmin#torch.argmin) | [paddle.argmin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/search/argmin_cn.html#argmin) | 功能一致,参数名不一致 | | 85 | [torch.argmin](https://pytorch.org/docs/stable/generated/torch.argmin.html?highlight=argmin#torch.argmin) | [paddle.argmin](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/argmin_cn.html#argmin) | 功能一致,参数名不一致 |
| 86 | [torch.max](https://pytorch.org/docs/stable/generated/torch.max.html?highlight=max#torch.max) | [paddle.max](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/max_cn.html#max) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 86 | [torch.max](https://pytorch.org/docs/stable/generated/torch.max.html?highlight=max#torch.max) | [paddle.max](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/max_cn.html#max) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
| 87 | [torch.min](https://pytorch.org/docs/stable/generated/torch.min.html?highlight=min#torch.min) | [paddle.min](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/math/min_cn.html#min) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor | | 87 | [torch.min](https://pytorch.org/docs/stable/generated/torch.min.html?highlight=min#torch.min) | [paddle.min](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/min_cn.html#min) | 功能一致,参数名不一致,PaddlePaddle未定义`out`参数代表输出Tensor |
***持续更新...*** ***持续更新...***
...@@ -12,7 +12,7 @@ torch.arange(start=0, ...@@ -12,7 +12,7 @@ torch.arange(start=0,
device=None, device=None,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/arange_cn.html#arange) ### [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/arange_cn.html#arange)
```python ```python
paddle.arange(start=0, paddle.arange(start=0,
end=None, end=None,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.bernoulli(input, *, generator=None, out=None) torch.bernoulli(input, *, generator=None, out=None)
``` ```
### [paddle.bernoulli](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/bernoulli_cn.html#bernoulli) ### [paddle.bernoulli](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/bernoulli_cn.html#bernoulli)
```python ```python
paddle.bernoulli(x, name=None) paddle.bernoulli(x, name=None)
``` ```
......
...@@ -12,7 +12,7 @@ torch.empty(*size, ...@@ -12,7 +12,7 @@ torch.empty(*size,
pin_memory=False) pin_memory=False)
``` ```
### [paddle.empty](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/empty_cn.html#empty) ### [paddle.empty](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/empty_cn.html#empty)
```python ```python
paddle.empty(shape, paddle.empty(shape,
......
...@@ -12,7 +12,7 @@ torch.eye(n, ...@@ -12,7 +12,7 @@ torch.eye(n,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.eye](https://pytorch.org/docs/stable/generated/torch.eye.html?highlight=eye#torch.eye) ### [paddle.eye](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/eye_cn.html#eye)
```python ```python
paddle.eye(num_rows, paddle.eye(num_rows,
num_columns=None, num_columns=None,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
torch.from_numpy(ndarray) torch.from_numpy(ndarray)
``` ```
### [paddle.to_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/to_tensor_cn.html#to-tensor) ### [paddle.to_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/to_tensor_cn.html#to-tensor)
```python ```python
paddle.to_tensor(data, paddle.to_tensor(data,
......
...@@ -12,7 +12,7 @@ torch.full(size, ...@@ -12,7 +12,7 @@ torch.full(size,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.full](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/full_cn.html#full) ### [paddle.full](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/full_cn.html#full)
```python ```python
paddle.full(shape, paddle.full(shape,
fill_value, fill_value,
......
...@@ -12,7 +12,7 @@ torch.full_like(input, ...@@ -12,7 +12,7 @@ torch.full_like(input,
memory_format=torch.preserve_format) memory_format=torch.preserve_format)
``` ```
### [paddle.full_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/full_like_cn.html#full-like) ### [paddle.full_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/full_like_cn.html#full-like)
```python ```python
paddle.full_like(x, fill_value, dtype=None, name=None) paddle.full_like(x, fill_value, dtype=None, name=None)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
torch.gather(input, dim, index, *, sparse_grad=False, out=None) torch.gather(input, dim, index, *, sparse_grad=False, out=None)
``` ```
### [paddle.gather](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/manipulation/gather_cn.html#gather) ### [paddle.gather](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/gather_cn.html#gather)
```python ```python
paddle.gather(x, index, axis=None, name=None) paddle.gather(x, index, axis=None, name=None)
......
...@@ -12,7 +12,7 @@ torch.linspace(start, ...@@ -12,7 +12,7 @@ torch.linspace(start,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.linspace](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/linspace_cn.html#linspace) ### [paddle.linspace](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/linspace_cn.html#linspace)
```python ```python
paddle.linspace(start, paddle.linspace(start,
stop, stop,
......
...@@ -8,7 +8,7 @@ torch.load(f, ...@@ -8,7 +8,7 @@ torch.load(f,
**pickle_load_args) **pickle_load_args)
``` ```
### [paddle.load](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/io/load_cn.html#load) ### [paddle.load](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/load_cn.html#load)
```python ```python
paddle.load(path, **configs) paddle.load(path, **configs)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.multinomial(input, num_samples, replacement=False, *, generator=None, out=None) torch.multinomial(input, num_samples, replacement=False, *, generator=None, out=None)
``` ```
### [paddle.multinomial](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/multinomial_cn.html#multinomial) ### [paddle.multinomial](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/multinomial_cn.html#multinomial)
```python ```python
paddle.multinomial(x, num_samples=1, replacement=False, name=None) paddle.multinomial(x, num_samples=1, replacement=False, name=None)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.narrow(input, dim, start, length) torch.narrow(input, dim, start, length)
``` ```
### [paddle.slice](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/slice_cn.html#slice) ### [paddle.slice](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/slice_cn.html#slice)
```python ```python
paddle.slice(input, axes, starts, ends) paddle.slice(input, axes, starts, ends)
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
```python ```python
torch.normal(mean, std, *, generator=None, out=None) torch.normal(mean, std, *, generator=None, out=None)
``` ```
### [paddle.normal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/normal_cn.html#normal) ### [paddle.normal](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/normal_cn.html#normal)
```python ```python
paddle.normal(mean=0.0, std=1.0, shape=None, name=None) paddle.normal(mean=0.0, std=1.0, shape=None, name=None)
``` ```
......
...@@ -11,7 +11,7 @@ torch.ones(*size, ...@@ -11,7 +11,7 @@ torch.ones(*size,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.ones](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/ones_cn.html#ones) ### [paddle.ones](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ones_cn.html#ones)
```python ```python
paddle.ones(shape, paddle.ones(shape,
......
...@@ -11,7 +11,7 @@ torch.ones_like(input, ...@@ -11,7 +11,7 @@ torch.ones_like(input,
memory_format=torch.preserve_format) memory_format=torch.preserve_format)
``` ```
### [paddle.ones_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/ones_like_cn.html#ones-like) ### [paddle.ones_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/ones_like_cn.html#ones-like)
```python ```python
paddle.ones_like(x, dtype=None, name=None) paddle.ones_like(x, dtype=None, name=None)
......
...@@ -10,7 +10,7 @@ torch.rand(*size, ...@@ -10,7 +10,7 @@ torch.rand(*size,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.rand](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/rand_cn.html#rand) ### [paddle.rand](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/rand_cn.html#rand)
```python ```python
paddle.rand(shape, paddle.rand(shape,
......
...@@ -13,7 +13,7 @@ torch.randint(low=0, ...@@ -13,7 +13,7 @@ torch.randint(low=0,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.randint](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/randint_cn.html#randint) ### [paddle.randint](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randint_cn.html#randint)
```python ```python
paddle.randint(low=0, paddle.randint(low=0,
high=None, high=None,
......
...@@ -10,7 +10,7 @@ torch.randn(*size, ...@@ -10,7 +10,7 @@ torch.randn(*size,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.randn](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/randn_cn.html#randn) ### [paddle.randn](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randn_cn.html#randn)
```python ```python
paddle.randn(shape, paddle.randn(shape,
......
...@@ -11,7 +11,7 @@ torch.randperm(n, ...@@ -11,7 +11,7 @@ torch.randperm(n,
requires_grad=False, requires_grad=False,
pin_memory=False) pin_memory=False)
``` ```
### [paddle.randperm](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/random/randperm_cn.html#randperm) ### [paddle.randperm](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/randperm_cn.html#randperm)
```python ```python
paddle.randperm(n, dtype='int64', name=None) paddle.randperm(n, dtype='int64', name=None)
``` ```
......
...@@ -12,7 +12,7 @@ torch.range(start=0, ...@@ -12,7 +12,7 @@ torch.range(start=0,
device=None, device=None,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/arange_cn.html#arange) ### [paddle.arange](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/arange_cn.html#arange)
```python ```python
paddle.arange(start=0, paddle.arange(start=0,
end=None, end=None,
......
...@@ -8,7 +8,7 @@ torch.save(obj, ...@@ -8,7 +8,7 @@ torch.save(obj,
pickle_protocol=2) pickle_protocol=2)
``` ```
### [paddle.save](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/io/save_cn.html#save) ### [paddle.save](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/save_cn.html#save)
```python ```python
paddle.save(obj, path, pickle_protocol=2) paddle.save(obj, path, pickle_protocol=2)
......
...@@ -9,7 +9,7 @@ torch.tensor(data, ...@@ -9,7 +9,7 @@ torch.tensor(data,
pin_memory=False) pin_memory=False)
``` ```
### [paddle.to_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/to_tensor_cn.html#to-tensor) ### [paddle.to_tensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/to_tensor_cn.html#to-tensor)
```python ```python
paddle.to_tensor(data, paddle.to_tensor(data,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
torch.transpose(input, dim0, dim1) torch.transpose(input, dim0, dim1)
``` ```
### [paddle.transpose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/layers/transpose_cn.html#transpose) ### [paddle.transpose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/transpose_cn.html#transpose)
```python ```python
paddle.transpose(x, perm, name=None) paddle.transpose(x, perm, name=None)
......
...@@ -11,7 +11,7 @@ torch.zeros(*size, ...@@ -11,7 +11,7 @@ torch.zeros(*size,
requires_grad=False) requires_grad=False)
``` ```
### [paddle.zeros](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/zeros_cn.html#zeros) ### [paddle.zeros](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/zeros_cn.html#zeros)
```python ```python
paddle.zeros(shape, paddle.zeros(shape,
......
...@@ -11,7 +11,7 @@ torch.zeros_like(input, ...@@ -11,7 +11,7 @@ torch.zeros_like(input,
memory_format=torch.preserve_format) memory_format=torch.preserve_format)
``` ```
### [paddle.zeros_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/tensor/creation/zeros_like_cn.html#zeros-like) ### [paddle.zeros_like](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/zeros_like_cn.html#zeros-like)
```python ```python
paddle.zeros_like(x, dtype=None, name=None) paddle.zeros_like(x, dtype=None, name=None)
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
该文档梳理了与数据处理、分布式处理等相关的PyTorch-PaddlePaddle API映射列表。 该文档梳理了与数据处理、分布式处理等相关的PyTorch-PaddlePaddle API映射列表。
| 序号 | PyTorch API | PaddlePaddle API | 备注 | | 序号 | PyTorch API | PaddlePaddle API | 备注 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1 | [torch.nn.DataParallel](https://pytorch.org/docs/stable/generated/torch.nn.DataParallel.html?highlight=dataparallel#torch.nn.DataParallel) | [paddle.DataParallel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/parallel/DataParallel_cn.html#dataparallel) | [差异对比](torch.nn.DataParallel.md) | | 1 | [torch.nn.DataParallel](https://pytorch.org/docs/stable/generated/torch.nn.DataParallel.html?highlight=dataparallel#torch.nn.DataParallel) | [paddle.DataParallel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/DataParallel_cn.html#dataparallel) | [差异对比](torch.nn.DataParallel.md) |
| 2 | [torch.nn.parameter.Parameter](https://pytorch.org/docs/stable/generated/torch.nn.parameter.Parameter.html?highlight=torch%20nn%20parameter#torch.nn.parameter.Parameter) | [paddle.create_parameter](https://github.com/PaddlePaddle/Paddle/blob/ce2bdb0afdc2a09a127e8d9aa394c8b00a877364/python/paddle/fluid/layers/tensor.py#L77) | [差异对比](torch.nn.parameter.Parameter.md) | | 2 | [torch.nn.parameter.Parameter](https://pytorch.org/docs/stable/generated/torch.nn.parameter.Parameter.html?highlight=torch%20nn%20parameter#torch.nn.parameter.Parameter) | [paddle.create_parameter](https://github.com/PaddlePaddle/Paddle/blob/release/2.1/python/paddle/fluid/layers/tensor.py#L77) | [差异对比](torch.nn.parameter.Parameter.md) |
| 3 | [torch.nn.utils.clip_grad_value_](https://pytorch.org/docs/stable/generated/torch.nn.utils.clip_grad_value_.html?highlight=clip_grad_value_#torch.nn.utils.clip_grad_value_) | 无对应实现 | [组合实现](torch.nn.utils.clip_grad_value_.md) | | 3 | [torch.nn.utils.clip_grad_value_](https://pytorch.org/docs/stable/generated/torch.nn.utils.clip_grad_value_.html?highlight=clip_grad_value_#torch.nn.utils.clip_grad_value_) | 无对应实现 | [组合实现](torch.nn.utils.clip_grad_value_.md) |
| 4 | [torch.utils.data.DataLoader](https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader) | [paddle.io.DataLoader](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/reader/DataLoader_cn.html#dataloader) | [差异对比](torch.utils.data.DataLoader.md) | | 4 | [torch.utils.data.DataLoader](https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader) | [paddle.io.DataLoader](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/DataLoader_cn.html#dataloader) | [差异对比](torch.utils.data.DataLoader.md) |
| 5 | [torch.utils.data.random_split](https://pytorch.org/docs/stable/data.html?highlight=random_split#torch.utils.data.random_split) | 无对应实现 | [组合实现](torch.utils.data.random_split.md) | | 5 | [torch.utils.data.random_split](https://pytorch.org/docs/stable/data.html?highlight=random_split#torch.utils.data.random_split) | 无对应实现 | [组合实现](torch.utils.data.random_split.md) |
| 6 | [torch.utils.data.distributed.DistributedSampler](https://pytorch.org/docs/stable/data.html?highlight=distributedsampler#torch.utils.data.distributed.DistributedSampler) | 无对应实现 | [组合实现](torch.utils.data.distributed.DistributedSampler.md) | | 6 | [torch.utils.data.distributed.DistributedSampler](https://pytorch.org/docs/stable/data.html?highlight=distributedsampler#torch.utils.data.distributed.DistributedSampler) | 无对应实现 | [组合实现](torch.utils.data.distributed.DistributedSampler.md) |
| 7 | [torch.utils.data.Dataset](https://pytorch.org/docs/stable/data.html?highlight=torch%20utils%20data%20dataset#torch.utils.data.Dataset) | [paddle.io.Dataset](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dataloader/dataset/Dataset_cn.html#dataset) | 功能一致 | | 7 | [torch.utils.data.Dataset](https://pytorch.org/docs/stable/data.html?highlight=torch%20utils%20data%20dataset#torch.utils.data.Dataset) | [paddle.io.Dataset](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/Dataset_cn.html#dataset) | 功能一致 |
| 8 | [torch.utils.data.BatchSampler](https://pytorch.org/docs/stable/data.html?highlight=batchsampler#torch.utils.data.BatchSampler) | [paddle.io.BatchSampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dataloader/batch_sampler/BatchSampler_cn.html#batchsampler) | [差异对比](torch.utils.data.BatchSampler.md) | | 8 | [torch.utils.data.BatchSampler](https://pytorch.org/docs/stable/data.html?highlight=batchsampler#torch.utils.data.BatchSampler) | [paddle.io.BatchSampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/BatchSampler_cn.html#batchsampler) | [差异对比](torch.utils.data.BatchSampler.md) |
| 9 | [torch.utils.data.Sampler](https://pytorch.org/docs/stable/data.html?highlight=sampler#torch.utils.data.Sampler) | [paddle.io.Sampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dataloader/sampler/Sampler_cn.html#sampler) | 功能一致 | | 9 | [torch.utils.data.Sampler](https://pytorch.org/docs/stable/data.html?highlight=sampler#torch.utils.data.Sampler) | [paddle.io.Sampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/Sampler_cn.html#sampler) | 功能一致 |
***持续更新...*** ***持续更新...***
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0) torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)
``` ```
### [paddle.DataParallel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/parallel/DataParallel_cn.html#dataparallel) ### [paddle.DataParallel](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/DataParallel_cn.html#dataparallel)
```python ```python
paddle.DataParallel(layers, strategy=None, comm_buffer_size=25, last_comm_buffer_size=1) paddle.DataParallel(layers, strategy=None, comm_buffer_size=25, last_comm_buffer_size=1)
``` ```
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.nn.parameter.Parameter(data, requires_grad=True) torch.nn.parameter.Parameter(data, requires_grad=True)
``` ```
## [paddle.create_parameter](https://github.com/PaddlePaddle/Paddle/blob/ce2bdb0afdc2a09a127e8d9aa394c8b00a877364/python/paddle/fluid/layers/tensor.py#L77) ## [paddle.create_parameter](https://github.com/PaddlePaddle/Paddle/blob/release/2.1/python/paddle/fluid/layers/tensor.py#L77)
```python ```python
paddle.create_parameter(shape, paddle.create_parameter(shape,
dtype, dtype,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torch.utils.data.BatchSampler(sampler, batch_size, drop_last) torch.utils.data.BatchSampler(sampler, batch_size, drop_last)
``` ```
### [paddle.io.BatchSampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dataloader/batch_sampler/BatchSampler_cn.html#batchsampler) ### [paddle.io.BatchSampler](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/BatchSampler_cn.html#batchsampler)
```python ```python
paddle.io.BatchSampler(dataset=None, sampler=None, shuffle=Fasle, batch_size=1, drop_last=False) paddle.io.BatchSampler(dataset=None, sampler=None, shuffle=Fasle, batch_size=1, drop_last=False)
``` ```
......
...@@ -18,7 +18,7 @@ torch.utils.data.DataLoader(dataset, ...@@ -18,7 +18,7 @@ torch.utils.data.DataLoader(dataset,
persistent_workers=False) persistent_workers=False)
``` ```
### [paddle.io.DataLoader](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/reader/DataLoader_cn.html#dataloader) ### [paddle.io.DataLoader](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/DataLoader_cn.html#dataloader)
```python ```python
paddle.io.DataLoader(dataset, paddle.io.DataLoader(dataset,
feed_list=None, feed_list=None,
......
...@@ -3,20 +3,20 @@ ...@@ -3,20 +3,20 @@
该文档梳理了与视觉处理相关的PyTorch-PaddlePaddle API映射列表。 该文档梳理了与视觉处理相关的PyTorch-PaddlePaddle API映射列表。
| 序号 | PyTorch API | PaddlePaddle API | 备注 | | 序号 | PyTorch API | PaddlePaddle API | 备注 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- |
| 1 | [torchvision.transforms.Compose](https://pytorch.org/vision/stable/transforms.html?highlight=compose#torchvision.transforms.Compose) | [paddle.vision.transforms.Compose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Compose_cn.html#compose) | 功能一致 | | 1 | [torchvision.transforms.Compose](https://pytorch.org/vision/stable/transforms.html?highlight=compose#torchvision.transforms.Compose) | [paddle.vision.transforms.Compose](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Compose_cn.html#compose) | 功能一致 |
| 2 | [torchvision.transforms.ToPILImage](https://pytorch.org/vision/stable/transforms.html?highlight=topilimage#torchvision.transforms.ToPILImage) | 无对应实现 | [组合实现](torchvision.transforms.ToPILImage.md) | | 2 | [torchvision.transforms.ToPILImage](https://pytorch.org/vision/stable/transforms.html?highlight=topilimage#torchvision.transforms.ToPILImage) | 无对应实现 | [组合实现](torchvision.transforms.ToPILImage.md) |
| 3 | [torchvision.transforms.Resize](https://pytorch.org/vision/stable/transforms.html?highlight=resize#torchvision.transforms.Resize) | [paddle.vision.transforms.Resize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Resize_cn.html#resize) | 功能一致 | | 3 | [torchvision.transforms.Resize](https://pytorch.org/vision/stable/transforms.html?highlight=resize#torchvision.transforms.Resize) | [paddle.vision.transforms.Resize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Resize_cn.html#resize) | 功能一致 |
| 4 | [torchvision.transforms.ToTensor](https://pytorch.org/vision/stable/transforms.html?highlight=totensor#torchvision.transforms.ToTensor) | [paddle.vision.transforms.ToTensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/ToTensor_cn.html#totensor) | 功能一致 | | 4 | [torchvision.transforms.ToTensor](https://pytorch.org/vision/stable/transforms.html?highlight=totensor#torchvision.transforms.ToTensor) | [paddle.vision.transforms.ToTensor](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/ToTensor_cn.html#totensor) | 功能一致 |
| 5 | [torchvision.transforms.RandomHorizontalFlip](https://pytorch.org/vision/stable/transforms.html?highlight=randomhorizontalflip#torchvision.transforms.RandomHorizontalFlip) | [paddle.vision.transforms.RandomHorizontalFlip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomHorizontalFlip_cn.html#randomhorizontalflip) | 功能一致 | | 5 | [torchvision.transforms.RandomHorizontalFlip](https://pytorch.org/vision/stable/transforms.html?highlight=randomhorizontalflip#torchvision.transforms.RandomHorizontalFlip) | [paddle.vision.transforms.RandomHorizontalFlip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/RandomHorizontalFlip_cn.html#randomhorizontalflip) | 功能一致 |
| 6 | [torchvision.transforms.CenterCrop](https://pytorch.org/vision/stable/transforms.html?highlight=centercrop#torchvision.transforms.CenterCrop) | [paddle.vision.transforms.CenterCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/CenterCrop_cn.html#centercrop) | 功能一致 | | 6 | [torchvision.transforms.CenterCrop](https://pytorch.org/vision/stable/transforms.html?highlight=centercrop#torchvision.transforms.CenterCrop) | [paddle.vision.transforms.CenterCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/CenterCrop_cn.html#centercrop) | 功能一致 |
| 7 | [torchvision.transforms.ColorJitter](https://pytorch.org/vision/stable/transforms.html?highlight=colorjitter#torchvision.transforms.ColorJitter) | [paddle.vision.transforms.ColorJitter](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/ColorJitter_cn.html#colorjitter) | 功能一致 | | 7 | [torchvision.transforms.ColorJitter](https://pytorch.org/vision/stable/transforms.html?highlight=colorjitter#torchvision.transforms.ColorJitter) | [paddle.vision.transforms.ColorJitter](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/ColorJitter_cn.html#colorjitter) | 功能一致 |
| 8 | [torchvision.transforms.Grayscale](https://pytorch.org/vision/stable/transforms.html?highlight=grayscale#torchvision.transforms.Grayscale) | [paddle.vision.transforms.Grayscale](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Grayscale_cn.html#grayscale) | 功能一致 | | 8 | [torchvision.transforms.Grayscale](https://pytorch.org/vision/stable/transforms.html?highlight=grayscale#torchvision.transforms.Grayscale) | [paddle.vision.transforms.Grayscale](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Grayscale_cn.html#grayscale) | 功能一致 |
| 9 | [torchvision.transforms.Normalize](https://pytorch.org/vision/stable/transforms.html?highlight=normalize#torchvision.transforms.Normalize) | [paddle.vision.transforms.Normalize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Normalize_cn.html#normalize) | [差异对比](torchvision.transforms.Normalize.md) | | 9 | [torchvision.transforms.Normalize](https://pytorch.org/vision/stable/transforms.html?highlight=normalize#torchvision.transforms.Normalize) | [paddle.vision.transforms.Normalize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Normalize_cn.html#normalize) | [差异对比](torchvision.transforms.Normalize.md) |
| 10 | [torchvision.transforms.RandomResizedCrop](https://pytorch.org/vision/stable/transforms.html?highlight=randomresizedcrop#torchvision.transforms.RandomResizedCrop) | [paddle.vision.transforms.RandomResizedCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomResizedCrop_cn.html#randomresizedcrop) | 功能一致 | | 10 | [torchvision.transforms.RandomResizedCrop](https://pytorch.org/vision/stable/transforms.html?highlight=randomresizedcrop#torchvision.transforms.RandomResizedCrop) | [paddle.vision.transforms.RandomResizedCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/RandomResizedCrop_cn.html#randomresizedcrop) | 功能一致 |
| 11 | [torchvision.transforms.Pad](https://pytorch.org/vision/stable/transforms.html?highlight=pad#torchvision.transforms.Pad) | [paddle.vision.transforms.Pad](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Pad_cn.html#pad) | 功能一致 | | 11 | [torchvision.transforms.Pad](https://pytorch.org/vision/stable/transforms.html?highlight=pad#torchvision.transforms.Pad) | [paddle.vision.transforms.Pad](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Pad_cn.html#pad) | 功能一致 |
| 12 | [torchvision.transforms.RandomCrop](https://pytorch.org/vision/stable/transforms.html?highlight=randomcrop#torchvision.transforms.RandomCrop) | [paddle.vision.transforms.RandomCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomCrop_cn.html#randomcrop) | 功能一致 | | 12 | [torchvision.transforms.RandomCrop](https://pytorch.org/vision/stable/transforms.html?highlight=randomcrop#torchvision.transforms.RandomCrop) | [paddle.vision.transforms.RandomCrop](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomCrop_cn.html#randomcrop) | 功能一致 |
| 13 | [torchvision.transforms.RandomRotation](https://pytorch.org/vision/stable/transforms.html?highlight=randomrotation#torchvision.transforms.RandomRotation) | [paddle.vision.transforms.RandomRotation](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomRotation_cn.html#daimashili) | 功能一致 | | 13 | [torchvision.transforms.RandomRotation](https://pytorch.org/vision/stable/transforms.html?highlight=randomrotation#torchvision.transforms.RandomRotation) | [paddle.vision.transforms.RandomRotation](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/RandomCrop_cn.html#randomcrop) | 功能一致 |
| 14 | [torchvision.transforms.RandomVerticalFlip](https://pytorch.org/vision/stable/transforms.html?highlight=randomverticalflip#torchvision.transforms.RandomVerticalFlip) | [paddle.vision.transforms.RandomVerticalFlip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/RandomVerticalFlip_cn.html#randomverticalflip) | 功能一致 | | 14 | [torchvision.transforms.RandomVerticalFlip](https://pytorch.org/vision/stable/transforms.html?highlight=randomverticalflip#torchvision.transforms.RandomVerticalFlip) | [paddle.vision.transforms.RandomVerticalFlip](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/RandomVerticalFlip_cn.html#randomverticalflip) | 功能一致 |
| 15 | [torchvision.transforms.Lambda](https://pytorch.org/vision/stable/transforms.html?highlight=lambda#torchvision.transforms.Lambda) | 无对应实现 | [组合实现](torchvision.transforms.Lambda.md) | | 15 | [torchvision.transforms.Lambda](https://pytorch.org/vision/stable/transforms.html?highlight=lambda#torchvision.transforms.Lambda) | 无对应实现 | [组合实现](torchvision.transforms.Lambda.md) |
| 17 | [torchvision.utils.save_image](https://pytorch.org/vision/stable/utils.html?highlight=save_image#torchvision.utils.save_image) | 无对应实现 | [组合实现](torchvision.utils.save_image.md) | | 17 | [torchvision.utils.save_image](https://pytorch.org/vision/stable/utils.html?highlight=save_image#torchvision.utils.save_image) | 无对应实现 | [组合实现](torchvision.utils.save_image.md) |
| 18 | [torchvision.models 系列模型](https://pytorch.org/vision/stable/models.html?highlight=torchvision%20models) | X2Paddle提供 | [使用方式](torchvision.models.md) | | 18 | [torchvision.models 系列模型](https://pytorch.org/vision/stable/models.html?highlight=torchvision%20models) | X2Paddle提供 | [使用方式](torchvision.models.md) |
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
torchvision.transforms.Normalize(mean, std, inplace=False) torchvision.transforms.Normalize(mean, std, inplace=False)
``` ```
### [paddle.vision.transforms.Normalize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/transforms/Normalize_cn.html#normalize) ### [paddle.vision.transforms.Normalize](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/transforms/Normalize_cn.html#normalize)
```python ```python
paddle.vision.transforms.Normalize(mean=0.0, std=1.0, data_format='CHW', to_rgb=False, keys=None) paddle.vision.transforms.Normalize(mean=0.0, std=1.0, data_format='CHW', to_rgb=False, keys=None)
``` ```
......
...@@ -70,12 +70,6 @@ def arg_parser(): ...@@ -70,12 +70,6 @@ def arg_parser():
action="store_true", action="store_true",
default=False, default=False,
help="define input shape for tf model") help="define input shape for tf model")
parser.add_argument(
"--paddle_type",
"-pt",
type=_text_type,
default="dygraph",
help="define the paddle model type after converting(dygraph/static)")
parser.add_argument( parser.add_argument(
"--convert_torch_project", "--convert_torch_project",
"-tp", "-tp",
...@@ -97,10 +91,7 @@ def arg_parser(): ...@@ -97,10 +91,7 @@ def arg_parser():
return parser return parser
def tf2paddle(model_path, def tf2paddle(model_path, save_dir, define_input_shape=False):
save_dir,
define_input_shape=False,
paddle_type="dygraph"):
# check tensorflow installation and version # check tensorflow installation and version
try: try:
import os import os
...@@ -119,32 +110,21 @@ def tf2paddle(model_path, ...@@ -119,32 +110,21 @@ def tf2paddle(model_path,
return return
from x2paddle.decoder.tf_decoder import TFDecoder from x2paddle.decoder.tf_decoder import TFDecoder
if paddle_type == "dygraph": from x2paddle.op_mapper.tf2paddle.tf_op_mapper import TFOpMapper
from x2paddle.op_mapper.dygraph.tf2paddle.tf_op_mapper import TFOpMapper
else:
from x2paddle.op_mapper.static.tf2paddle.tf_op_mapper import TFOpMapper
print("Now translating model from tensorflow to paddle.") print("Now translating model from tensorflow to paddle.")
model = TFDecoder(model_path, define_input_shape=define_input_shape) model = TFDecoder(model_path, define_input_shape=define_input_shape)
mapper = TFOpMapper(model) mapper = TFOpMapper(model)
mapper.paddle_graph.build() mapper.paddle_graph.build()
if paddle_type == "dygraph": from x2paddle.optimizer.optimizer import GraphOptimizer
from x2paddle.optimizer.optimizer import GraphOptimizer graph_opt = GraphOptimizer(source_frame="tf")
graph_opt = GraphOptimizer(source_frame="tf", paddle_type=paddle_type) graph_opt.optimize(mapper.paddle_graph)
graph_opt.optimize(mapper.paddle_graph)
else:
from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer(source_frame="tf", paddle_type=paddle_type)
graph_opt.optimize(mapper.paddle_graph)
mapper.paddle_graph.gen_model(save_dir) mapper.paddle_graph.gen_model(save_dir)
def caffe2paddle(proto, weight, save_dir, caffe_proto, paddle_type): def caffe2paddle(proto, weight, save_dir, caffe_proto):
from x2paddle.decoder.caffe_decoder import CaffeDecoder from x2paddle.decoder.caffe_decoder import CaffeDecoder
if paddle_type == "dygraph": from x2paddle.op_mapper.caffe2paddle.caffe_op_mapper import CaffeOpMapper
from x2paddle.op_mapper.dygraph.caffe2paddle.caffe_op_mapper import CaffeOpMapper
else:
from x2paddle.op_mapper.static.caffe2paddle.caffe_op_mapper import CaffeOpMapper
import google.protobuf as gpb import google.protobuf as gpb
ver_part = gpb.__version__.split('.') ver_part = gpb.__version__.split('.')
version_satisfy = False version_satisfy = False
...@@ -158,13 +138,13 @@ def caffe2paddle(proto, weight, save_dir, caffe_proto, paddle_type): ...@@ -158,13 +138,13 @@ def caffe2paddle(proto, weight, save_dir, caffe_proto, paddle_type):
mapper.paddle_graph.build() mapper.paddle_graph.build()
print("Model optimizing ...") print("Model optimizing ...")
from x2paddle.optimizer.optimizer import GraphOptimizer from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer(source_frame="caffe", paddle_type=paddle_type) graph_opt = GraphOptimizer(source_frame="caffe")
graph_opt.optimize(mapper.paddle_graph) graph_opt.optimize(mapper.paddle_graph)
print("Model optimized.") print("Model optimized.")
mapper.paddle_graph.gen_model(save_dir) mapper.paddle_graph.gen_model(save_dir)
def onnx2paddle(model_path, save_dir, paddle_type): def onnx2paddle(model_path, save_dir):
# check onnx installation and version # check onnx installation and version
try: try:
import onnx import onnx
...@@ -178,10 +158,7 @@ def onnx2paddle(model_path, save_dir, paddle_type): ...@@ -178,10 +158,7 @@ def onnx2paddle(model_path, save_dir, paddle_type):
print("Now translating model from onnx to paddle.") print("Now translating model from onnx to paddle.")
from x2paddle.decoder.onnx_decoder import ONNXDecoder from x2paddle.decoder.onnx_decoder import ONNXDecoder
if paddle_type == "dygraph": from x2paddle.op_mapper.onnx2paddle.onnx_op_mapper import ONNXOpMapper
from x2paddle.op_mapper.dygraph.onnx2paddle.onnx_op_mapper import ONNXOpMapper
else:
from x2paddle.op_mapper.static.onnx2paddle.onnx_op_mapper import ONNXOpMapper
model = ONNXDecoder(model_path) model = ONNXDecoder(model_path)
mapper = ONNXOpMapper(model) mapper = ONNXOpMapper(model)
mapper.paddle_graph.build() mapper.paddle_graph.build()
...@@ -206,7 +183,7 @@ def pytorch2paddle(module, save_dir, jit_type="trace", input_examples=None): ...@@ -206,7 +183,7 @@ def pytorch2paddle(module, save_dir, jit_type="trace", input_examples=None):
print("Now translating model from pytorch to paddle.") print("Now translating model from pytorch to paddle.")
from x2paddle.decoder.pytorch_decoder import ScriptDecoder, TraceDecoder from x2paddle.decoder.pytorch_decoder import ScriptDecoder, TraceDecoder
from x2paddle.op_mapper.dygraph.pytorch2paddle.pytorch_op_mapper import PyTorchOpMapper from x2paddle.op_mapper.pytorch2paddle.pytorch_op_mapper import PyTorchOpMapper
if jit_type == "trace": if jit_type == "trace":
model = TraceDecoder(module, input_examples) model = TraceDecoder(module, input_examples)
...@@ -216,8 +193,7 @@ def pytorch2paddle(module, save_dir, jit_type="trace", input_examples=None): ...@@ -216,8 +193,7 @@ def pytorch2paddle(module, save_dir, jit_type="trace", input_examples=None):
mapper.paddle_graph.build() mapper.paddle_graph.build()
print("Model optimizing ...") print("Model optimizing ...")
from x2paddle.optimizer.optimizer import GraphOptimizer from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer( graph_opt = GraphOptimizer(source_frame="pytorch", jit_type=jit_type)
source_frame="pytorch", paddle_type="dygraph", jit_type=jit_type)
graph_opt.optimize(mapper.paddle_graph) graph_opt.optimize(mapper.paddle_graph)
print("Model optimized.") print("Model optimized.")
mapper.paddle_graph.gen_model(save_dir, jit_type=jit_type) mapper.paddle_graph.gen_model(save_dir, jit_type=jit_type)
...@@ -242,8 +218,6 @@ def main(): ...@@ -242,8 +218,6 @@ def main():
if not args.convert_torch_project: if not args.convert_torch_project:
assert args.framework is not None, "--framework is not defined(support tensorflow/caffe/onnx)" assert args.framework is not None, "--framework is not defined(support tensorflow/caffe/onnx)"
assert args.save_dir is not None, "--save_dir is not defined" assert args.save_dir is not None, "--save_dir is not defined"
assert args.paddle_type in ["dygraph", "static"
], "--paddle_type must be 'dygraph' or 'static'"
try: try:
import platform import platform
...@@ -274,16 +248,15 @@ def main(): ...@@ -274,16 +248,15 @@ def main():
define_input_shape = False define_input_shape = False
if args.define_input_shape: if args.define_input_shape:
define_input_shape = True define_input_shape = True
tf2paddle(args.model, args.save_dir, define_input_shape, tf2paddle(args.model, args.save_dir, define_input_shape)
args.paddle_type)
elif args.framework == "caffe": elif args.framework == "caffe":
assert args.prototxt is not None and args.weight is not None, "--prototxt and --weight should be defined while translating caffe model" assert args.prototxt is not None and args.weight is not None, "--prototxt and --weight should be defined while translating caffe model"
caffe2paddle(args.prototxt, args.weight, args.save_dir, caffe2paddle(args.prototxt, args.weight, args.save_dir,
args.caffe_proto, args.paddle_type) args.caffe_proto)
elif args.framework == "onnx": elif args.framework == "onnx":
assert args.model is not None, "--model should be defined while translating onnx model" assert args.model is not None, "--model should be defined while translating onnx model"
onnx2paddle(args.model, args.save_dir, args.paddle_type) onnx2paddle(args.model, args.save_dir)
elif args.framework == "paddle2onnx": elif args.framework == "paddle2onnx":
print( print(
"Paddle to ONNX tool has been migrated to the new github: https://github.com/PaddlePaddle/paddle2onnx" "Paddle to ONNX tool has been migrated to the new github: https://github.com/PaddlePaddle/paddle2onnx"
......
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.core.graph import GraphNode
from x2paddle.core.util import *
import collections
import six
class Layer(object):
def __init__(self):
self.op = None
self.param_attr = dict()
self.inputs = dict()
self.output = None
self.is_custom_layer = False
self.use_fluid = False
def get_code(self):
layer_code = ""
if self.output is not None:
if isinstance(self.output, six.string_types):
layer_code = self.output + " = "
else:
layer_code = self.output.layer_name + " = "
if self.is_custom_layer:
layer_code = layer_code + self.op + "("
elif self.op == "=":
layer_code = layer_code
elif self.use_fluid:
layer_code = layer_code + "fluid." + self.op + "("
elif self.op == "full_like":
layer_code = layer_code + "paddle." + self.op + "("
else:
layer_code = layer_code + "fluid.layers." + self.op + "("
if isinstance(self.inputs, list):
in_list = "["
for input in self.inputs:
if isinstance(input, GraphNode):
if hasattr(input, "index"):
in_list += (
input.layer_name + "[{}]".format(input.index) + ", "
)
else:
in_list += (input.layer_name + ", ")
elif isinstance(input, six.string_types):
in_list += (input + ", ")
else:
raise Exception(
"Element of inputs should GraphNode or String")
in_list = in_list.strip(", ") + "], "
layer_code += in_list
elif isinstance(self.inputs, dict):
inputs = collections.OrderedDict(self.inputs)
for key, input in inputs.items():
if isinstance(input, GraphNode):
if hasattr(input, "index"):
layer_code = layer_code + key + "={}, ".format(
input.layer_name + "[{}]".format(input.index))
else:
layer_code = layer_code + key + "={}, ".format(
input.layer_name)
else:
layer_code = layer_code + key + "={}, ".format(input)
elif isinstance(self.inputs, GraphNode):
if hasattr(self.inputs, "index"):
layer_code += (
self.inputs.layer_name + "[{}]".format(self.inputs.index))
else:
layer_code += (self.inputs.layer_name)
if self.op != "=":
layer_code += ", "
elif isinstance(self.inputs, six.string_types):
layer_code += (self.inputs)
if self.op != "=":
layer_code += ", "
else:
raise Exception("Unknown type of inputs.")
param_attr = collections.OrderedDict(self.param_attr)
for key, value in param_attr.items():
if '\n' in str(value):
value = string(str(value).replace('\n', ','))
if str(key) == 'attr':
value = 'ParamAttr(' + str(value) + ')'
layer_code = layer_code + key + "={}, ".format(value)
layer_code = layer_code.strip(", ")
if self.op != "=":
layer_code += ")"
return layer_code
class FluidCode(object):
def __init__(self):
self.layers = list()
def add_layer(self,
op,
inputs,
output,
param_attr=None,
use_fluid=False,
is_custom_layer=False):
layer = Layer()
layer.op = op
layer.use_fluid = use_fluid
layer.is_custom_layer = is_custom_layer
if inputs is not None:
layer.inputs = inputs
layer.output = output
if param_attr is not None:
layer.param_attr = param_attr
self.layers.append(layer)
def add_note(self, note):
# note should be string
self.layers.append(note)
def clear(self):
self.layers = list()
def gen_codes(self):
codes = list()
for layer in self.layers:
if isinstance(layer, Layer):
codes.append(layer.get_code())
elif isinstance(layer, six.string_types):
codes.append(layer)
return codes
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle.fluid as fluid
from paddle.fluid.proto import framework_pb2
from x2paddle.core.util import *
import inspect
import os
def export_paddle_param(param, param_name, dir):
dtype_map = {
"int16": [framework_pb2.VarType.INT16, 'h'],
"int32": [framework_pb2.VarType.INT32, 'i'],
"int64": [framework_pb2.VarType.INT64, 'q'],
"float16": [framework_pb2.VarType.FP16, 'e'],
"float32": [framework_pb2.VarType.FP32, 'f'],
"float64": [framework_pb2.VarType.FP64, 'd'],
"bool": [framework_pb2.VarType.BOOL, None]
}
shape = param.shape
if str(param.dtype) in ['uint8', 'uint_8', 'bool']:
param = param.astype('int64')
if len(shape) == 0:
assert param.size == 1, "Unexpected situation happend!"
shape = [1]
assert str(
param.dtype) in dtype_map, "Unknown dtype {} of params: {}.".format(
str(param.dtype), param_name)
fp = open(os.path.join(dir, param_name), 'wb')
numpy.array([0], dtype='int32').tofile(fp)
numpy.array([0], dtype='int64').tofile(fp)
numpy.array([0], dtype='int32').tofile(fp)
tensor_desc = framework_pb2.VarType.TensorDesc()
tensor_desc.data_type = dtype_map[str(param.dtype)][0]
tensor_desc.dims.extend(shape)
desc_size = tensor_desc.ByteSize()
numpy.array([desc_size], dtype='int32').tofile(fp)
fp.write(tensor_desc.SerializeToString())
param.tofile(fp)
fp.close()
# This func will copy to generate code file
def run_net(param_dir="./"):
import os
inputs, outputs = x2paddle_net()
ops = fluid.default_main_program().global_block().ops
used_vars = list()
for op in ops:
used_vars += op.input_arg_names
tmp = list()
for input in inputs:
if isinstance(input, list):
for ipt in input:
if ipt.name not in used_vars:
continue
tmp.append(ipt)
else:
if input.name not in used_vars:
continue
tmp.append(input)
inputs = tmp
for i, out in enumerate(outputs):
if isinstance(out, list):
for out_part in out:
outputs.append(out_part)
del outputs[i]
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
def if_exist(var):
b = os.path.exists(os.path.join(param_dir, var.name))
return b
fluid.io.load_vars(
exe, param_dir, fluid.default_main_program(), predicate=if_exist)
class OpMapper(object):
def __init__(self):
self.paddle_codes = ""
self.tab = " "
self.net_code = list()
self.weights = dict()
self.inputs = list()
self.outputs = list()
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op):
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
print("There are {} ops not supported yet, list as below".format(
len(unsupported_ops)))
for op in unsupported_ops:
print(op)
return False
def add_codes(self, codes, indent=0):
if isinstance(codes, list):
for code in codes:
self.paddle_codes += (
self.tab * indent + code.strip('\n') + '\n')
elif isinstance(codes, str):
self.paddle_codes += (self.tab * indent + codes.strip('\n') + '\n')
else:
raise Exception("Unknown type of codes")
def add_heads(self):
self.add_codes("from paddle.fluid.initializer import Constant")
self.add_codes("from paddle.fluid.param_attr import ParamAttr")
self.add_codes("import paddle.fluid as fluid")
self.add_codes("import paddle")
self.add_codes("")
def save_inference_model(self, save_dir, params_merge):
self.save_python_model(save_dir)
import sys
import paddle.fluid as fluid
py_code_dir = os.path.join(save_dir, "model_with_code")
sys.path.append(py_code_dir)
import model
try:
inputs, outputs = model.x2paddle_net()
ops = fluid.default_main_program().global_block().ops
used_vars = list()
for op in ops:
used_vars += op.input_arg_names
for i, out in enumerate(outputs):
if isinstance(out, list):
for out_part in out:
outputs.append(out_part)
del outputs[i]
input_names = list()
for input in inputs:
if isinstance(input, list):
for ipt in input:
if ipt.name not in used_vars:
continue
input_names.append(ipt.name)
else:
if input.name not in used_vars:
continue
input_names.append(input.name)
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
def if_exist(var):
b = os.path.exists(
os.path.join(os.path.join(py_code_dir, var.name)))
return b
fluid.io.load_vars(
exe,
py_code_dir,
fluid.default_main_program(),
predicate=if_exist)
if params_merge:
fluid.io.save_inference_model(
dirname=os.path.join(save_dir, "inference_model"),
feeded_var_names=input_names,
target_vars=outputs,
executor=exe,
params_filename="__params__")
else:
fluid.io.save_inference_model(
dirname=os.path.join(save_dir, "inference_model"),
feeded_var_names=input_names,
target_vars=outputs,
executor=exe,
params_filename=None)
except:
raise Exception(
"Paddle code was saved in {}/model.py, but seems there's wrong exist, please check model.py manually."
.format(py_code_dir))
def save_python_model(self, save_dir):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
py_code_dir = os.path.join(save_dir, "model_with_code")
if not os.path.exists(py_code_dir):
os.makedirs(py_code_dir)
for name, param in self.weights.items():
export_paddle_param(param, name, py_code_dir)
self.add_heads()
if hasattr(self, "used_custom_layers"):
for _, layer_code in self.used_custom_layers.items():
self.add_codes(layer_code, 0)
self.add_codes("", 0)
self.add_codes("\ndef x2paddle_net():", 0)
self.add_codes("paddle.enable_static()", 1)
for i in range(len(self.graph.topo_sort)):
node_name = self.graph.topo_sort[i]
node = self.graph.get_node(node_name)
if node is None:
continue
if len(node.fluid_code.layers) == 0:
continue
self.add_codes(node.fluid_code.gen_codes(), 1)
self.add_codes("", 0)
input_str = "["
for name in self.graph.input_nodes:
input_str += (name + ", ")
input_str = input_str.strip(", ") + "]"
output_str = "["
for name in self.graph.output_nodes:
output_str += (name + ", ")
output_str = output_str.strip(", ") + "]"
return_code = "return {}, {}".format(input_str, output_str)
self.add_codes(return_code, 1)
self.add_codes("", 0)
self.add_codes(inspect.getsourcelines(run_net)[0])
fp = open(os.path.join(py_code_dir, "model.py"), 'w')
fp.write(self.paddle_codes)
fp.close()
...@@ -16,15 +16,12 @@ ...@@ -16,15 +16,12 @@
from __future__ import print_function from __future__ import print_function
from __future__ import division from __future__ import division
import paddle import paddle
from paddle.fluid.proto import framework_pb2
import collections import collections
import numpy
import sys import sys
import os import os
import six import six
import pickle import pickle
import numpy as np from os import path as osp
from os import path as osp
from x2paddle.core.util import * from x2paddle.core.util import *
...@@ -57,14 +54,13 @@ class PaddleLayer(object): ...@@ -57,14 +54,13 @@ class PaddleLayer(object):
self.attrs = kwargs self.attrs = kwargs
self.id = id self.id = id
self.blocks = list() self.blocks = list()
def add_block(self, block): def add_block(self, block):
self.blocks.append(block) self.blocks.append(block)
class PaddleGraph(object): class PaddleGraph(object):
def __init__(self, source_type=None, parent_layer=None, graph_type="static"): def __init__(self, source_type=None, parent_layer=None):
self.layers = collections.OrderedDict() self.layers = collections.OrderedDict()
self.edges_out = dict() self.edges_out = dict()
self.edges_in = dict() self.edges_in = dict()
...@@ -72,7 +68,6 @@ class PaddleGraph(object): ...@@ -72,7 +68,6 @@ class PaddleGraph(object):
self.outputs = list() self.outputs = list()
self.parameters = dict() self.parameters = dict()
self.parent_layer = parent_layer self.parent_layer = parent_layer
self.graph_type = graph_type
self.source_type = source_type self.source_type = source_type
self.custom_code = None self.custom_code = None
self.inputs_info = None self.inputs_info = None
...@@ -83,13 +78,13 @@ class PaddleGraph(object): ...@@ -83,13 +78,13 @@ class PaddleGraph(object):
def set_parameters(self, parameters): def set_parameters(self, parameters):
self.parameters = parameters self.parameters = parameters
def set_custom(self, custom_code): def set_custom(self, custom_code):
self.custom_code = custom_code self.custom_code = custom_code
def set_inputs_info(self, inputs_info): def set_inputs_info(self, inputs_info):
self.inputs_info = inputs_info self.inputs_info = inputs_info
def set_script(self, script): def set_script(self, script):
self.script = script self.script = script
...@@ -111,7 +106,8 @@ class PaddleGraph(object): ...@@ -111,7 +106,8 @@ class PaddleGraph(object):
layer_id = "{}.{}.{}".format(self.parent_layer.id, layer_id = "{}.{}.{}".format(self.parent_layer.id,
len(self.parent_layer.blocks), len(self.parent_layer.blocks),
layer_id) layer_id)
layer = PaddleLayer(layer_id, kernel, inputs, outputs, scope_name=scope_name, **kwargs) layer = PaddleLayer(
layer_id, kernel, inputs, outputs, scope_name=scope_name, **kwargs)
self.layers[layer_id] = layer self.layers[layer_id] = layer
if layer.kernel in ["prim.list_unpack" or "prim.tuple_unpack"]: if layer.kernel in ["prim.list_unpack" or "prim.tuple_unpack"]:
self.has_unpack = True self.has_unpack = True
...@@ -214,7 +210,8 @@ class PaddleGraph(object): ...@@ -214,7 +210,8 @@ class PaddleGraph(object):
and layer.kernel != "prim.exception" \ and layer.kernel != "prim.exception" \
and layer.kernel != "prim.warnings" \ and layer.kernel != "prim.warnings" \
and layer.outputs[0] not in self.outputs: and layer.outputs[0] not in self.outputs:
if layer.kernel == "paddle.to_tensor" and layer.outputs[0] in self.inputs_info: if layer.kernel == "paddle.to_tensor" and layer.outputs[
0] in self.inputs_info:
self.inputs_info.pop(layer.outputs[0]) self.inputs_info.pop(layer.outputs[0])
if layer.outputs[0] in self.inputs: if layer.outputs[0] in self.inputs:
self.inputs.pop(self.inputs.index(layer.outputs[0])) self.inputs.pop(self.inputs.index(layer.outputs[0]))
...@@ -222,10 +219,9 @@ class PaddleGraph(object): ...@@ -222,10 +219,9 @@ class PaddleGraph(object):
for layer_id in invalid_list: for layer_id in invalid_list:
self.layers.pop(layer_id) self.layers.pop(layer_id)
if self.graph_type == "dygraph": self.get_inputs()
self.get_dygraph_inputs() if len(self.outputs) == 0:
if len(self.outputs) == 0: self.get_outputs()
self.get_dygraph_outputs()
def get_global_layers(self): def get_global_layers(self):
# 该全局layers的信息是按照拓扑排序组成的 # 该全局layers的信息是按照拓扑排序组成的
...@@ -237,43 +233,12 @@ class PaddleGraph(object): ...@@ -237,43 +233,12 @@ class PaddleGraph(object):
block_global_layers = update(block.layers) block_global_layers = update(block.layers)
global_layers.update(block_global_layers) global_layers.update(block_global_layers)
return global_layers return global_layers
return update(self.layers) return update(self.layers)
def gen_model(self, save_dir, jit_type=None): def gen_model(self, save_dir, jit_type=None):
if not osp.exists(save_dir): if not osp.exists(save_dir):
os.makedirs(save_dir) os.makedirs(save_dir)
if self.graph_type == "static":
self.gen_static_model(save_dir)
else:
self.gen_dygraph_model(save_dir, jit_type)
def gen_static_model(self, save_dir):
code_dir = osp.join(save_dir, 'model_with_code')
infer_dir = osp.join(save_dir, 'inference_model')
self.gen_static_code(code_dir)
sys.path.append(code_dir)
import x2paddle_model
paddle.enable_static()
scope = paddle.static.Scope()
startup_program = paddle.static.Program()
main_program = paddle.static.Program()
with paddle.static.scope_guard(scope):
with paddle.static.program_guard(main_program, startup_program):
inputs, outputs = x2paddle_model.x2paddle_net()
exe = paddle.static.Executor(paddle.CPUPlace())
exe.run(startup_program)
param_dir = osp.join(code_dir, 'weights')
for k, v in self.parameters.items():
if scope.find_var(k):
self.dump_parameter(k, v, param_dir)
paddle.static.load(main_program, param_dir, exe)
paddle.static.save_inference_model(
path_prefix=osp.join(infer_dir, "model"),
feed_vars=[i for i in inputs],
fetch_vars=outputs,
executor=exe)
def gen_dygraph_model(self, save_dir, jit_type=None):
if jit_type == "trace": if jit_type == "trace":
if not self.has_unpack: if not self.has_unpack:
from x2paddle.optimizer.pytorch_code_optimizer import HierarchicalTree from x2paddle.optimizer.pytorch_code_optimizer import HierarchicalTree
...@@ -281,22 +246,23 @@ class PaddleGraph(object): ...@@ -281,22 +246,23 @@ class PaddleGraph(object):
for layer_id, layer in self.layers.items(): for layer_id, layer in self.layers.items():
hierarchical_tree.insert(layer) hierarchical_tree.insert(layer)
hierarchical_tree.save_source_files(save_dir) hierarchical_tree.save_source_files(save_dir)
self.dump_dygraph_parameter(save_dir) self.dump_parameter(save_dir)
else: else:
self.gen_dygraph_code(save_dir) self.gen_code(save_dir)
self.dump_dygraph_parameter(save_dir) self.dump_parameter(save_dir)
else: else:
if self.source_type == "pytorch": if self.source_type == "pytorch":
from x2paddle.optimizer.pytorch_code_optimizer import ModuleGraph from x2paddle.optimizer.pytorch_code_optimizer import ModuleGraph
module_graph = ModuleGraph(self) module_graph = ModuleGraph(self)
module_graph.save_source_files(save_dir) module_graph.save_source_files(save_dir)
self.dump_dygraph_parameter(save_dir) self.dump_parameter(save_dir)
else: else:
self.gen_dygraph_code(save_dir) self.gen_code(save_dir)
self.dump_dygraph_parameter(save_dir) self.dump_parameter(save_dir)
# 动转静 # 动转静
code_path = osp.join(osp.abspath(save_dir), "x2paddle_code.py") code_path = osp.join(osp.abspath(save_dir), "x2paddle_code.py")
print("Exporting inference model from python code ('{}')... \n".format(code_path)) print("Exporting inference model from python code ('{}')... \n".format(
code_path))
if len(self.inputs_info) > 0: if len(self.inputs_info) > 0:
input_shapes = list() input_shapes = list()
input_types = list() input_types = list()
...@@ -306,130 +272,13 @@ class PaddleGraph(object): ...@@ -306,130 +272,13 @@ class PaddleGraph(object):
try: try:
self.dygraph2static(save_dir, input_shapes, input_types) self.dygraph2static(save_dir, input_shapes, input_types)
except Exception as e: except Exception as e:
print("Fail to generate inference model! Problem happend while export inference model from python code '{}';\n".format(code_path)) print(
"Fail to generate inference model! Problem happend while export inference model from python code '{}';\n".
format(code_path))
print("===================Error Information===============") print("===================Error Information===============")
raise e raise e
def gen_static_code(self, code_dir): def get_inputs(self):
def write_code(f, code_list, indent=0):
indent_blank = " " * indent
for code_line in code_list:
if code_line.strip() == "":
f.write('\n')
else:
f.write(indent_blank + code_line + '\n')
if not osp.exists(code_dir):
os.makedirs(code_dir)
f = open(osp.join(code_dir, 'x2paddle_model.py'), 'w')
if self.source_type == "caffe":
custom_import = "from x2paddle.op_mapper.static.caffe2paddle " + \
"import caffe_custom_layer as x2paddle_nn"
elif self.source_type == "onnx":
custom_import = "from x2paddle.op_mapper.static.onnx2paddle " + \
"import onnx_custom_layer as x2paddle_nn"
else:
custom_import = ""
write_code(
f, [
custom_import,
"import paddle",
"import math",
"",
],
indent=0)
if self.custom_code is not None:
write_code(
f,
list(self.custom_code.values()),
indent=0)
write_code(f,
["", "def x2paddle_net():"],
indent=0)
write_code(
f, [
"paddle.enable_static()"
],
indent=1)
for layer_id, layer in self.layers.items():
if layer.kernel.startswith("paddle"):
remove_default_attrs(layer.kernel, layer.attrs)
edges_in = self.edges_in.get(layer_id, [])
edges_out = self.edges_out.get(layer_id, [])
if len(edges_in) == 0 and len(edges_out) == 0 and layer.outputs[0] not in self.outputs:
if layer.outputs[0] in self.inputs:
self.inputs.pop(self.inputs.index(layer.outputs[0]))
continue
line = ""
if len(layer.outputs) == 1:
line = layer.outputs[0]
else:
for output in layer.outputs:
line += "{}, ".format(output)
line = line.strip(", ")
if layer.kernel.startswith("custom_layer"):
line += "= x2paddle_nn.{}(".format(layer.kernel.split(":")[-1])
else:
line += " = {}(".format(layer.kernel)
for k, v in layer.inputs.items():
if isinstance(v, list):
line += "{}=[{}], ".format(k, ", ".join(v))
else:
line += "{}={}, ".format(k, v)
for k, v in layer.attrs.items():
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
write_code(f, [line], indent=1)
write_code(
f, [
"return [{}], [{}]".format(", ".join(self.inputs),
", ".join(self.outputs))
],
indent=1)
f.close()
def dump_parameter(self, param_name, param, save_dir):
if not osp.exists(save_dir):
os.makedirs(save_dir)
dtype_map = {
"int16": [framework_pb2.VarType.INT16, 'h'],
"int32": [framework_pb2.VarType.INT32, 'i'],
"int64": [framework_pb2.VarType.INT64, 'q'],
"float16": [framework_pb2.VarType.FP16, 'e'],
"float32": [framework_pb2.VarType.FP32, 'f'],
"float64": [framework_pb2.VarType.FP64, 'd'],
"bool": [framework_pb2.VarType.BOOL, None]
}
shape = param.shape
if str(param.dtype) in ['uint8', 'uint_8', 'bool']:
param = param.astype('int64')
if len(shape) == 0:
assert param.size == 1, "Unexpected situation happend!"
shape = [1]
assert str(
param.dtype) in dtype_map, "Unknown dtype {} of params: {}.".format(
str(param.dtype), param_name)
fp = open(osp.join(save_dir, param_name), 'wb')
numpy.array([0], dtype='int32').tofile(fp)
numpy.array([0], dtype='int64').tofile(fp)
numpy.array([0], dtype='int32').tofile(fp)
tensor_desc = framework_pb2.VarType.TensorDesc()
tensor_desc.data_type = dtype_map[str(param.dtype)][0]
tensor_desc.dims.extend(shape)
desc_size = tensor_desc.ByteSize()
numpy.array([desc_size], dtype='int32').tofile(fp)
fp.write(tensor_desc.SerializeToString())
param.tofile(fp)
fp.close()
def get_dygraph_inputs(self):
def update(layers): def update(layers):
for layer_id, layer in layers.items(): for layer_id, layer in layers.items():
if self.edges_in.get(layer_id, 0) == 0 and self.edges_out.get( if self.edges_in.get(layer_id, 0) == 0 and self.edges_out.get(
...@@ -440,7 +289,7 @@ class PaddleGraph(object): ...@@ -440,7 +289,7 @@ class PaddleGraph(object):
self.inputs.append(data) self.inputs.append(data)
if len(layer.blocks) > 0: if len(layer.blocks) > 0:
for block in layer.blocks: for block in layer.blocks:
block.get_dygraph_inputs() block.get_inputs()
self.inputs.extend(block.inputs) self.inputs.extend(block.inputs)
update(self.layers) update(self.layers)
...@@ -448,21 +297,22 @@ class PaddleGraph(object): ...@@ -448,21 +297,22 @@ class PaddleGraph(object):
if self.inputs is not None: if self.inputs is not None:
self.inputs.sort() self.inputs.sort()
def get_dygraph_outputs(self): def get_outputs(self):
for layer_id, layer in self.layers.items(): for layer_id, layer in self.layers.items():
if self.edges_in.get(layer_id, 0) == 0 and self.edges_out.get( if self.edges_in.get(layer_id, 0) == 0 and self.edges_out.get(
layer_id, 0) == 0: layer_id, 0) == 0:
continue continue
if self.edges_out.get(layer_id, 0) == 0: if self.edges_out.get(layer_id, 0) == 0:
for i, output_name in enumerate(layer.outputs): for i, output_name in enumerate(layer.outputs):
if ("paddle.nn" in layer.kernel and "functional" not in layer.kernel): if ("paddle.nn" in layer.kernel and
"functional" not in layer.kernel):
if i == 0: if i == 0:
continue continue
if output_name not in self.outputs: if output_name not in self.outputs:
self.outputs.append(output_name) self.outputs.append(output_name)
def gen_dygraph_code(self, code_dir=None, indent=2): def gen_code(self, code_dir=None, indent=2):
def gen_codes(code_list, indent=0): def gen_codes(code_list, indent=0):
indent_blank = " " * indent indent_blank = " " * indent
codes = [] codes = []
...@@ -475,13 +325,13 @@ class PaddleGraph(object): ...@@ -475,13 +325,13 @@ class PaddleGraph(object):
def gen_head(): def gen_head():
if self.source_type == "caffe": if self.source_type == "caffe":
custom_import = "from x2paddle.op_mapper.dygraph.caffe2paddle " + \ custom_import = "from x2paddle.op_mapper.caffe2paddle " + \
"import caffe_custom_layer as x2paddle_nn" "import caffe_custom_layer as x2paddle_nn"
elif self.source_type == "pytorch": elif self.source_type == "pytorch":
custom_import = "from x2paddle.op_mapper.dygraph.pytorch2paddle " + \ custom_import = "from x2paddle.op_mapper.pytorch2paddle " + \
"import pytorch_custom_layer as x2paddle_nn" "import pytorch_custom_layer as x2paddle_nn"
elif self.source_type == "onnx": elif self.source_type == "onnx":
custom_import = "from x2paddle.op_mapper.dygraph.onnx2paddle " + \ custom_import = "from x2paddle.op_mapper.onnx2paddle " + \
"import onnx_custom_layer as x2paddle_nn" "import onnx_custom_layer as x2paddle_nn"
else: else:
custom_import = "" custom_import = ""
...@@ -495,9 +345,7 @@ class PaddleGraph(object): ...@@ -495,9 +345,7 @@ class PaddleGraph(object):
], ],
indent=0) indent=0)
input_data_name = ', '.join(self.inputs) input_data_name = ', '.join(self.inputs)
self.init_func.extend( self.init_func.extend(gen_codes(["def __init__(self):"], indent=1))
gen_codes(
["def __init__(self):"], indent=1))
self.init_func.extend( self.init_func.extend(
gen_codes( gen_codes(
["super({}, self).__init__()".format(self.name)], indent=2)) ["super({}, self).__init__()".format(self.name)], indent=2))
...@@ -505,32 +353,34 @@ class PaddleGraph(object): ...@@ -505,32 +353,34 @@ class PaddleGraph(object):
gen_codes( gen_codes(
["def forward(self, {}):".format(input_data_name)], ["def forward(self, {}):".format(input_data_name)],
indent=1)) indent=1))
def gen_main_code(code_dir): def gen_main_code(code_dir):
input_data_name = ', '.join(self.inputs) input_data_name = ', '.join(self.inputs)
self.run_func = gen_codes( self.run_func = gen_codes(
[ [
"", "",
"def main({}):".format(input_data_name), "def main({}):".format(input_data_name),
], ], indent=0)
indent=0)
comment_list = list() comment_list = list()
comment_list.append("# There are {} inputs.".format(len(self.inputs_info))) comment_list.append("# There are {} inputs.".format(
len(self.inputs_info)))
for k, v in self.inputs_info.items(): for k, v in self.inputs_info.items():
comment_list.append("# {}: shape-{}, type-{}.".format(k, v[0], v[1])) comment_list.append("# {}: shape-{}, type-{}.".format(k, v[0],
v[1]))
self.run_func.extend(gen_codes(comment_list, indent=1))
use_structured_name = False if self.source_type in ["tf"] else True
self.run_func.extend( self.run_func.extend(
gen_codes( gen_codes(
comment_list, [
"paddle.disable_static()",
"params = paddle.load('{}')".format(
osp.join(osp.abspath(code_dir), "model.pdparams")),
"model = {}()".format(self.name),
"model.set_dict(params, use_structured_name={})".format(
use_structured_name), "model.eval()",
"out = model({})".format(input_data_name), "return out"
],
indent=1)) indent=1))
use_structured_name = False if self.source_type in ["tf"] else True
self.run_func.extend(
gen_codes(["paddle.disable_static()",
"params = paddle.load('{}')".format(osp.join(osp.abspath(code_dir), "model.pdparams")),
"model = {}()".format(self.name),
"model.set_dict(params, use_structured_name={})".format(use_structured_name),
"model.eval()",
"out = model({})".format(input_data_name),
"return out"], indent=1))
def write_code(code_dir): def write_code(code_dir):
f = open(osp.join(code_dir, 'x2paddle_code.py'), 'w') f = open(osp.join(code_dir, 'x2paddle_code.py'), 'w')
...@@ -570,7 +420,8 @@ class PaddleGraph(object): ...@@ -570,7 +420,8 @@ class PaddleGraph(object):
"data"].startswith("params[") else "self.{}".format( "data"].startswith("params[") else "self.{}".format(
layer.outputs[0]) layer.outputs[0])
if layer.kernel.startswith("custom_layer"): if layer.kernel.startswith("custom_layer"):
line += "= x2paddle_nn.{}(".format(layer.kernel.split(":")[-1]) line += "= x2paddle_nn.{}(".format(
layer.kernel.split(":")[-1])
else: else:
line += " = {}(".format(layer.kernel) line += " = {}(".format(layer.kernel)
for k, v in layer.attrs.items(): for k, v in layer.attrs.items():
...@@ -591,7 +442,8 @@ class PaddleGraph(object): ...@@ -591,7 +442,8 @@ class PaddleGraph(object):
line = layer.outputs[1] line = layer.outputs[1]
else: else:
if layer.kernel in ["paddle.nn.LSTM"]: if layer.kernel in ["paddle.nn.LSTM"]:
line = "{}, ({})".format(layer.outputs[1], ', '.join(layer.outputs[-2:])) line = "{}, ({})".format(layer.outputs[1],
', '.join(layer.outputs[-2:]))
else: else:
line = ','.join(layer.outputs[1:]) line = ','.join(layer.outputs[1:])
if layer.kernel == "paddle.to_tensor" and layer.attrs[ if layer.kernel == "paddle.to_tensor" and layer.attrs[
...@@ -608,10 +460,10 @@ class PaddleGraph(object): ...@@ -608,10 +460,10 @@ class PaddleGraph(object):
line += "{}, ".format(v) line += "{}, ".format(v)
line = line.strip(", ") line = line.strip(", ")
line += ")" line += ")"
self.forward_func.extend(gen_codes([line], indent=indent)) self.forward_func.extend(gen_codes([line], indent=indent))
elif "prim" in layer.kernel: elif "prim" in layer.kernel:
func_name = layer.kernel.replace(".", "_") func_name = layer.kernel.replace(".", "_")
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim2code from x2paddle.op_mapper.pytorch2paddle import prim2code
if hasattr(prim2code, func_name): if hasattr(prim2code, func_name):
func = getattr(prim2code, func_name) func = getattr(prim2code, func_name)
func( func(
...@@ -645,8 +497,13 @@ class PaddleGraph(object): ...@@ -645,8 +497,13 @@ class PaddleGraph(object):
line += ")" line += ")"
if layer.kernel == "self.create_parameter": if layer.kernel == "self.create_parameter":
self.init_func.extend(gen_codes(["self." + line], indent=2)) self.init_func.extend(gen_codes(["self." + line], indent=2))
self.forward_func.extend(gen_codes(["{} = self.{}".format(layer.outputs[0], self.forward_func.extend(
layer.outputs[0])], indent=indent)) gen_codes(
[
"{} = self.{}".format(layer.outputs[0],
layer.outputs[0])
],
indent=indent))
else: else:
self.forward_func.extend(gen_codes([line], indent=indent)) self.forward_func.extend(gen_codes([line], indent=indent))
if indent == 2 and code_dir is not None: if indent == 2 and code_dir is not None:
...@@ -655,7 +512,7 @@ class PaddleGraph(object): ...@@ -655,7 +512,7 @@ class PaddleGraph(object):
else: else:
return self.init_func, self.forward_func return self.init_func, self.forward_func
def dump_dygraph_parameter(self, code_dir): def dump_parameter(self, code_dir):
save_path = osp.join(code_dir, 'model.pdparams') save_path = osp.join(code_dir, 'model.pdparams')
paddle.save(self.parameters, save_path) paddle.save(self.parameters, save_path)
...@@ -665,7 +522,6 @@ class PaddleGraph(object): ...@@ -665,7 +522,6 @@ class PaddleGraph(object):
sepc_list.append( sepc_list.append(
paddle.static.InputSpec( paddle.static.InputSpec(
shape=input_shapes[i], name=name, dtype=input_types[i])) shape=input_shapes[i], name=name, dtype=input_types[i]))
import sys
path = osp.abspath(save_dir) path = osp.abspath(save_dir)
sys.path.insert(0, save_dir) sys.path.insert(0, save_dir)
import x2paddle_code import x2paddle_code
...@@ -679,10 +535,13 @@ class PaddleGraph(object): ...@@ -679,10 +535,13 @@ class PaddleGraph(object):
model.eval() model.eval()
static_model = paddle.jit.to_static(model, input_spec=sepc_list) static_model = paddle.jit.to_static(model, input_spec=sepc_list)
try: try:
paddle.jit.save(static_model, osp.join(save_dir, "inference_model/model")) paddle.jit.save(static_model,
osp.join(save_dir, "inference_model/model"))
except ValueError as e: except ValueError as e:
if str(e) == "'target_vars' should be a list of Variable.": if str(e) == "'target_vars' should be a list of Variable.":
print("[DyGraph2StaticGraph Error] Can not convert the dygraph to static! The output of PyTorch mustbe Variable or a list of Variable.") print(
"[DyGraph2StaticGraph Error] Can not convert the dygraph to static! The output of PyTorch mustbe Variable or a list of Variable."
)
else: else:
print(e) print(e)
exit(0) exit(0)
...@@ -17,7 +17,6 @@ import sys ...@@ -17,7 +17,6 @@ import sys
from google.protobuf import text_format from google.protobuf import text_format
import numpy as np import numpy as np
from x2paddle.core.graph import GraphNode, Graph from x2paddle.core.graph import GraphNode, Graph
from x2paddle.core.fluid_code import FluidCode
from x2paddle.decoder import caffe_shape_inference from x2paddle.decoder import caffe_shape_inference
...@@ -55,18 +54,17 @@ class CaffeGraphNode(GraphNode): ...@@ -55,18 +54,17 @@ class CaffeGraphNode(GraphNode):
super(CaffeGraphNode, self).__init__( super(CaffeGraphNode, self).__init__(
layer, layer_name.replace('/', '_').replace('-', '_').lower()) layer, layer_name.replace('/', '_').replace('-', '_').lower())
self.layer_type = type_str self.layer_type = type_str
self.fluid_code = FluidCode()
self.data = None self.data = None
def set_params(self, params): def set_params(self, params):
self.data = params self.data = params
@property @property
def name(self): def name(self):
if hasattr(self, 'index'): if hasattr(self, 'index'):
return "{}_p{}".format(self.layer_name, self.index) return "{}_p{}".format(self.layer_name, self.index)
return self.layer_name return self.layer_name
@property @property
def out_shapes(self): def out_shapes(self):
return self._out_shapes return self._out_shapes
...@@ -74,7 +72,7 @@ class CaffeGraphNode(GraphNode): ...@@ -74,7 +72,7 @@ class CaffeGraphNode(GraphNode):
@out_shapes.setter @out_shapes.setter
def out_shapes(self, value): def out_shapes(self, value):
self._out_shapes = value self._out_shapes = value
@property @property
def in_shapes(self): def in_shapes(self):
return self._in_shapes return self._in_shapes
...@@ -258,13 +256,14 @@ class CaffeGraph(Graph): ...@@ -258,13 +256,14 @@ class CaffeGraph(Graph):
assert input_node_name in self.node_map, 'The {} isn\'t a valid node'.format( assert input_node_name in self.node_map, 'The {} isn\'t a valid node'.format(
name) name)
input_node = self.node_map[input_node_name] input_node = self.node_map[input_node_name]
if len(input_node.layer.top) > 1 and input_node.layer_type not in ["Input", "MemoryData"]: if len(input_node.layer.top
) > 1 and input_node.layer_type not in ["Input", "MemoryData"]:
need_idx = list(input_node.layer.top).index(node.layer.bottom[idx]) need_idx = list(input_node.layer.top).index(node.layer.bottom[idx])
name = input_node_name + ':' + str(need_idx) name = input_node_name + ':' + str(need_idx)
else: else:
name = input_node_name name = input_node_name
return self.get_node(name, copy=copy) return self.get_node(name, copy=copy)
def set_node_shape(self, node): def set_node_shape(self, node):
inputs = node.inputs inputs = node.inputs
input_shape = [] input_shape = []
...@@ -289,7 +288,7 @@ class CaffeDecoder(object): ...@@ -289,7 +288,7 @@ class CaffeDecoder(object):
with open(proto_path, 'rb') as proto_file: with open(proto_path, 'rb') as proto_file:
proto_str = proto_file.read() proto_str = proto_file.read()
text_format.Merge(proto_str, self.net) text_format.Merge(proto_str, self.net)
self.load_using_pb() self.load_using_pb()
self.caffe_graph = CaffeGraph(self.net, self.params, self.caffe_graph = CaffeGraph(self.net, self.params,
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
from x2paddle.core.graph import GraphNode, Graph from x2paddle.core.graph import GraphNode, Graph
from x2paddle.core.fluid_code import FluidCode
from x2paddle.decoder.onnx_shape_inference import SymbolicShapeInference from x2paddle.decoder.onnx_shape_inference import SymbolicShapeInference
from onnx.checker import ValidationError from onnx.checker import ValidationError
from onnx.checker import check_model from onnx.checker import check_model
...@@ -44,7 +43,6 @@ class ONNXGraphNode(GraphNode): ...@@ -44,7 +43,6 @@ class ONNXGraphNode(GraphNode):
else: else:
super(ONNXGraphNode, self).__init__(layer, layer_name) super(ONNXGraphNode, self).__init__(layer, layer_name)
self.layer_type = layer.op_type self.layer_type = layer.op_type
self.fluid_code = FluidCode()
self.attr_map = self.get_attr_map() self.attr_map = self.get_attr_map()
self.out_shapes = list() self.out_shapes = list()
self.dtype = None self.dtype = None
...@@ -65,7 +63,7 @@ class ONNXGraphNode(GraphNode): ...@@ -65,7 +63,7 @@ class ONNXGraphNode(GraphNode):
if 'value' not in self.attr_map: if 'value' not in self.attr_map:
return None return None
return self.attr_map['value'] return self.attr_map['value']
@property @property
def name(self): def name(self):
if hasattr(self, 'index'): if hasattr(self, 'index'):
...@@ -97,8 +95,10 @@ class ONNXGraphNode(GraphNode): ...@@ -97,8 +95,10 @@ class ONNXGraphNode(GraphNode):
return self.attr_map[name] return self.attr_map[name]
def output(self, index=0): def output(self, index=0):
if index >0 and len(self.layer.output) <= index: if index > 0 and len(self.layer.output) <= index:
raise IndexError('Output numbers of Node:{} is {} <= index:{}'.format(self.layer_name, len(self.layer.output), index)) raise IndexError(
'Output numbers of Node:{} is {} <= index:{}'.format(
self.layer_name, len(self.layer.output), index))
return self.layer.output[index] return self.layer.output[index]
...@@ -113,7 +113,6 @@ class ONNXGraphDataNode(GraphNode): ...@@ -113,7 +113,6 @@ class ONNXGraphDataNode(GraphNode):
else: else:
self.layer_type = 'create_parameter' self.layer_type = 'create_parameter'
self.layer_name = layer_name self.layer_name = layer_name
self.fluid_code = FluidCode()
self.weight = None self.weight = None
self.embeded_as = None self.embeded_as = None
self.which_child = {} self.which_child = {}
...@@ -147,7 +146,7 @@ class ONNXGraphDataNode(GraphNode): ...@@ -147,7 +146,7 @@ class ONNXGraphDataNode(GraphNode):
out_shapes = list() out_shapes = list()
out_shapes.append(values) out_shapes.append(values)
return out_shapes return out_shapes
@property @property
def name(self): def name(self):
return self.layer_name return self.layer_name
...@@ -320,7 +319,8 @@ class ONNXGraph(Graph): ...@@ -320,7 +319,8 @@ class ONNXGraph(Graph):
if first_i == n_i: if first_i == n_i:
continue continue
if n_ipt == nd.name: if n_ipt == nd.name:
new_nd_name = "{}/{}".format(nd.name, n_i) new_nd_name = "{}/{}".format(nd.name,
n_i)
if new_nd_name not in node.which_child: if new_nd_name not in node.which_child:
node.which_child[new_nd_name] = idx node.which_child[new_nd_name] = idx
break break
...@@ -350,9 +350,8 @@ class ONNXGraph(Graph): ...@@ -350,9 +350,8 @@ class ONNXGraph(Graph):
else: else:
if ipt_node.layer_name in node.which_child: if ipt_node.layer_name in node.which_child:
ipt_node.index = node.which_child[ipt_node.layer_name] ipt_node.index = node.which_child[ipt_node.layer_name]
return ipt_node return ipt_node
def graph_weights(self): def graph_weights(self):
""" """
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
from x2paddle.core.graph import GraphNode, Graph from x2paddle.core.graph import GraphNode, Graph
from x2paddle.core.fluid_code import FluidCode
from tensorflow.python.framework import tensor_util from tensorflow.python.framework import tensor_util
from tensorflow.core.framework import attr_value_pb2 from tensorflow.core.framework import attr_value_pb2
import tensorflow as tf import tensorflow as tf
...@@ -36,7 +35,6 @@ class TFGraphNode(GraphNode): ...@@ -36,7 +35,6 @@ class TFGraphNode(GraphNode):
self.layer_type = layer.op self.layer_type = layer.op
self.tf_data_format = data_format self.tf_data_format = data_format
self.pd_data_format = "NCHW" self.pd_data_format = "NCHW"
self.fluid_code = FluidCode()
self.dtype_map = { self.dtype_map = {
1: "float32", 1: "float32",
...@@ -174,7 +172,6 @@ class TFGraph(Graph): ...@@ -174,7 +172,6 @@ class TFGraph(Graph):
self._optimize_dialiation_conv() self._optimize_dialiation_conv()
self._remove_identity_node() self._remove_identity_node()
self._remove_cast_node() self._remove_cast_node()
def get_node(self, node_name, copy=False): def get_node(self, node_name, copy=False):
items = node_name.strip().split(':') items = node_name.strip().split(':')
...@@ -191,7 +188,7 @@ class TFGraph(Graph): ...@@ -191,7 +188,7 @@ class TFGraph(Graph):
if len(items) == 1 and node.layer_type in self.multi_out_ops: if len(items) == 1 and node.layer_type in self.multi_out_ops:
node.index = 0 node.index = 0
return node return node
def get_input_node(self, node, idx=0, copy=False): def get_input_node(self, node, idx=0, copy=False):
input_node_name = node.layer.input[idx] input_node_name = node.layer.input[idx]
if idx > 0: if idx > 0:
...@@ -289,7 +286,6 @@ class TFGraph(Graph): ...@@ -289,7 +286,6 @@ class TFGraph(Graph):
self.output_nodes.pop(idx) self.output_nodes.pop(idx)
else: else:
self.output_nodes[idx] = input_node.layer_name self.output_nodes[idx] = input_node.layer_name
def _remove_cast_node(self): def _remove_cast_node(self):
cast_node = list() cast_node = list()
...@@ -442,7 +438,7 @@ class TFDecoder(object): ...@@ -442,7 +438,7 @@ class TFDecoder(object):
if shape.count(None) > 0: if shape.count(None) > 0:
shape[shape.index(None)] = -1 shape[shape.index(None)] = -1
self.inputs_info["x2paddle_{}".format(layer.name)] = (shape, self.inputs_info["x2paddle_{}".format(layer.name)] = (shape,
dtype) dtype)
else: else:
value = graph_node.layer.attr["shape"].shape value = graph_node.layer.attr["shape"].shape
shape = [dim.size for dim in value.dim] shape = [dim.size for dim in value.dim]
...@@ -466,13 +462,15 @@ class TFDecoder(object): ...@@ -466,13 +462,15 @@ class TFDecoder(object):
for b in batch_size: for b in batch_size:
for input_name, info in self.inputs_info.items(): for input_name, info in self.inputs_info.items():
(shape, dtype) = cp.deepcopy(info) (shape, dtype) = cp.deepcopy(info)
input_tensor = self.sess.graph.get_tensor_by_name(input_name + ":0") input_tensor = self.sess.graph.get_tensor_by_name(input_name +
":0")
if shape.count(-1) > 0: if shape.count(-1) > 0:
shape[shape.index(-1)] = b shape[shape.index(-1)] = b
feed[input_tensor] = numpy.random.random_sample(shape) feed[input_tensor] = numpy.random.random_sample(shape)
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name) output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
if use_diff_inputs: if use_diff_inputs:
results.append(self.sess.run([output_tensor], feed)[0].flatten()) results.append(
self.sess.run([output_tensor], feed)[0].flatten())
else: else:
return self.sess.run([output_tensor], feed)[0] return self.sess.run([output_tensor], feed)[0]
...@@ -499,4 +497,3 @@ class TFDecoder(object): ...@@ -499,4 +497,3 @@ class TFDecoder(object):
return results[0].tolist() return results[0].tolist()
else: else:
raise Exception("Couldn't infer a stable shape shape tensor value") raise Exception("Couldn't infer a stable shape shape tensor value")
\ No newline at end of file
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from .detectionoutput import DetectionOutput from .detectionoutput import DetectionOutput
from .normalize import Normalize from .normalize import Normalize
from .priorbox import PriorBox from .priorbox import PriorBox
from .roipooling import ROIPooling from .roipooling import ROIPooling
from .select import Select from .select import Select
\ No newline at end of file
...@@ -15,16 +15,19 @@ ...@@ -15,16 +15,19 @@
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
class DetectionOutput(object): class DetectionOutput(object):
def __init__(self, nms_threshold, nms_top_k, keep_top_k, nms_eta, score_threshold, background_label): def __init__(self, nms_threshold, nms_top_k, keep_top_k, nms_eta,
score_threshold, background_label):
self.detection_output_layer_attrs = { self.detection_output_layer_attrs = {
"background_label": background_label, "background_label": background_label,
"nms_threshold": nms_threshold, "nms_threshold": nms_threshold,
"nms_top_k": nms_top_k, "nms_top_k": nms_top_k,
"keep_top_k": keep_top_k, "keep_top_k": keep_top_k,
"score_threshold": score_threshold, "score_threshold": score_threshold,
"nms_eta": nms_eta} "nms_eta": nms_eta
}
def __call__(self, x0, x1, x2): def __call__(self, x0, x1, x2):
priorbox_list = paddle.split(x2, num_or_sections=2, axis=1) priorbox_list = paddle.split(x2, num_or_sections=2, axis=1)
pb = priorbox_list[0] pb = priorbox_list[0]
...@@ -34,11 +37,10 @@ class DetectionOutput(object): ...@@ -34,11 +37,10 @@ class DetectionOutput(object):
pb_dim = fluid.layers.shape(pb)[0] pb_dim = fluid.layers.shape(pb)[0]
loc = paddle.reshape(x0, shape=[-1, pb_dim, 4]) loc = paddle.reshape(x0, shape=[-1, pb_dim, 4])
conf_flatten = paddle.reshape(x1, shape=[0, pb_dim, -1]) conf_flatten = paddle.reshape(x1, shape=[0, pb_dim, -1])
out = fluid.layers.detection_output(loc=loc, out = fluid.layers.detection_output(
scores=conf_flatten, loc=loc,
prior_box=pb, scores=conf_flatten,
prior_box_var=pbv, prior_box=pb,
**self.detection_output_layer_attrs) prior_box_var=pbv,
**self.detection_output_layer_attrs)
return out return out
\ No newline at end of file
...@@ -15,10 +15,11 @@ ...@@ -15,10 +15,11 @@
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
class Normalize(object): class Normalize(object):
def __init__(self, axis): def __init__(self, axis):
self.axis = axis self.axis = axis
def __call__(self, x, param): def __call__(self, x, param):
l2_norm = fluid.layers.l2_normalize(x=x, axis=1) l2_norm = fluid.layers.l2_normalize(x=x, axis=1)
param = paddle.reshape(param, [param.shape[-1]]) param = paddle.reshape(param, [param.shape[-1]])
...@@ -32,5 +33,3 @@ class Normalize(object): ...@@ -32,5 +33,3 @@ class Normalize(object):
perm.insert(self.axis, dim) perm.insert(self.axis, dim)
out = paddle.transpose(out, perm=perm) out = paddle.transpose(out, perm=perm)
return out return out
\ No newline at end of file
...@@ -15,11 +15,10 @@ ...@@ -15,11 +15,10 @@
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
class PriorBox(object): class PriorBox(object):
def __init__(self, min_sizes, max_sizes, def __init__(self, min_sizes, max_sizes, aspect_ratios, variance, flip,
aspect_ratios, variance, flip, clip, steps, offset, min_max_aspect_ratios_order):
clip, steps, offset,
min_max_aspect_ratios_order):
self.priorbox_layer_attrs = { self.priorbox_layer_attrs = {
"min_sizes": min_sizes, "min_sizes": min_sizes,
"max_sizes": max_sizes, "max_sizes": max_sizes,
...@@ -29,13 +28,13 @@ class PriorBox(object): ...@@ -29,13 +28,13 @@ class PriorBox(object):
"clip": clip, "clip": clip,
"steps": steps, "steps": steps,
"offset": offset, "offset": offset,
"min_max_aspect_ratios_order": min_max_aspect_ratios_order} "min_max_aspect_ratios_order": min_max_aspect_ratios_order
}
def __call__(self, x0, x1): def __call__(self, x0, x1):
box, var = fluid.layers.prior_box(input=x0, box, var = fluid.layers.prior_box(
image=x1, input=x0, image=x1, **self.priorbox_layer_attrs)
**self.priorbox_layer_attrs)
box = paddle.reshape(x=box, shape=[1, 1, -1]) box = paddle.reshape(x=box, shape=[1, 1, -1])
var = paddle.reshape(x=var, shape=[1, 1, -1]) var = paddle.reshape(x=var, shape=[1, 1, -1])
out = paddle.concat(x=[box, var], axis=1) out = paddle.concat(x=[box, var], axis=1)
return out return out
\ No newline at end of file
...@@ -15,19 +15,17 @@ ...@@ -15,19 +15,17 @@
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
class ROIPooling(object): class ROIPooling(object):
def __init__(self, pooled_height, pooled_width, spatial_scale): def __init__(self, pooled_height, pooled_width, spatial_scale):
self.roipooling_layer_attrs = { self.roipooling_layer_attrs = {
"pooled_height": pooled_height, "pooled_height": pooled_height,
"pooled_width": pooled_width, "pooled_width": pooled_width,
"spatial_scale": spatial_scale} "spatial_scale": spatial_scale
}
def __call__(self, x0, x1): def __call__(self, x0, x1):
slice_x1 = paddle.slice(input=x1, axes=[1], slice_x1 = paddle.slice(input=x1, axes=[1], starts=[1], ends=[5])
starts=[1], ends=[5]) out = fluid.layers.roi_pool(
out = fluid.layers.roi_pool(input=x0, input=x0, rois=slice_x1, **self.roipooling_layer_attrs)
rois=slice_x1,
**self.roipooling_layer_attrs)
return out return out
\ No newline at end of file
...@@ -15,21 +15,18 @@ ...@@ -15,21 +15,18 @@
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
class Select(object): class Select(object):
def __init__(self, input_shape, point, axis): def __init__(self, input_shape, point, axis):
self.point = point self.point = point
self.input_shape = input_shape self.input_shape = input_shape
self.axis = axis self.axis = axis
def __call__(self, x): def __call__(self, x):
start = self.point[0] start = self.point[0]
if len(self.point) == 2: if len(self.point) == 2:
end = self.point[1] end = self.point[1]
else: else:
end = self.input_shape[self.axis] end = self.input_shape[self.axis]
out = paddle.slice(x=x, out = paddle.slice(x=x, start=start, end=end, axes=[self.axis])
start=start,
end=end,
axes=[self.axis])
return out return out
\ No newline at end of file
...@@ -15,9 +15,8 @@ ...@@ -15,9 +15,8 @@
import sys import sys
import numbers import numbers
import numpy as np import numpy as np
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import * from x2paddle.core.util import *
from x2paddle.core.program import PaddleGraph from x2paddle.core.program import PaddleGraph
from x2paddle.decoder.caffe_decoder import CaffeGraphNode from x2paddle.decoder.caffe_decoder import CaffeGraphNode
...@@ -57,14 +56,16 @@ def _adjust_parameters(node): ...@@ -57,14 +56,16 @@ def _adjust_parameters(node):
shape_new = data[idx].shape shape_new = data[idx].shape
return data return data
def _get_kernel_parameters(kind, params): def _get_kernel_parameters(kind, params):
assert kind in ["Convolution", "Pooling", "Deconvolution", "ConvolutionDepthwise"] assert kind in [
"Convolution", "Pooling", "Deconvolution", "ConvolutionDepthwise"
]
[k_h, k_w] = [1, 1] [k_h, k_w] = [1, 1]
if isinstance(params.kernel_size, numbers.Number): if isinstance(params.kernel_size, numbers.Number):
[k_h, k_w] = [params.kernel_size] * 2 [k_h, k_w] = [params.kernel_size] * 2
elif len(params.kernel_size) > 0: elif len(params.kernel_size) > 0:
k_h = params.kernel_h if params.kernel_h > 0 else params.kernel_size[ k_h = params.kernel_h if params.kernel_h > 0 else params.kernel_size[0]
0]
k_w = params.kernel_w if params.kernel_w > 0 else params.kernel_size[ k_w = params.kernel_w if params.kernel_w > 0 else params.kernel_size[
len(params.kernel_size) - 1] len(params.kernel_size) - 1]
elif params.kernel_h > 0 or params.kernel_w > 0: elif params.kernel_h > 0 or params.kernel_w > 0:
...@@ -85,8 +86,8 @@ def _get_kernel_parameters(kind, params): ...@@ -85,8 +86,8 @@ def _get_kernel_parameters(kind, params):
[p_h, p_w] = [params.pad] * 2 [p_h, p_w] = [params.pad] * 2
elif len(params.pad) > 0: elif len(params.pad) > 0:
p_h = params.pad_h if params.pad_h > 0 else params.pad[0] p_h = params.pad_h if params.pad_h > 0 else params.pad[0]
p_w = params.pad_w if params.pad_w > 0 else params.pad[len( p_w = params.pad_w if params.pad_w > 0 else params.pad[len(params.pad) -
params.pad) - 1] 1]
elif params.pad_h > 0 or params.pad_w > 0: elif params.pad_h > 0 or params.pad_w > 0:
p_h = params.pad_h p_h = params.pad_h
p_w = params.pad_w p_w = params.pad_w
...@@ -114,21 +115,20 @@ def _get_kernel_parameters(kind, params): ...@@ -114,21 +115,20 @@ def _get_kernel_parameters(kind, params):
return c_o, kernel, stride, pad, dilation, group return c_o, kernel, stride, pad, dilation, group
class CaffeOpMapper(OpMapper): class CaffeOpMapper():
directly_map_ops = { directly_map_ops = {
'Sigmoid': ['paddle.nn.layer.Sigmoid'], 'Sigmoid': ['paddle.nn.layer.Sigmoid'],
'TanH': ['paddle.nn.Tanh'], 'TanH': ['paddle.nn.Tanh'],
} }
def __init__(self, decoder): def __init__(self, decoder):
super(CaffeOpMapper, self).__init__()
self.graph = decoder.caffe_graph self.graph = decoder.caffe_graph
if not self.op_checker(): if not self.op_checker():
raise Exception("Model is not supported yet.") raise Exception("Model is not supported yet.")
self.params = dict() self.params = dict()
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="dygraph", source_type="caffe") self.paddle_graph = PaddleGraph(parent_layer=None, source_type="caffe")
self.paddle_graph.outputs = self.graph.output_nodes self.paddle_graph.outputs = self.graph.output_nodes
self.input_index = 0 self.input_index = 0
self.inputs_info = {} self.inputs_info = {}
self.nn_name2id = {} self.nn_name2id = {}
print("Total nodes: {}".format( print("Total nodes: {}".format(
...@@ -150,7 +150,7 @@ class CaffeOpMapper(OpMapper): ...@@ -150,7 +150,7 @@ class CaffeOpMapper(OpMapper):
self.paddle_graph.set_name(self.graph.graph_name) self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.params) self.paddle_graph.set_parameters(self.params)
self.paddle_graph.set_inputs_info(self.inputs_info) self.paddle_graph.set_inputs_info(self.inputs_info)
def op_checker(self): def op_checker(self):
unsupported_ops = set() unsupported_ops = set()
for node_name in self.graph.topo_sort: for node_name in self.graph.topo_sort:
...@@ -162,12 +162,12 @@ class CaffeOpMapper(OpMapper): ...@@ -162,12 +162,12 @@ class CaffeOpMapper(OpMapper):
return True return True
else: else:
if len(unsupported_ops) > 0: if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format( print("\n========= {} OPs are not supported yet ===========".
len(unsupported_ops))) format(len(unsupported_ops)))
for op in unsupported_ops: for op in unsupported_ops:
print("========== {} ============".format(op)) print("========== {} ============".format(op))
return False return False
def directly_map(self, node): def directly_map(self, node):
inputs = node.layer.input inputs = node.layer.input
assert len(inputs) == 1, 'directly_map error with multi inputs' assert len(inputs) == 1, 'directly_map error with multi inputs'
...@@ -185,8 +185,7 @@ class CaffeOpMapper(OpMapper): ...@@ -185,8 +185,7 @@ class CaffeOpMapper(OpMapper):
outputs=layer_outputs) outputs=layer_outputs)
else: else:
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
kernel=paddle_op, kernel=paddle_op, inputs={"x": input.name},
inputs={"x": input.name},
outputs=[node.name]) outputs=[node.name])
def Input(self, node): def Input(self, node):
...@@ -196,9 +195,10 @@ class CaffeOpMapper(OpMapper): ...@@ -196,9 +195,10 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name], outputs=[node.layer_name],
data="x{}".format(self.input_index)) data="x{}".format(self.input_index))
shape = list(node.layer.input_param.shape[0].dim)[1:] shape = list(node.layer.input_param.shape[0].dim)[1:]
self.inputs_info["x{}".format(self.input_index)] = [[-1] + shape, "float32"] self.inputs_info["x{}".format(self.input_index)] = [[-1] + shape,
"float32"]
self.input_index += 1 self.input_index += 1
def MemoryData(self, node): def MemoryData(self, node):
params = node.layer.memory_data_param params = node.layer.memory_data_param
transform_params = node.layer.transform_param transform_params = node.layer.transform_param
...@@ -233,8 +233,9 @@ class CaffeOpMapper(OpMapper): ...@@ -233,8 +233,9 @@ class CaffeOpMapper(OpMapper):
"The parameter of {} (type is {}) is not set. So we set the parameters as 0" "The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type)) .format(node.layer_name, node.layer_type))
data.append( data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype( np.zeros([
'float32')) out_channel, node.in_shapes[0][1], kernel[0], kernel[1]
]).astype('float32'))
data.append(np.zeros([out_channel, ]).astype('float32')) data.append(np.zeros([out_channel, ]).astype('float32'))
else: else:
data = _adjust_parameters(node) data = _adjust_parameters(node)
...@@ -260,7 +261,7 @@ class CaffeOpMapper(OpMapper): ...@@ -260,7 +261,7 @@ class CaffeOpMapper(OpMapper):
inputs={"input": input.name}, inputs={"input": input.name},
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def DepthwiseConvolution(self, node): def DepthwiseConvolution(self, node):
node.layer_type = "ConvolutionDepthwise" node.layer_type = "ConvolutionDepthwise"
self.ConvolutionDepthwise(node) self.ConvolutionDepthwise(node)
...@@ -279,8 +280,9 @@ class CaffeOpMapper(OpMapper): ...@@ -279,8 +280,9 @@ class CaffeOpMapper(OpMapper):
"The parameter of {} (type is {}) is not set. So we set the parameters as 0" "The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type)) .format(node.layer_name, node.layer_type))
data.append( data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype( np.zeros([
'float32')) out_channel, node.in_shapes[0][1], kernel[0], kernel[1]
]).astype('float32'))
data.append(np.zeros([out_channel, ]).astype('float32')) data.append(np.zeros([out_channel, ]).astype('float32'))
else: else:
data = _adjust_parameters(node) data = _adjust_parameters(node)
...@@ -306,7 +308,7 @@ class CaffeOpMapper(OpMapper): ...@@ -306,7 +308,7 @@ class CaffeOpMapper(OpMapper):
inputs={"input": input.name}, inputs={"input": input.name},
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def ConvolutionDepthwise(self, node): def ConvolutionDepthwise(self, node):
conv2d_name = name_generator("conv", self.nn_name2id) conv2d_name = name_generator("conv", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -315,18 +317,21 @@ class CaffeOpMapper(OpMapper): ...@@ -315,18 +317,21 @@ class CaffeOpMapper(OpMapper):
params = node.layer.convolution_param params = node.layer.convolution_param
out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters( out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params) node.layer_type, params)
out_channel = params.num_output if params.num_output is not None else node.in_shapes[0][1] out_channel = params.num_output if params.num_output is not None else node.in_shapes[
0][1]
in_channel = node.in_shapes[0][1] in_channel = node.in_shapes[0][1]
group = int(in_channel / (in_channel / out_channel)) if in_channel > out_channel else int(in_channel / group = int(in_channel / (
(out_channel / in_channel)) in_channel / out_channel)) if in_channel > out_channel else int(
in_channel / (out_channel / in_channel))
if data is None: if data is None:
data = [] data = []
print( print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0" "The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type)) .format(node.layer_name, node.layer_type))
data.append( data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype( np.zeros([
'float32')) out_channel, node.in_shapes[0][1], kernel[0], kernel[1]
]).astype('float32'))
data.append(np.zeros([out_channel, ]).astype('float32')) data.append(np.zeros([out_channel, ]).astype('float32'))
else: else:
data = _adjust_parameters(node) data = _adjust_parameters(node)
...@@ -423,12 +428,11 @@ class CaffeOpMapper(OpMapper): ...@@ -423,12 +428,11 @@ class CaffeOpMapper(OpMapper):
"beta": params.beta, "beta": params.beta,
} }
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.fluid.layers.lrn", "paddle.fluid.layers.lrn",
inputs={"input": input.name}, inputs={"input": input.name},
outputs=[node.layer_name], outputs=[node.layer_name],
**layer_attrs) **layer_attrs)
def InnerProduct(self, node): def InnerProduct(self, node):
linear_name = name_generator("linear", self.nn_name2id) linear_name = name_generator("linear", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -442,10 +446,11 @@ class CaffeOpMapper(OpMapper): ...@@ -442,10 +446,11 @@ class CaffeOpMapper(OpMapper):
.format(node.layer_name, node.layer_type)) .format(node.layer_name, node.layer_type))
data = [] data = []
data.append( data.append(
np.zeros([node.in_shapes[0][1], params.num_output]).astype("float32").astype( np.zeros([node.in_shapes[0][1], params.num_output]).astype(
"float32")) "float32").astype("float32"))
data.append( data.append(
np.zeros([params.num_output]).astype("float32").astype("float32")) np.zeros([params.num_output]).astype("float32").astype(
"float32"))
else: else:
data = _adjust_parameters(node) data = _adjust_parameters(node)
# Reshape the parameters to Paddle's ordering # Reshape the parameters to Paddle's ordering
...@@ -466,7 +471,7 @@ class CaffeOpMapper(OpMapper): ...@@ -466,7 +471,7 @@ class CaffeOpMapper(OpMapper):
assert params.bias_term == True assert params.bias_term == True
layer_attrs = { layer_attrs = {
"in_features": data[0].shape[0], "in_features": data[0].shape[0],
"out_features": params.num_output "out_features": params.num_output
} }
if len(data) == 1: if len(data) == 1:
layer_attrs["bias"] = False layer_attrs["bias"] = False
...@@ -487,7 +492,7 @@ class CaffeOpMapper(OpMapper): ...@@ -487,7 +492,7 @@ class CaffeOpMapper(OpMapper):
inputs={"input": input.name}, inputs={"input": input.name},
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def AbsVal(self, node): def AbsVal(self, node):
assert len( assert len(
node.inputs node.inputs
...@@ -642,25 +647,21 @@ class CaffeOpMapper(OpMapper): ...@@ -642,25 +647,21 @@ class CaffeOpMapper(OpMapper):
inputs_dict['x'] = node.layer_name + '_mul0' inputs_dict['x'] = node.layer_name + '_mul0'
inputs_dict['y'] = node.layer_name + '_mul1' inputs_dict['y'] = node.layer_name + '_mul1'
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict,
inputs=inputs_dict,
outputs=[node.layer_name]) outputs=[node.layer_name])
else: else:
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = input0_name inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name inputs_dict['y'] = input1_name
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict,
inputs=inputs_dict,
outputs=[node.layer_name]) outputs=[node.layer_name])
else: else:
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = input0_name inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name inputs_dict['y'] = input1_name
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.max", "paddle.max", inputs=inputs_dict, outputs=[node.layer_name])
inputs=inputs_dict,
outputs=[node.layer_name])
def BatchNorm(self, node): def BatchNorm(self, node):
batchnorm_name = name_generator("batchnorm", self.nn_name2id) batchnorm_name = name_generator("batchnorm", self.nn_name2id)
...@@ -702,7 +703,7 @@ class CaffeOpMapper(OpMapper): ...@@ -702,7 +703,7 @@ class CaffeOpMapper(OpMapper):
"paddle.unsqueeze", "paddle.unsqueeze",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[input.name], outputs=[input.name],
axis=[2,3]) axis=[2, 3])
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.nn.BatchNorm2D", "paddle.nn.BatchNorm2D",
inputs={"input": input.name}, inputs={"input": input.name},
...@@ -713,8 +714,8 @@ class CaffeOpMapper(OpMapper): ...@@ -713,8 +714,8 @@ class CaffeOpMapper(OpMapper):
"paddle.squeeze", "paddle.squeeze",
inputs={"x": node.layer_name}, inputs={"x": node.layer_name},
outputs=[node.layer_name], outputs=[node.layer_name],
axis=[2,3]) axis=[2, 3])
def Scale(self, node): def Scale(self, node):
if node.data is None: if node.data is None:
print( print(
...@@ -734,8 +735,8 @@ class CaffeOpMapper(OpMapper): ...@@ -734,8 +735,8 @@ class CaffeOpMapper(OpMapper):
node.in_shapes[0][1], node.in_shapes[0][1],
]).astype("float32") ]).astype("float32")
else: else:
self.params[node.layer_name + "_cparam2"] = np.squeeze(node.data[ self.params[node.layer_name + "_cparam2"] = np.squeeze(
1]).astype("float32") node.data[1]).astype("float32")
params = node.layer.scale_param params = node.layer.scale_param
axis = params.axis axis = params.axis
inputs = [] inputs = []
...@@ -787,9 +788,7 @@ class CaffeOpMapper(OpMapper): ...@@ -787,9 +788,7 @@ class CaffeOpMapper(OpMapper):
output_shape = node.out_shapes[0] output_shape = node.out_shapes[0]
if axis == -1: if axis == -1:
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict, outputs=[node.layer_name])
inputs=inputs_dict,
outputs=[node.layer_name])
else: else:
if axis < 0: if axis < 0:
axis = axis + len(output_shape) axis = axis + len(output_shape)
...@@ -803,10 +802,8 @@ class CaffeOpMapper(OpMapper): ...@@ -803,10 +802,8 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name + "_cparam2"], outputs=[node.layer_name + "_cparam2"],
shape=new_shape) shape=new_shape)
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict, outputs=[node.layer_name])
inputs=inputs_dict,
outputs=[node.layer_name])
def Reshape(self, node): def Reshape(self, node):
input = self.graph.get_input_node(node, idx=0, copy=True) input = self.graph.get_input_node(node, idx=0, copy=True)
output_shape = node.out_shapes[0] output_shape = node.out_shapes[0]
...@@ -816,7 +813,6 @@ class CaffeOpMapper(OpMapper): ...@@ -816,7 +813,6 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name], outputs=[node.layer_name],
shape=output_shape) shape=output_shape)
def ArgMax(self, node): def ArgMax(self, node):
assert len(node.inputs) == 1 and len( assert len(node.inputs) == 1 and len(
node.outputs node.outputs
...@@ -834,7 +830,10 @@ class CaffeOpMapper(OpMapper): ...@@ -834,7 +830,10 @@ class CaffeOpMapper(OpMapper):
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.topk", "paddle.topk",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[node.layer_name + "_topk_var", node.layer_name + "_index_var"], outputs=[
node.layer_name + "_topk_var",
node.layer_name + "_index_var"
],
k=top_k) k=top_k)
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.cast", "paddle.cast",
...@@ -843,7 +842,12 @@ class CaffeOpMapper(OpMapper): ...@@ -843,7 +842,12 @@ class CaffeOpMapper(OpMapper):
dtype="{}_topk_var.dtype".format(node.layer_name)) dtype="{}_topk_var.dtype".format(node.layer_name))
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.concat", "paddle.concat",
inputs={"x": [node.layer_name + "_topk_var", node.layer_name + "_index_var"]}, inputs={
"x": [
node.layer_name + "_topk_var",
node.layer_name + "_index_var"
]
},
outputs=[node.layer_name], outputs=[node.layer_name],
axis=axis) axis=axis)
else: else:
...@@ -852,7 +856,7 @@ class CaffeOpMapper(OpMapper): ...@@ -852,7 +856,7 @@ class CaffeOpMapper(OpMapper):
inputs={"x": input.name}, inputs={"x": input.name},
outputs=["_", node.layer_name], outputs=["_", node.layer_name],
k=top_k) k=top_k)
def Axpy(self, node): def Axpy(self, node):
assert len(node.inputs) == 1 and len( assert len(node.inputs) == 1 and len(
node.outputs node.outputs
...@@ -880,7 +884,6 @@ class CaffeOpMapper(OpMapper): ...@@ -880,7 +884,6 @@ class CaffeOpMapper(OpMapper):
"paddle.add", "paddle.add",
inputs=inputs_dict, inputs=inputs_dict,
outputs=[node.layer_name + "_mul"]) outputs=[node.layer_name + "_mul"])
def Crop(self, node): def Crop(self, node):
assert len( assert len(
...@@ -900,11 +903,11 @@ class CaffeOpMapper(OpMapper): ...@@ -900,11 +903,11 @@ class CaffeOpMapper(OpMapper):
str(offset)) str(offset))
offset_real = [0] * axis + offset offset_real = [0] * axis + offset
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.crop", "paddle.crop",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[node.layer_name], outputs=[node.layer_name],
shape=node.in_shapes[1], shape=node.in_shapes[1],
offsets=list(offset_real)) offsets=list(offset_real))
def Flatten(self, node): def Flatten(self, node):
assert len( assert len(
...@@ -953,7 +956,7 @@ class CaffeOpMapper(OpMapper): ...@@ -953,7 +956,7 @@ class CaffeOpMapper(OpMapper):
axis += input_len + 1 axis += input_len + 1
dim = list(range(input_len)) dim = list(range(input_len))
# operation = SUM # operation = SUM
if operation == 1: if operation == 1:
layer_attrs = { layer_attrs = {
"dim": dim[axis:], "dim": dim[axis:],
"keep_dim": False, "keep_dim": False,
...@@ -964,7 +967,7 @@ class CaffeOpMapper(OpMapper): ...@@ -964,7 +967,7 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name], outputs=[node.layer_name],
**layer_attrs) **layer_attrs)
# operation = ASUM # operation = ASUM
elif operation == 2: elif operation == 2:
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.abs", "paddle.abs",
inputs={"x": input.name}, inputs={"x": input.name},
...@@ -979,7 +982,7 @@ class CaffeOpMapper(OpMapper): ...@@ -979,7 +982,7 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name], outputs=[node.layer_name],
**layer_attrs) **layer_attrs)
# operation = SUMSQ # operation = SUMSQ
elif operation == 3: elif operation == 3:
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.pow", "paddle.pow",
inputs={"x": input.name}, inputs={"x": input.name},
...@@ -995,7 +998,7 @@ class CaffeOpMapper(OpMapper): ...@@ -995,7 +998,7 @@ class CaffeOpMapper(OpMapper):
outputs=[node.layer_name], outputs=[node.layer_name],
**layer_attrs) **layer_attrs)
# operation = MEAN # operation = MEAN
else: else:
layer_attrs = { layer_attrs = {
"axis": dim[axis:], "axis": dim[axis:],
"keepdim": False, "keepdim": False,
...@@ -1010,13 +1013,15 @@ class CaffeOpMapper(OpMapper): ...@@ -1010,13 +1013,15 @@ class CaffeOpMapper(OpMapper):
inputs={"x": node.layer_name}, inputs={"x": node.layer_name},
outputs=[node.layer_name], outputs=[node.layer_name],
scale=coeff) scale=coeff)
def DetectionOutput(self, node): def DetectionOutput(self, node):
detection_output_name = name_generator("detection_output", self.nn_name2id) detection_output_name = name_generator("detection_output",
self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
layer_outputs = [detection_output_name, output_name] layer_outputs = [detection_output_name, output_name]
assert len( assert len(
node.inputs) == 3, "The count of DetectionOutput node\'s input is not 3." node.
inputs) == 3, "The count of DetectionOutput node\'s input is not 3."
inputs_dict = dict() inputs_dict = dict()
for i in range(len(node.inputs)): for i in range(len(node.inputs)):
input = self.graph.get_input_node(node, idx=i, copy=True) input = self.graph.get_input_node(node, idx=i, copy=True)
...@@ -1048,13 +1053,14 @@ class CaffeOpMapper(OpMapper): ...@@ -1048,13 +1053,14 @@ class CaffeOpMapper(OpMapper):
"nms_top_k": nms_param_dict["top_k"], "nms_top_k": nms_param_dict["top_k"],
"keep_top_k": params.keep_top_k, "keep_top_k": params.keep_top_k,
"score_threshold": params.confidence_threshold, "score_threshold": params.confidence_threshold,
"nms_eta": nms_param_dict["eta"]} "nms_eta": nms_param_dict["eta"]
}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
kernel="custom_layer:DetectionOutput", kernel="custom_layer:DetectionOutput",
inputs=inputs_dict, inputs=inputs_dict,
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def Normalize(self, node): def Normalize(self, node):
normalize_name = name_generator("normalize", self.nn_name2id) normalize_name = name_generator("normalize", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -1072,8 +1078,7 @@ class CaffeOpMapper(OpMapper): ...@@ -1072,8 +1078,7 @@ class CaffeOpMapper(OpMapper):
np.zeros([1] if params.channel_shared else [node.in_shapes[0][1]]).astype("float32") np.zeros([1] if params.channel_shared else [node.in_shapes[0][1]]).astype("float32")
else: else:
self.params[param_name] = _adjust_parameters(node)[0] self.params[param_name] = _adjust_parameters(node)[0]
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"self.create_parameter", "self.create_parameter",
inputs={}, inputs={},
...@@ -1081,27 +1086,26 @@ class CaffeOpMapper(OpMapper): ...@@ -1081,27 +1086,26 @@ class CaffeOpMapper(OpMapper):
shape=self.params[param_name].shape, shape=self.params[param_name].shape,
attr=string(param_name)) attr=string(param_name))
inputs_dict = {} inputs_dict = {}
layer_attrs = { layer_attrs = {"axis": -1 if params.channel_shared else 1}
"axis": -1 if params.channel_shared else 1}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"custom_layer:Normalize", "custom_layer:Normalize",
inputs={"x": input.name, inputs={"x": input.name,
"param": param_name}, "param": param_name},
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def Permute(self, node): def Permute(self, node):
assert len( assert len(
node.inputs) == 1, "The count of Permute node\'s input is not 1." node.inputs) == 1, "The count of Permute node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True) input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.permute_param params = node.layer.permute_param
order = list(params.order) order = list(params.order)
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.transpose", "paddle.transpose",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[node.layer_name], outputs=[node.layer_name],
perm=order) perm=order)
def PriorBox(self, node): def PriorBox(self, node):
priorbox_name = name_generator("priorbox", self.nn_name2id) priorbox_name = name_generator("priorbox", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -1126,13 +1130,14 @@ class CaffeOpMapper(OpMapper): ...@@ -1126,13 +1130,14 @@ class CaffeOpMapper(OpMapper):
"clip": params.clip, "clip": params.clip,
"steps": steps, "steps": steps,
"offset": params.offset, "offset": params.offset,
"min_max_aspect_ratios_order": True} "min_max_aspect_ratios_order": True
}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"custom_layer:PriorBox", "custom_layer:PriorBox",
inputs=inputs_dict, inputs=inputs_dict,
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def ReLU6(self, node): def ReLU6(self, node):
relu6_name = name_generator("relu6", self.nn_name2id) relu6_name = name_generator("relu6", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -1144,7 +1149,7 @@ class CaffeOpMapper(OpMapper): ...@@ -1144,7 +1149,7 @@ class CaffeOpMapper(OpMapper):
"paddle.nn.ReLU6", "paddle.nn.ReLU6",
inputs={"input": input.name}, inputs={"input": input.name},
outputs=layer_outputs) outputs=layer_outputs)
def ROIPooling(self, node): def ROIPooling(self, node):
roipooling_name = name_generator("roipooling", self.nn_name2id) roipooling_name = name_generator("roipooling", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -1160,16 +1165,17 @@ class CaffeOpMapper(OpMapper): ...@@ -1160,16 +1165,17 @@ class CaffeOpMapper(OpMapper):
layer_attrs = { layer_attrs = {
"pooled_height": params.pooled_h, "pooled_height": params.pooled_h,
"pooled_width": params.pooled_w, "pooled_width": params.pooled_w,
"spatial_scale": params.spatial_scale} "spatial_scale": params.spatial_scale
}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"custom_layer:ROIPooling", "custom_layer:ROIPooling",
inputs=inputs_dict, inputs=inputs_dict,
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
def ShuffleChannel(self, node): def ShuffleChannel(self, node):
assert len( assert len(node.inputs
node.inputs) == 1, "The count of ShuffleChannel node\'s input is not 1." ) == 1, "The count of ShuffleChannel node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True) input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.shuffle_channel_param params = node.layer.shuffle_channel_param
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
...@@ -1177,7 +1183,7 @@ class CaffeOpMapper(OpMapper): ...@@ -1177,7 +1183,7 @@ class CaffeOpMapper(OpMapper):
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[node.layer_name], outputs=[node.layer_name],
group=params.group) group=params.group)
def Upsample(self, node): def Upsample(self, node):
assert len( assert len(
node.inputs) == 1, "The count of Upsample node\'s input is not 1." node.inputs) == 1, "The count of Upsample node\'s input is not 1."
...@@ -1186,13 +1192,14 @@ class CaffeOpMapper(OpMapper): ...@@ -1186,13 +1192,14 @@ class CaffeOpMapper(OpMapper):
layer_attrs = { layer_attrs = {
"align_corners": False, "align_corners": False,
"scale_factor": params.scale, "scale_factor": params.scale,
"mode": "nearest"} "mode": "nearest"
}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"paddle.nn.functional.interpolate", "paddle.nn.functional.interpolate",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=[node.layer_name], outputs=[node.layer_name],
**layer_attrs) **layer_attrs)
def Select(self, node): def Select(self, node):
select_name = name_generator("select", self.nn_name2id) select_name = name_generator("select", self.nn_name2id)
output_name = node.layer_name output_name = node.layer_name
...@@ -1205,13 +1212,10 @@ class CaffeOpMapper(OpMapper): ...@@ -1205,13 +1212,10 @@ class CaffeOpMapper(OpMapper):
layer_attrs = { layer_attrs = {
"input_shape": input_shape, "input_shape": input_shape,
"point": params.slice_point, "point": params.slice_point,
"axis": params.axis} "axis": params.axis
}
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
"custom_layer:Select", "custom_layer:Select",
inputs={"x": input.name}, inputs={"x": input.name},
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
...@@ -14,17 +14,14 @@ ...@@ -14,17 +14,14 @@
import paddle import paddle
class LocalResponseNorm(object): class LocalResponseNorm(object):
def __init__(self, def __init__(self, size, alpha=1e-4, beta=0.75, k=1.):
size,
alpha=1e-4,
beta=0.75,
k=1.):
self.size = size self.size = size
self.alpha = alpha self.alpha = alpha
self.beta = beta self.beta = beta
self.k = k self.k = k
def __call__(self, x): def __call__(self, x):
sizes = x.shape sizes = x.shape
dim = len(sizes) dim = len(sizes)
...@@ -62,4 +59,4 @@ class LocalResponseNorm(object): ...@@ -62,4 +59,4 @@ class LocalResponseNorm(object):
div = paddle.scale(div, scale=self.alpha, bias=self.k) div = paddle.scale(div, scale=self.alpha, bias=self.k)
div = paddle.pow(div, self.beta) div = paddle.pow(div, self.beta)
res = paddle.divide(x, div) res = paddle.divide(x, div)
return res return res
\ No newline at end of file
...@@ -14,10 +14,11 @@ ...@@ -14,10 +14,11 @@
import paddle import paddle
class OneHot(object): class OneHot(object):
def __init__(self, axis): def __init__(self, axis):
self.axis = axis self.axis = axis
def __call__(self, indices, depth, values): def __call__(self, indices, depth, values):
indices_shape = indices.shape indices_shape = indices.shape
rank = len(indices.shape) rank = len(indices.shape)
...@@ -25,14 +26,16 @@ class OneHot(object): ...@@ -25,14 +26,16 @@ class OneHot(object):
if self.axis < 0: if self.axis < 0:
real_axis = self.axis + rank + 1 real_axis = self.axis + rank + 1
depth_range = paddle.arange(end=depth) depth_range = paddle.arange(end=depth)
ls = tuple(indices_shape[0: real_axis]) ls = tuple(indices_shape[0:real_axis])
rs = tuple(indices_shape[real_axis: rank]) rs = tuple(indices_shape[real_axis:rank])
targets = paddle.reshape(depth_range, (1,) * (real_axis-0) + tuple(depth_range.shape) + (1,) * (rank-real_axis)) targets = paddle.reshape(depth_range, (1, ) *
(real_axis - 0) + tuple(depth_range.shape) +
(1, ) * (rank - real_axis))
mod = paddle.mod(indices, depth) mod = paddle.mod(indices, depth)
v = paddle.reshape(mod, ls + (1,) + rs) v = paddle.reshape(mod, ls + (1, ) + rs)
out = targets == v out = targets == v
out = paddle.cast(out, "float32") out = paddle.cast(out, "float32")
on_value = paddle.slice(values, axes=[0], starts=[1], ends=[2]) on_value = paddle.slice(values, axes=[0], starts=[1], ends=[2])
off_value = paddle.slice(values, axes=[0], starts=[0], ends=[1]) off_value = paddle.slice(values, axes=[0], starts=[0], ends=[1])
out = out * (on_value - off_value) + off_value out = out * (on_value - off_value) + off_value
return out return out
\ No newline at end of file
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import paddle import paddle
from x2paddle.core.util import * from x2paddle.core.util import *
class PadAllDim2(object): class PadAllDim2(object):
def __init__(self, value, mode): def __init__(self, value, mode):
self.layer_attrs = {} self.layer_attrs = {}
...@@ -22,7 +23,6 @@ class PadAllDim2(object): ...@@ -22,7 +23,6 @@ class PadAllDim2(object):
self.layer_attrs['data_format'] = 'NCHW' self.layer_attrs['data_format'] = 'NCHW'
self.layer_attrs['value'] = value self.layer_attrs['value'] = value
def __call__(self, x, pad): def __call__(self, x, pad):
pad = paddle.reshape(pad, shape=[2, -1]) pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0]) pad = paddle.transpose(pad, perm=[1, 0])
...@@ -32,4 +32,4 @@ class PadAllDim2(object): ...@@ -32,4 +32,4 @@ class PadAllDim2(object):
x = paddle.unsqueeze(x, axis=[0, 1]) x = paddle.unsqueeze(x, axis=[0, 1])
out = paddle.nn.functional.pad(x=x, pad=pad, **self.layer_attrs) out = paddle.nn.functional.pad(x=x, pad=pad, **self.layer_attrs)
out = paddle.squeeze(out, axis=[0, 1]) out = paddle.squeeze(out, axis=[0, 1])
return out return out
\ No newline at end of file
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import paddle import paddle
from x2paddle.core.util import * from x2paddle.core.util import *
class PadAllDim4(object): class PadAllDim4(object):
def __init__(self, value, mode): def __init__(self, value, mode):
self.layer_attrs = {} self.layer_attrs = {}
...@@ -22,16 +23,15 @@ class PadAllDim4(object): ...@@ -22,16 +23,15 @@ class PadAllDim4(object):
self.layer_attrs['data_format'] = 'NCHW' self.layer_attrs['data_format'] = 'NCHW'
self.layer_attrs['value'] = value self.layer_attrs['value'] = value
def __call__(self, x, pad): def __call__(self, x, pad):
pad = paddle.reshape(pad, shape=[2, -1]) pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0]) pad = paddle.transpose(pad, perm=[1, 0])
pad = paddle.reverse(pad, axis=[0]) pad = paddle.reverse(pad, axis=[0])
pad = paddle.flatten(pad) pad = paddle.flatten(pad)
pad = paddle.cast(pad, dtype="int32") pad = paddle.cast(pad, dtype="int32")
pad1, pad2 = paddle.split(pad, num_or_sections=2, axis=0) pad1, pad2 = paddle.split(pad, num_or_sections=2, axis=0)
x = paddle.nn.functional.pad(x=x, pad=pad1, **self.layer_attrs) x = paddle.nn.functional.pad(x=x, pad=pad1, **self.layer_attrs)
x = paddle.transpose(x, perm=[2, 3, 0, 1]) x = paddle.transpose(x, perm=[2, 3, 0, 1])
x = paddle.nn.functional.pad(x=x, pad=pad2, **self.layer_attrs) x = paddle.nn.functional.pad(x=x, pad=pad2, **self.layer_attrs)
out = paddle.transpose(x, perm=[2, 3, 0, 1]) out = paddle.transpose(x, perm=[2, 3, 0, 1])
return out return out
\ No newline at end of file
...@@ -15,18 +15,19 @@ ...@@ -15,18 +15,19 @@
import paddle import paddle
from x2paddle.core.util import * from x2paddle.core.util import *
class PadAllDim4WithOneInput(object): class PadAllDim4WithOneInput(object):
def __init__(self, pad, value, mode): def __init__(self, pad, value, mode):
self.layer_attrs = {} self.layer_attrs = {}
self.layer_attrs['mode'] = mode self.layer_attrs['mode'] = mode
self.layer_attrs['data_format'] = 'NCHW' self.layer_attrs['data_format'] = 'NCHW'
self.layer_attrs['value'] = value self.layer_attrs['value'] = value
self.pad1 = pad[0: 4] self.pad1 = pad[0:4]
self.pad2 = pad[4: 9] self.pad2 = pad[4:9]
def __call__(self, x): def __call__(self, x):
x = paddle.nn.functional.pad(x=x, pad=self.pad1, **self.layer_attrs) x = paddle.nn.functional.pad(x=x, pad=self.pad1, **self.layer_attrs)
x = paddle.transpose(x, perm=[2, 3, 0, 1]) x = paddle.transpose(x, perm=[2, 3, 0, 1])
x = paddle.nn.functional.pad(x=x, pad=self.pad2, **self.layer_attrs) x = paddle.nn.functional.pad(x=x, pad=self.pad2, **self.layer_attrs)
out = paddle.transpose(x, perm=[2, 3, 0, 1]) out = paddle.transpose(x, perm=[2, 3, 0, 1])
return out return out
\ No newline at end of file
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import paddle import paddle
from x2paddle.core.util import * from x2paddle.core.util import *
class PadWithTwoInput(object): class PadWithTwoInput(object):
def __init__(self, value, mode, data_format): def __init__(self, value, mode, data_format):
self.layer_attrs = {} self.layer_attrs = {}
...@@ -22,7 +23,6 @@ class PadWithTwoInput(object): ...@@ -22,7 +23,6 @@ class PadWithTwoInput(object):
self.layer_attrs['data_format'] = data_format self.layer_attrs['data_format'] = data_format
self.layer_attrs['value'] = value self.layer_attrs['value'] = value
def __call__(self, x, pad): def __call__(self, x, pad):
pad = paddle.reshape(pad, shape=[2, -1]) pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0]) pad = paddle.transpose(pad, perm=[1, 0])
...@@ -30,4 +30,4 @@ class PadWithTwoInput(object): ...@@ -30,4 +30,4 @@ class PadWithTwoInput(object):
pad = paddle.flatten(pad) pad = paddle.flatten(pad)
pad = paddle.cast(pad, dtype="int32") pad = paddle.cast(pad, dtype="int32")
out = paddle.nn.functional.pad(x=x, pad=pad, **self.layer_attrs) out = paddle.nn.functional.pad(x=x, pad=pad, **self.layer_attrs)
return out return out
\ No newline at end of file
...@@ -13,24 +13,22 @@ ...@@ -13,24 +13,22 @@
# limitations under the License. # limitations under the License.
import sys import sys
from x2paddle.op_mapper.dygraph.onnx2paddle.opset9 import OpSet9 from x2paddle.op_mapper.onnx2paddle.opset9 import OpSet9
from x2paddle.core.op_mapper import OpMapper
from x2paddle.decoder.onnx_decoder import ONNXGraphNode from x2paddle.decoder.onnx_decoder import ONNXGraphNode
from x2paddle.core.program import PaddleGraph from x2paddle.core.program import PaddleGraph
class ONNXOpMapper(OpMapper): class ONNXOpMapper():
def __init__(self, decoder): def __init__(self, decoder):
super(ONNXOpMapper, self).__init__()
self.support_op_sets = [9, ] self.support_op_sets = [9, ]
self.default_op_set = 9 self.default_op_set = 9
self.graph = decoder.graph self.graph = decoder.graph
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="dygraph", source_type="onnx") self.paddle_graph = PaddleGraph(parent_layer=None, source_type="onnx")
self.paddle_graph.outputs = self.graph.output_nodes self.paddle_graph.outputs = self.graph.output_nodes
self.opset = self.create_opset(decoder) self.opset = self.create_opset(decoder)
if not self.op_checker(): if not self.op_checker():
raise Exception("Model is not supported yet.") raise Exception("Model is not supported yet.")
print("Total nodes: {}".format( print("Total nodes: {}".format(
sum([ sum([
isinstance(node, ONNXGraphNode) isinstance(node, ONNXGraphNode)
...@@ -52,7 +50,6 @@ class ONNXOpMapper(OpMapper): ...@@ -52,7 +50,6 @@ class ONNXOpMapper(OpMapper):
self.paddle_graph.set_name(self.graph.graph_name) self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.opset.weights) self.paddle_graph.set_parameters(self.opset.weights)
self.paddle_graph.set_inputs_info(self.opset.inputs_info) self.paddle_graph.set_inputs_info(self.opset.inputs_info)
def op_checker(self): def op_checker(self):
unsupported_ops = set() unsupported_ops = set()
...@@ -67,8 +64,8 @@ class ONNXOpMapper(OpMapper): ...@@ -67,8 +64,8 @@ class ONNXOpMapper(OpMapper):
return True return True
else: else:
if len(unsupported_ops) > 0: if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format( print("\n========= {} OPs are not supported yet ===========".
len(unsupported_ops))) format(len(unsupported_ops)))
for op in unsupported_ops: for op in unsupported_ops:
print("========== {} ============".format(op)) print("========== {} ============".format(op))
return False return False
......
...@@ -411,7 +411,6 @@ class OpSet9(): ...@@ -411,7 +411,6 @@ class OpSet9():
pooled_width = node.get_attr('output_width') pooled_width = node.get_attr('output_width')
spatial_scale = node.get_attr('spatial_scale') spatial_scale = node.get_attr('spatial_scale')
sampling_ratio = node.get_attr('sampling_ratio') sampling_ratio = node.get_attr('sampling_ratio')
#dygraph rois_num is necessary
val_rois_shape = val_rois.name + '_shape' val_rois_shape = val_rois.name + '_shape'
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
kernel="paddle.shape", kernel="paddle.shape",
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
# limitations under the License. # limitations under the License.
NO_OUTPUT_COUNT = 0 NO_OUTPUT_COUNT = 0
def gen_codes(code_list, indent=0): def gen_codes(code_list, indent=0):
indent_blank = " " * indent indent_blank = " " * indent
codes = [] codes = []
...@@ -52,13 +53,24 @@ def get_value(layer, key, layer_id=None, different_attrs=None): ...@@ -52,13 +53,24 @@ def get_value(layer, key, layer_id=None, different_attrs=None):
return str(layer.attrs[key]) return str(layer.attrs[key])
def prim_add(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_add(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} + {}".format(layer.outputs[0], line = "{} = {} + {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs)) get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_add_(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_add_(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} + {} * {}".format(layer.outputs[0], line = "{} = {} + {} * {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
layer.attrs["alpha"], layer.attrs["alpha"],
...@@ -66,20 +78,36 @@ def prim_add_(layer, indent=1, init_func=[], forward_func=[], layer_id=None, dif ...@@ -66,20 +78,36 @@ def prim_add_(layer, indent=1, init_func=[], forward_func=[], layer_id=None, dif
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_and(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_and(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} and {}".format(layer.outputs[0], line = "{} = {} and {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs)) get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_append(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_append(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{}.append({})".format( line = "{}.append({})".format(
get_value(layer, "list", layer_id, different_attrs), get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "element", layer_id, different_attrs)) get_value(layer, "element", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_assert(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_assert(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
if layer.attrs["type"] == "eq": if layer.attrs["type"] == "eq":
values = get_value(layer, "key") values = get_value(layer, "key")
if "value" in layer.attrs: if "value" in layer.attrs:
...@@ -102,7 +130,12 @@ def prim_assert(layer, indent=1, init_func=[], forward_func=[], layer_id=None, d ...@@ -102,7 +130,12 @@ def prim_assert(layer, indent=1, init_func=[], forward_func=[], layer_id=None, d
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_check_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_check_dim(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
lines = [] lines = []
dim = get_value(layer, "dim", different_attrs) dim = get_value(layer, "dim", different_attrs)
lines.append("if {} < 0:".format(dim)) lines.append("if {} < 0:".format(dim))
...@@ -113,92 +146,166 @@ def prim_check_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None ...@@ -113,92 +146,166 @@ def prim_check_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None
forward_func.extend(gen_codes(lines, indent=indent)) forward_func.extend(gen_codes(lines, indent=indent))
def prim_constant(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_constant(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}".format(layer.outputs[0], layer.attrs["value"]) line = "{} = {}".format(layer.outputs[0], layer.attrs["value"])
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_contain(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_contain(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} in {}".format(layer.outputs[0], line = "{} = {} in {}".format(layer.outputs[0],
get_value(layer, "element", different_attrs), get_value(layer, "element", different_attrs),
get_value(layer, "input", different_attrs)) get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_dict(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_dict(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = dict()".format(layer.outputs[0]) line = "{} = dict()".format(layer.outputs[0])
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_dict_construct(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_dict_construct(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
lines = list() lines = list()
line = "{} = dict()".format(layer.outputs[0]) line = "{} = dict()".format(layer.outputs[0])
lines.append(line) lines.append(line)
for i in range(len(layer.inputs)): for i in range(len(layer.inputs)):
line = "{}[{}] = {}".format(layer.outputs[0], line = "{}[{}] = {}".format(
get_value(layer, "key{}".format(i), different_attrs), layer.outputs[0],
get_value(layer, "value{}".format(i), different_attrs)) get_value(layer, "key{}".format(i), different_attrs),
get_value(layer, "value{}".format(i), different_attrs))
lines.append(line) lines.append(line)
forward_func.extend(gen_codes(lines, indent=indent)) forward_func.extend(gen_codes(lines, indent=indent))
def prim_div(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_div(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} / {}".format(layer.outputs[0], line = "{} = {} / {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_eq(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_eq(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} == {}".format(layer.outputs[0], line = "{} = {} == {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_equal(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_equal(layer,
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_exception(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_exception(layer,
line = "raise RaiseException({})".format(get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "raise RaiseException({})".format(
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_float(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_float(layer,
line = "{} = float({})".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = float({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_floor(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_floor(layer,
line = "{} = math.floor({})".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs)) init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = math.floor({})".format(
layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_floordiv(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_floordiv(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} // {}".format(layer.outputs[0], line = "{} = {} // {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_getitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_getitem(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}[{}]".format(layer.outputs[0], line = "{} = {}[{}]".format(layer.outputs[0],
get_value(layer, "list", different_attrs), get_value(layer, "list", different_attrs),
get_value(layer, "index", different_attrs)) get_value(layer, "index", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_gt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_gt(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} > {}".format(layer.outputs[0], line = "{} = {} > {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_if(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_if(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "if {} :".format(get_value(layer, "input", different_attrs)) line = "if {} :".format(get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0] block = layer.blocks[0]
...@@ -216,75 +323,135 @@ def prim_if(layer, indent=1, init_func=[], forward_func=[], layer_id=None, diffe ...@@ -216,75 +323,135 @@ def prim_if(layer, indent=1, init_func=[], forward_func=[], layer_id=None, diffe
forward_func.extend(b_forward_lines) forward_func.extend(b_forward_lines)
def prim_int(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_int(layer,
line = "{} = int({})".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = int({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_is(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_is(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} is {}".format(layer.outputs[0], line = "{} = {} is {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_isinstance(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_isinstance(layer,
line = "{} = isinstance({}, {})".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs), init_func=[],
layer.attrs["cls"]) forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = isinstance({}, {})".format(
layer.outputs[0],
get_value(layer, "input", different_attrs), layer.attrs["cls"])
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_isnot(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_isnot(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} is not {}".format(layer.outputs[0], line = "{} = {} is not {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_le(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_le(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} <= {}".format(layer.outputs[0], line = "{} = {} <= {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_len(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_len(layer,
line = "{} = len({})".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = len({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_len2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_len2list(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
lines = [] lines = []
lines.append("{} = []".format(layer.outputs[0])) lines.append("{} = []".format(layer.outputs[0]))
lines.append("for i in range({}):".format(get_value(layer, "len", different_attrs))) lines.append("for i in range({}):".format(
get_value(layer, "len", different_attrs)))
lines.append(" {}.append(i)".format(layer.outputs[0])) lines.append(" {}.append(i)".format(layer.outputs[0]))
forward_func.extend(gen_codes(lines, indent=indent)) forward_func.extend(gen_codes(lines, indent=indent))
def prim_lt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_lt(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} < {}".format(layer.outputs[0], line = "{} = {} < {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_list(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs) input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list() inputs_list = list()
for i in range(input_len): for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs)) inputs_list.append(
get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list) inputs_str = ', '.join(inputs_list)
line = "{} = [{}]".format(layer.outputs[0], inputs_str) line = "{} = [{}]".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_list_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(", ".join(layer.outputs), get_value(layer, "input", different_attrs)) def prim_list_unpack(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}".format(", ".join(layer.outputs),
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_loop(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_loop(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
loop_range = get_value(layer, "input", different_attrs) loop_range = get_value(layer, "input", different_attrs)
line = "for {} in range({}):".format(layer.outputs[1], loop_range) line = "for {} in range({}):".format(layer.outputs[1], loop_range)
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
...@@ -294,140 +461,258 @@ def prim_loop(layer, indent=1, init_func=[], forward_func=[], layer_id=None, dif ...@@ -294,140 +461,258 @@ def prim_loop(layer, indent=1, init_func=[], forward_func=[], layer_id=None, dif
forward_func.extend(b_forward_lines) forward_func.extend(b_forward_lines)
def prim_min(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_min(layer,
line = "{} = min({})".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = min({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_mul(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_mul(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} * {}".format(layer.outputs[0], line = "{} = {} * {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_ne(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_ne(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} != {}".format(layer.outputs[0], line = "{} = {} != {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_neg(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_neg(layer,
line = "{} = -{}".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = -{}".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_not(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_not(layer,
line = "{} = not {}".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = not {}".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_or(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_or(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} or {}".format(layer.outputs[0], line = "{} = {} or {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_replaceitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_replaceitem(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{}[{}] = {}".format( line = "{}[{}] = {}".format(
get_value(layer, "list", layer_id, different_attrs), get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "index", layer_id, different_attrs), get_value(layer, "index", layer_id, different_attrs),
get_value(layer, "item", layer_id, different_attrs)) get_value(layer, "item", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_requires_grad(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_requires_grad(layer,
line = "{} = not {}.stop_gradient".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs)) init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = not {}.stop_gradient".format(
layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_rsub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} - {} * {}".format(layer.outputs[0], def prim_rsub(layer,
get_value(layer, "y", different_attrs), indent=1,
get_value(layer, "x", different_attrs), init_func=[],
get_value(layer, "alpha", different_attrs)) forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} - {} * {}".format(
layer.outputs[0],
get_value(layer, "y", different_attrs),
get_value(layer, "x", different_attrs),
get_value(layer, "alpha", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_select(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_select(layer,
line = "{} = {}[".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}[".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
for dim in range(layer.attrs["dim"]): for dim in range(layer.attrs["dim"]):
line += ":, " line += ":, "
line += (get_value(layer, "index", different_attrs) + "]") line += (get_value(layer, "index", different_attrs) + "]")
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_set_attr(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_set_attr(layer,
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_set_item(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_set_item(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{}[{}] = {}".format( line = "{}[{}] = {}".format(
get_value(layer, "dict", different_attrs), get_value(layer, "dict", different_attrs),
get_value(layer, "key", different_attrs), get_value(layer, "value", different_attrs)) get_value(layer, "key", different_attrs),
get_value(layer, "value", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_shape_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_shape_dim(layer,
line = "{} = fluid.layers.shape({})[{}]".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs), init_func=[],
get_value(layer, "dim", different_attrs)) forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = fluid.layers.shape({})[{}]".format(
layer.outputs[0],
get_value(layer, "input", different_attrs),
get_value(layer, "dim", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_slice(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_slice(layer,
line = "{} = {}[{}: {}: {}]".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs), init_func=[],
get_value(layer, "start", different_attrs), forward_func=[],
get_value(layer, "end", different_attrs), layer_id=None,
get_value(layer, "step", different_attrs)) different_attrs=None):
line = "{} = {}[{}: {}: {}]".format(
layer.outputs[0],
get_value(layer, "input", different_attrs),
get_value(layer, "start", different_attrs),
get_value(layer, "end", different_attrs),
get_value(layer, "step", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_str(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_str(layer,
line = "{} = str({})".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = str({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_sub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_sub(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {} - {}".format(layer.outputs[0], line = "{} = {} - {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs)) get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_tuple(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs) input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list() inputs_list = list()
for i in range(input_len): for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs)) inputs_list.append(
get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list) inputs_str = ', '.join(inputs_list)
line = "{} = ({})".format(layer.outputs[0], inputs_str) line = "{} = ({})".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_tuple_unpack(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
outputs_str = ', '.join(layer.outputs) outputs_str = ', '.join(layer.outputs)
line = "{} = {}".format(outputs_str, get_value(layer, "input", different_attrs)) line = "{} = {}".format(outputs_str,
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_type(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_type(layer,
line = "{} = {}.dtype".format(layer.outputs[0], get_value(layer, "input", different_attrs)) indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}.dtype".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_var2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_var2list(layer,
line = "{} = {}.numpy().tolist()".format(layer.outputs[0], indent=1,
get_value(layer, "input", different_attrs)) init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
line = "{} = {}.numpy().tolist()".format(
layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
def prim_warnings(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None): def prim_warnings(layer,
indent=1,
init_func=[],
forward_func=[],
layer_id=None,
different_attrs=None):
lines = ["import warnings"] lines = ["import warnings"]
line = "warnings.warn({}, stacklevel={})".format( line = "warnings.warn({}, stacklevel={})".format(
get_value(layer, "input", different_attrs), layer.attrs["stacklevel"]) get_value(layer, "input", different_attrs), layer.attrs["stacklevel"])
......
...@@ -1014,7 +1014,7 @@ def aten_constant_pad_nd(mapper, graph, node): ...@@ -1014,7 +1014,7 @@ def aten_constant_pad_nd(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.sub", "prim.sub",
inputs={"y": inputs_name[0] + "_len"}, inputs={"y": inputs_name[0] + "_len"},
...@@ -1046,7 +1046,7 @@ def aten_constant_pad_nd(mapper, graph, node): ...@@ -1046,7 +1046,7 @@ def aten_constant_pad_nd(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
layer_inputs["input"] = inputs_name[0] layer_inputs["input"] = inputs_name[0]
block.add_layer( block.add_layer(
kernel, kernel,
...@@ -1847,7 +1847,7 @@ def aten_expand_as(mapper, graph, node): ...@@ -1847,7 +1847,7 @@ def aten_expand_as(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.type", "prim.type",
inputs={"input": inputs_name[1]}, inputs={"input": inputs_name[1]},
...@@ -1861,7 +1861,7 @@ def aten_expand_as(mapper, graph, node): ...@@ -1861,7 +1861,7 @@ def aten_expand_as(mapper, graph, node):
dtype=inputs_name[1] + "_type") dtype=inputs_name[1] + "_type")
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
if_layer.add_block(block) if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0] if_layer.inputs["input-0"] = inputs_name[0]
if_layer.inputs["input-1"] = inputs_name[1] if_layer.inputs["input-1"] = inputs_name[1]
...@@ -1876,7 +1876,7 @@ def aten_expand_as(mapper, graph, node): ...@@ -1876,7 +1876,7 @@ def aten_expand_as(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"paddle.cast", "paddle.cast",
inputs={"x": layer_outputs[0]}, inputs={"x": layer_outputs[0]},
...@@ -1885,7 +1885,7 @@ def aten_expand_as(mapper, graph, node): ...@@ -1885,7 +1885,7 @@ def aten_expand_as(mapper, graph, node):
dtype=string("bool")) dtype=string("bool"))
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
if_layer.add_block(block) if_layer.add_block(block)
if_layer.inputs["input-0"] = layer_outputs[0] if_layer.inputs["input-0"] = layer_outputs[0]
# TODO(syf): check expand_as # TODO(syf): check expand_as
...@@ -2088,7 +2088,7 @@ def aten_floor(mapper, graph, node): ...@@ -2088,7 +2088,7 @@ def aten_floor(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"paddle.floor", "paddle.floor",
inputs=copy.deepcopy(layer_inputs), inputs=copy.deepcopy(layer_inputs),
...@@ -2096,7 +2096,7 @@ def aten_floor(mapper, graph, node): ...@@ -2096,7 +2096,7 @@ def aten_floor(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.floor", "prim.floor",
inputs=copy.deepcopy(layer_inputs), inputs=copy.deepcopy(layer_inputs),
...@@ -3194,7 +3194,7 @@ def aten_masked_fill_(mapper, graph, node): ...@@ -3194,7 +3194,7 @@ def aten_masked_fill_(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.equal", "prim.equal",
inputs={"input": inputs_name[1] + "_mask"}, inputs={"input": inputs_name[1] + "_mask"},
...@@ -3202,7 +3202,7 @@ def aten_masked_fill_(mapper, graph, node): ...@@ -3202,7 +3202,7 @@ def aten_masked_fill_(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.mul", "prim.mul",
inputs={"x": inputs_name[1] + "_mask", inputs={"x": inputs_name[1] + "_mask",
...@@ -3306,7 +3306,7 @@ def aten_masked_fill(mapper, graph, node): ...@@ -3306,7 +3306,7 @@ def aten_masked_fill(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.equal", "prim.equal",
inputs={"input": inputs_name[1] + "_mask"}, inputs={"input": inputs_name[1] + "_mask"},
...@@ -3314,7 +3314,7 @@ def aten_masked_fill(mapper, graph, node): ...@@ -3314,7 +3314,7 @@ def aten_masked_fill(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.mul", "prim.mul",
inputs={"x": inputs_name[1] + "_mask", inputs={"x": inputs_name[1] + "_mask",
...@@ -5115,7 +5115,7 @@ def aten_split(mapper, graph, node): ...@@ -5115,7 +5115,7 @@ def aten_split(mapper, graph, node):
if "[]" in str(input_type): if "[]" in str(input_type):
layer_inputs["num_or_sections"] = inputs_name[1] layer_inputs["num_or_sections"] = inputs_name[1]
else: else:
layer_attrs["num_or_sections"] = 1 layer_attrs["num_or_sections"] = mapper.attrs[inputs_name[1]] + 1
# 获取当前节点输入的list # 获取当前节点输入的list
current_inputs = list(layer_inputs.values()) current_inputs = list(layer_inputs.values())
...@@ -5385,7 +5385,7 @@ def aten_upsample_bilinear2d(mapper, graph, node): ...@@ -5385,7 +5385,7 @@ def aten_upsample_bilinear2d(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.var2list", "prim.var2list",
inputs={"input": inputs_name[1]}, inputs={"input": inputs_name[1]},
...@@ -5393,7 +5393,7 @@ def aten_upsample_bilinear2d(mapper, graph, node): ...@@ -5393,7 +5393,7 @@ def aten_upsample_bilinear2d(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
if_layer.add_block(block) if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[1] if_layer.inputs["input-0"] = inputs_name[1]
# 处理输入2,即%5421 # 处理输入2,即%5421
...@@ -5465,7 +5465,7 @@ def aten_upsample_nearest2d(mapper, graph, node): ...@@ -5465,7 +5465,7 @@ def aten_upsample_nearest2d(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]] if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
block.add_layer( block.add_layer(
"prim.var2list", "prim.var2list",
inputs={"input": inputs_name[1]}, inputs={"input": inputs_name[1]},
...@@ -5473,7 +5473,7 @@ def aten_upsample_nearest2d(mapper, graph, node): ...@@ -5473,7 +5473,7 @@ def aten_upsample_nearest2d(mapper, graph, node):
scope_name=scope_name) scope_name=scope_name)
if_layer.add_block(block) if_layer.add_block(block)
block = PaddleGraph( block = PaddleGraph(
source_type="pytorch", parent_layer=if_layer, graph_type="dygraph") source_type="pytorch", parent_layer=if_layer)
if_layer.add_block(block) if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[1] if_layer.inputs["input-0"] = inputs_name[1]
if "size" in layer_attrs and layer_attrs["size"] is None: if "size" in layer_attrs and layer_attrs["size"] is None:
......
...@@ -356,8 +356,7 @@ def prim_if(layer, ...@@ -356,8 +356,7 @@ def prim_if(layer,
else: else:
block = layer.blocks[1] block = layer.blocks[1]
if len(block.layers) > 0: if len(block.layers) > 0:
b_init_lines, b_forward_lines = block.gen_dygraph_code( b_init_lines, b_forward_lines = block.gen_code(indent=indent)
indent=indent)
init_func.extend(b_init_lines) init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines) forward_func.extend(b_forward_lines)
except: except:
...@@ -368,14 +367,12 @@ def prim_if(layer, ...@@ -368,14 +367,12 @@ def prim_if(layer,
line = "pass" line = "pass"
forward_func.extend(gen_codes([line], indent=indent + 1)) forward_func.extend(gen_codes([line], indent=indent + 1))
else: else:
b_init_lines, b_forward_lines = block.gen_dygraph_code( b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
indent=indent + 1)
init_func.extend(b_init_lines) init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines) forward_func.extend(b_forward_lines)
block = layer.blocks[1] block = layer.blocks[1]
if len(block.layers) > 0: if len(block.layers) > 0:
b_init_lines, b_forward_lines = block.gen_dygraph_code( b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
indent=indent + 1)
if len(b_forward_lines) != 0: if len(b_forward_lines) != 0:
line = "else:" line = "else:"
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
...@@ -531,7 +528,7 @@ def prim_loop(layer, ...@@ -531,7 +528,7 @@ def prim_loop(layer,
line = "for {} in range({}):".format(layer.outputs[1], loop_range) line = "for {} in range({}):".format(layer.outputs[1], loop_range)
forward_func.extend(gen_codes([line], indent=indent)) forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0] block = layer.blocks[0]
b_init_lines, b_forward_lines = block.gen_dygraph_code(indent=indent + 1) b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
init_func.extend(b_init_lines) init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines) forward_func.extend(b_forward_lines)
......
...@@ -12,6 +12,5 @@ ...@@ -12,6 +12,5 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from .gather import Gather from .gather import Gather
from .instance_norm import InstanceNorm from .instance_norm import InstanceNorm
\ No newline at end of file
...@@ -15,16 +15,14 @@ ...@@ -15,16 +15,14 @@
import torch import torch
import numpy as np import numpy as np
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import string from x2paddle.core.util import string
from x2paddle.core.program import PaddleGraph from x2paddle.core.program import PaddleGraph
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim from x2paddle.op_mapper.pytorch2paddle import prim
from x2paddle.op_mapper.dygraph.pytorch2paddle import aten from x2paddle.op_mapper.pytorch2paddle import aten
class PyTorchOpMapper(OpMapper): class PyTorchOpMapper():
def __init__(self, decoder): def __init__(self, decoder):
super(PyTorchOpMapper, self).__init__()
self.script = decoder.script self.script = decoder.script
self.input_examples = decoder.input_examples self.input_examples = decoder.input_examples
self.paddle_params = dict() self.paddle_params = dict()
...@@ -86,10 +84,7 @@ class PyTorchOpMapper(OpMapper): ...@@ -86,10 +84,7 @@ class PyTorchOpMapper(OpMapper):
current_node_outputs.extend(outputs) current_node_outputs.extend(outputs)
# 初始化 # 初始化
graph = PaddleGraph( graph = PaddleGraph(source_type="pytorch", parent_layer=parent_layer)
source_type="pytorch",
parent_layer=parent_layer,
graph_type="dygraph")
if "TopLevelTracedModule" in str(type(self.script)): if "TopLevelTracedModule" in str(type(self.script)):
graph.set_script(self.script) graph.set_script(self.script)
current_node_outputs = [] current_node_outputs = []
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .detectionoutput import detectionoutput
from .normalize import normalize
from .priorbox import priorbox
from .roipooling import roipooling
from .select import select
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
import paddle.fluid as fluid
def detectionoutput(x0,
x1,
x2,
nms_threshold,
nms_top_k,
keep_top_k,
nms_eta,
score_threshold,
background_label):
detection_output_layer_attrs = {
"background_label": background_label,
"nms_threshold": nms_threshold,
"nms_top_k": nms_top_k,
"keep_top_k": keep_top_k,
"score_threshold": score_threshold,
"nms_eta": nms_eta}
priorbox_list = paddle.split(x2, num_or_sections=2, axis=1)
pb = priorbox_list[0]
pbv = priorbox_list[1]
pb = paddle.reshape(x=pb, shape=[-1, 4])
pbv = paddle.reshape(x=pbv, shape=[-1, 4])
pb_dim = fluid.layers.shape(pb)[0]
loc = paddle.reshape(x0, shape=[-1, pb_dim, 4])
conf_flatten = paddle.reshape(x1, shape=[0, pb_dim, -1])
out = fluid.layers.detection_output(loc=loc,
scores=conf_flatten,
prior_box=pb,
prior_box_var=pbv,
**detection_output_layer_attrs)
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def normalize(x, axis, param_name, param_shape, param_dtype):
l2_norm = paddle.fluid.layers.l2_normalize(x=x, axis=1)
param = paddle.static.nn.create_parameter(shape=param_shape,
dtype=param_dtype,
name=param_name)
param = paddle.reshape(param, [param.shape[-1]])
perm = list(range(len(l2_norm.shape)))
perm.pop(axis)
perm = perm + [axis]
l2_norm = paddle.transpose(l2_norm, perm=perm)
out = paddle.multiply(x=l2_norm, y=param)
perm = list(range(len(l2_norm.shape)))
dim = perm.pop(-1)
perm.insert(axis, dim)
out = paddle.transpose(out, perm=perm)
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
import paddle.fluid as fluid
def priorbox(x0,
x1,
min_sizes,
max_sizes,
aspect_ratios,
variance,
flip,
clip,
steps,
offset,
min_max_aspect_ratios_order):
priorbox_layer_attrs = {
"min_sizes": min_sizes,
"max_sizes": max_sizes,
"aspect_ratios": aspect_ratios,
"variance": variance,
"flip": flip,
"clip": clip,
"steps": steps,
"offset": offset,
"min_max_aspect_ratios_order": min_max_aspect_ratios_order}
box, var = fluid.layers.prior_box(input=x0,
image=x1,
**priorbox_layer_attrs)
box = paddle.reshape(x=box, shape=[1, 1, -1])
var = paddle.reshape(x=var, shape=[1, 1, -1])
out = paddle.concat(x=[box, var], axis=1)
return out
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
import paddle.fluid as fluid
def roipooling(x0,
x1,
pooled_height,
pooled_width,
spatial_scale):
roipooling_layer_attrs = {
"pooled_height": pooled_height,
"pooled_width": pooled_width,
"spatial_scale": spatial_scale}
slice_x1 = paddle.slice(input=x1, axes=[1],
starts=[1], ends=[5])
out = fluid.layers.roi_pool(input=x0,
rois=slice_x1,
**roipooling_layer_attrs)
return out
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
import paddle.fluid as fluid
def select(x,
input_shape,
point,
axis):
start = point[0]
if len(point) == 2:
end = point[1]
else:
end = input_shape[axis]
out = paddle.slice(x=x,
start=start,
end=end,
axes=[axis])
return out
\ No newline at end of file
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import numbers
import copy
import numpy as np
from x2paddle.decoder.caffe_decoder import CaffeGraph, CaffeGraphNode
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle.core.program import PaddleGraph
def _adjust_parameters(node):
data = node.data
# When using the protobuf-backend, each parameter initially has four dimensions.
# In certain cases (like FC layers), we want to eliminate the singleton dimensions.
# This implementation takes care of the common cases. However, it does leave the
# potential for future issues.
# The Caffe-backend does not suffer from this problem.
data = list(data)
squeeze_indices = [1] # Squeeze biases.
if node.layer_type == 'InnerProduct':
squeeze_indices.append(0) # Squeeze FC.
for idx in squeeze_indices:
if idx >= len(data):
continue
d = data[idx]
assert len(
d.shape
) == 4, 'invalid shape[%s] from caffe when adjust_parameters' % (
str(d.shape))
shape_old = d.shape
sq_axis = None
if idx == 0:
sq_axis = (0, 1)
elif idx == 1:
sq_axis = (0, 1, 2)
else:
continue
data[idx] = np.squeeze(d, axis=sq_axis)
shape_new = data[idx].shape
return data
def _get_kernel_parameters(kind, params):
assert kind in ["Convolution", "Pooling", "Deconvolution", "ConvolutionDepthwise"]
[k_h, k_w] = [1, 1]
if isinstance(params.kernel_size, numbers.Number):
[k_h, k_w] = [params.kernel_size] * 2
elif len(params.kernel_size) > 0:
k_h = params.kernel_h if params.kernel_h > 0 else params.kernel_size[
0]
k_w = params.kernel_w if params.kernel_w > 0 else params.kernel_size[
len(params.kernel_size) - 1]
elif params.kernel_h > 0 or params.kernel_w > 0:
k_h = params.kernel_h
k_w = params.kernel_w
[s_h, s_w] = [1, 1]
if isinstance(params.stride, numbers.Number):
[s_h, s_w] = [params.stride] * 2
elif len(params.stride) > 0:
s_h = params.stride_h if params.stride_h > 0 else params.stride[0]
s_w = params.stride_w if params.stride_w > 0 else params.stride[len(
params.stride) - 1]
elif params.stride_h > 0 or params.stride_w > 0:
s_h = params.stride_h
s_w = params.stride_w
[p_h, p_w] = [0, 0]
if isinstance(params.pad, numbers.Number):
[p_h, p_w] = [params.pad] * 2
elif len(params.pad) > 0:
p_h = params.pad_h if params.pad_h > 0 else params.pad[0]
p_w = params.pad_w if params.pad_w > 0 else params.pad[len(
params.pad) - 1]
elif params.pad_h > 0 or params.pad_w > 0:
p_h = params.pad_h
p_w = params.pad_w
dila_h = dila_w = 1
group = 1
c_o = 1
if kind in ["Convolution", "Deconvolution", "ConvolutionDepthwise"]:
if kind in ["Convolution", "Deconvolution"]:
c_o = params.num_output
dila_len = len(params.dilation)
if dila_len == 2:
dila_h = params.dilation[0]
dila_w = params.dilation[1]
elif dila_len == 1:
dila_h = dila_w = params.dilation[0]
else:
assert dila_len == 0, "invalid length[%s] of dilation in convolution" % (
dila_len)
if kind in ['Convolution', 'Deconvolution']:
group = params.group
kernel = [k_h, k_w]
stride = [s_h, s_w]
pad = [p_h, p_w]
dilation = [dila_h, dila_w]
return c_o, kernel, stride, pad, dilation, group
class CaffeOpMapper(OpMapper):
directly_map_ops = {
'AbsVal': 'paddle.abs',
'Sigmoid': 'paddle.nn.functional.sigmoid',
'TanH': 'paddle.tanh',
}
def __init__(self, decoder):
super(CaffeOpMapper, self).__init__()
self.graph = decoder.caffe_graph
if not self.op_checker():
raise Exception("Model is not supported yet.")
self.params = dict()
resolver = decoder.resolver
self.used_custom_layers = {}
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="static", source_type="caffe")
self.paddle_graph.inputs = self.graph.input_nodes
self.paddle_graph.outputs = self.graph.output_nodes
print("Total nodes: {}".format(
sum([
isinstance(node, CaffeGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if hasattr(self, op):
func = getattr(self, op)
func(node)
elif op in self.directly_map_ops:
self.directly_map(node)
print("\nNodes converted.")
self.paddle_graph.set_parameters(self.params)
self.paddle_graph.set_custom(self.used_custom_layers)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op) and \
op not in self.directly_map_ops and \
op not in self.elementwise_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def directly_map(self, node):
assert node.layer_type in self.directly_map_ops
op_info = self.directly_map_ops[node.layer_type]
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
kernel=op_info,
inputs={"x": input.name},
outputs=[node.name])
def Input(self, node):
shape = list(node.layer.input_param.shape[0].dim)[1:]
dtype = 'float32'
layer_attrs = {
"dtype": string(dtype),
"shape": [-1] + shape,
"name": string(node.name)
}
self.paddle_graph.add_layer(
kernel="paddle.static.data",
inputs={},
outputs=[node.name],
**layer_attrs)
def MemoryData(self, node):
params = node.layer.memory_data_param
transform_params = node.layer.transform_param
shape = list()
shape.append(params.batch_size)
shape.append(params.channels)
if hasattr(transform_params, "crop_size"):
shape.append(transform_params.crop_size)
shape.append(transform_params.crop_size)
else:
shape.append(params.width)
shape.append(params.height)
dtype = 'float32'
layer_attrs = {
"dtype": string(dtype),
"shape": shape,
"name": string(node.name)
}
self.paddle_graph.add_layer(
kernel="paddle.static.data",
inputs={},
outputs=[node.name],
**layer_attrs)
def Convolution(self, node):
data = node.data
params = node.layer.convolution_param
channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
if data is None:
data = []
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.name, node.layer_type))
input_c = node.in_shapes[0][1]
output_c = channel
data.append(
np.zeros([output_c, input_c, kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([output_c, ]).astype('float32'))
else:
data = _adjust_parameters(node)
kernel_weight_name = node.name + '_weights'
self.params[kernel_weight_name] = data[0]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
if len(data) == 2:
kernel_bias_name = node.name + '_bias'
self.params[kernel_bias_name] = data[1]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_bias_name],
shape=self.params[kernel_bias_name].shape,
dtype=string(str(self.params[kernel_bias_name].dtype)),
name=string(kernel_bias_name))
assert len(node.inputs
) == 1, 'The count of Convolution node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_inputs = {"x": input.name,
"weight": kernel_weight_name}
layer_attrs = {'stride': stride,
'padding': pad,
'dilation': dilation,
'groups': group}
if len(data) == 2:
layer_inputs["bias"] = kernel_bias_name
else:
layer_attrs["bias"] = None
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
def Deconvolution(self, node):
data = node.data
params = node.layer.convolution_param
channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
if data is None:
data = []
print(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
.format(node.name, node.layer_type))
input_c = node.in_shapes[0][1]
output_c = channel
data.append(
np.zeros([output_c, input_c, kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([output_c, ]).astype('float32'))
else:
data = _adjust_parameters(node)
kernel_weight_name = node.name + '_weights'
self.params[kernel_weight_name] = data[0]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
if len(data) == 2:
kernel_bias_name = node.name + '_bias'
self.params[kernel_bias_name] = data[1]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_bias_name],
shape=self.params[kernel_bias_name].shape,
dtype=string(str(self.params[kernel_bias_name].dtype)),
name=string(kernel_bias_name))
assert len(node.inputs
) == 1, 'The count of Deconvolution node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_inputs = {"x": input.name,
"weight": kernel_weight_name}
layer_attrs = {'stride': stride,
'padding': pad,
'dilation': dilation,
'groups': group}
if len(data) == 2:
layer_inputs["bias"] = kernel_bias_name
else:
layer_attrs["bias"] = None
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d_transpose",
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
def DepthwiseConvolution(self, node):
node.layer_type = "ConvolutionDepthwise"
self.ConvolutionDepthwise(node)
def ConvolutionDepthwise(self, node):
data = node.data
params = node.layer.convolution_param
out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
out_channel = params.num_output if params.num_output is not None else node.in_shapes[0][1]
in_channel = node.in_shapes[0][1]
group = int(in_channel / (in_channel / out_channel)) if in_channel > out_channel else int(in_channel /
(out_channel / in_channel))
if data is None:
data = []
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([out_channel, ]).astype('float32'))
else:
data = _adjust_parameters(node)
kernel_weight_name = node.name + '_weights'
self.params[kernel_weight_name] = data[0]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
if len(data) == 2:
kernel_bias_name = node.name + '_bias'
self.params[kernel_bias_name] = data[1]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_bias_name],
shape=self.params[kernel_bias_name].shape,
dtype=string(str(self.params[kernel_bias_name].dtype)),
name=string(kernel_bias_name))
assert len(node.inputs
) == 1, "The count of Deconvolution node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_inputs = {"x": input.name,
"weight": kernel_weight_name}
layer_attrs = {'stride': stride,
'padding': pad,
'dilation': dilation,
'groups': group}
if len(data) == 2:
layer_inputs["bias"] = kernel_bias_name
else:
layer_attrs["bias"] = None
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
def Pooling(self, node):
params = node.layer.pooling_param
ceil_mode = getattr(params, 'ceil_mode', True)
if not hasattr(params, 'ceil_mode'):
ceil_mode = True if getattr(params, "round_mode", 0) == 0 else False
global_pool = getattr(params, 'global_pooling', False)
kernel_default = [1, 1]
channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
assert len(
node.inputs) == 1, 'The count of Pooling node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
if global_pool:
if kernel[0] == 0:
kernel = [1, 1]
if params.pool == 0:
self.paddle_graph.add_layer(
"paddle.nn.functional.adaptive_max_pool2d",
inputs={"x": input.name},
outputs=layer_outputs,
output_size=kernel)
else:
self.paddle_graph.add_layer(
"paddle.nn.functional.adaptive_avg_pool2d",
inputs={"x": input.name},
outputs=[node.name],
output_size=kernel)
else:
if params.pool == 0:
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.max_pool2d",
inputs={"x": input.name},
outputs=[node.name],
kernel_size=kernel,
stride=stride,
padding=pad,
ceil_mode=ceil_mode)
else:
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.avg_pool2d",
inputs={"x": input.name},
outputs=[node.name],
kernel_size=kernel,
stride=stride,
padding=pad,
ceil_mode=ceil_mode)
def LRN(self, node):
assert len(node.inputs) == 1, 'The count of LRN node\'s input is not 1.'
params = node.layer.lrn_param
# The window size must be an odd value. For a window
# size of (2*n+1), Paddle defines depth_radius = n.
assert params.local_size % 2 == 1
# Caffe scales by (alpha/(2*n+1)), whereas Paddle
# just scales by alpha (as does Krizhevsky's paper).
# We'll account for that here.
alpha = params.alpha / float(params.local_size)
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'n': params.local_size,
'k': params.k,
'alpha': alpha,
'beta': params.beta,
'name': string(node.name)
}
self.paddle_graph.add_layer(
kernel="paddle.fluid.layers.lrn",
inputs={"input": input.name},
outputs=[node.name],
**layer_attrs)
def InnerProduct(self, node):
data = node.data
params = node.layer.inner_product_param
if data is None:
print(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0.'
.format(node.layer_name, node.layer_type))
input_c = node.in_shapes[0][1]
output_c = params.num_output
data = []
data.append(
np.zeros([input_c, output_c]).astype('float32').astype(
'float32'))
data.append(
np.zeros([output_c]).astype('float32').astype('float32'))
else:
data = _adjust_parameters(node)
# Reshape the parameters to Paddle's ordering
transpose_order = (1, 0)
w = data[0]
fc_shape = w.shape
output_channels = fc_shape[0]
w = w.reshape((output_channels, -1))
w = w.transpose(transpose_order)
data[0] = w
kernel_weight_name = node.name + '_weights'
self.params[kernel_weight_name] = data[0]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
if len(data) == 2:
kernel_bias_name = node.name + '_bias'
self.params[kernel_bias_name] = data[1]
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_bias_name],
shape=self.params[kernel_bias_name].shape,
dtype=string(str(self.params[kernel_bias_name].dtype)),
name=string(kernel_bias_name))
assert len(node.inputs
) == 1, 'The count of InnerProduct node\'s input is not 1.'
#params = node.layer.inner_product_param
assert params.axis == 1
assert params.bias_term == True
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_inputs = {"x": input.name,
"weight": kernel_weight_name}
layer_attrs = dict()
if len(data) == 2:
layer_inputs["bias"] = kernel_bias_name
else:
layer_attrs["bias"] = None
if node.in_shapes[0][-1] != data[0].shape[0]:
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[input.name],
shape=[-1, data[0].shape[0]])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.linear",
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
else:
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.linear",
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
def Softmax(self, node):
assert len(
node.inputs) == 1, 'The count of Softmax node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.softmax_param
axis = params.axis
shape = node.in_shapes[0]
dims = len(shape)
axis = axis + dims if axis < 0 else axis
layer_attrs = {'axis': axis, 'name': string(node.layer_name + '_softmax')}
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.softmax",
inputs={"x": input.name},
outputs=[node.layer_name],
**layer_attrs)
def Slice(self, node):
assert len(
node.inputs) == 1, "The count of Slice node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
top_len = len(node.layer.top)
params = node.layer.slice_param
axis = params.axis
slice_dim = params.slice_dim
if slice_dim != 1 and axis == 1:
axis = slice_dim
output_shape = node.out_shapes
sections_list = list()
outputs_list = list()
for i, s in enumerate(output_shape):
sections_list.append(s[axis])
outputs_list.append("{}_p{}".format(node.layer_name, i))
layer_attrs = {
'num_or_sections': sections_list,
'axis': axis,
}
self.paddle_graph.add_layer(
"paddle.split",
inputs={"x": input.name},
outputs=outputs_list,
**layer_attrs)
def Concat(self, node):
assert len(
node.inputs
) >= 1, 'The count of Concat node\'s input is not more than 1.'
inputs_list = []
for i in range(len(node.inputs)):
input = self.graph.get_input_node(node, idx=i, copy=True)
inputs_list.append(input.name)
params = node.layer.concat_param
axis = params.axis
layer_attrs = {'axis': axis, 'name': string(node.name)}
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": inputs_list},
outputs=[node.name],
**layer_attrs)
def ReLU(self, node):
"""
:param node:
:return:
"""
assert len(
node.inputs) == 1, 'The count of ReLU node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.relu_param
if params.HasField('negative_slope') and params.negative_slope != 0:
negative_slope = float(params.negative_slope)
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.leaky_relu",
inputs={"x": input.name},
outputs=[node.name],
negative_slope=negative_slope)
else:
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.relu",
inputs={"x": input.name},
outputs=[node.name])
def PReLU(self, node):
assert len(
node.inputs) == 1, 'The count of PReLU node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.prelu_param
mode_bool = params.channel_shared
output_shape = node.out_shapes[0]
if mode_bool:
num_parameters = 1
else:
num_parameters = output_shape[1]
data = node.data
assert data is not None, 'The parameter of {} (type is {}) is not set. You need to use python package of caffe to set the default value.'.format(
node.name, node.layer_type)
kernel_weight_name = node.name + '_weights'
self.params[kernel_weight_name] = np.squeeze(data[0])
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=[num_parameters],
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.prelu",
inputs={"x": input.name,
"weight": kernel_weight_name},
outputs=[node.name])
def Eltwise(self, node):
assert len(
node.inputs) == 2, "The count of Eltwise node\'s input is not 2."
params = node.layer.eltwise_param
mode = params.operation
inputs = []
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input0_name = input0.name
input1_name = input1.name
if mode == 0:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.name])
elif mode == 1:
if hasattr(params, 'coeff') and len(params.coeff) == 2:
coeff = params.coeff
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input0_name},
outputs=[node.name + '_mul0'],
scale=coeff[0])
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input1_name},
outputs=[node.name + '_mul1'],
scale=coeff[1])
inputs_dict = {}
inputs_dict['x'] = node.name + '_mul0'
inputs_dict['y'] = node.name + '_mul1'
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name])
else:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name])
else:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.max",
inputs=inputs_dict,
outputs=[node.name])
def BatchNorm(self, node):
assert len(
node.inputs) == 1, 'The count of BatchNorm node\'s input is not 1.'
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.batch_norm_param
if hasattr(params, 'eps'):
eps = params.eps
else:
eps = 1e-5
if hasattr(params, 'moving_average_fraction'):
momentum = params.moving_average_fraction
else:
momentum = 0.9
if node.data is None or len(node.data) != 3:
print(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
.format(node.layer_name, node.layer_type))
input_c = node.in_shapes[0][1]
mean = np.zeros([input_c, ]).astype('float32')
variance = np.zeros([input_c, ]).astype('float32')
scale = 0
else:
node.data = [np.squeeze(i).astype('float32') for i in node.data]
mean, variance, scale = node.data
# Prescale the stats
scaling_factor = 1.0 / scale if scale != 0 else 0
mean *= scaling_factor
variance *= scaling_factor
weight_name = node.name + '_weight'
self.paddle_graph.add_layer(
kernel="paddle.ones",
inputs={},
outputs=[weight_name],
shape=mean.shape,
dtype=string("float32"))
bias_name = node.name + '_bias'
self.paddle_graph.add_layer(
kernel="paddle.zeros",
inputs={},
outputs=[bias_name],
shape=mean.shape,
dtype=string("float32"))
mean_name = node.name + '_mean'
self.params[mean_name] = mean
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[mean_name],
shape=self.params[mean_name].shape,
dtype=string(str(self.params[mean_name].dtype)),
name=string(mean_name))
variance_name = node.name + '_variance'
self.params[variance_name] = variance
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[variance_name],
shape=self.params[variance_name].shape,
dtype=string(str(self.params[variance_name].dtype)),
name=string(variance_name))
layer_attrs = {
'epsilon': eps,
'momentum': momentum
}
if len(node.in_shapes[0]) == 2:
self.paddle_graph.add_layer(
"paddle.unsqueeze",
inputs={"x": input.name},
outputs=[input.name],
axis=[2,3])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.batch_norm",
inputs={"x": input.name,
"weight": weight_name,
"bias": bias_name,
"running_mean": mean_name,
"running_var": variance_name,},
outputs=[node.name],
**layer_attrs)
if len(node.in_shapes[0]) == 2:
self.paddle_graph.add_layer(
"paddle.squeeze",
inputs={"x": node.layer_name},
outputs=[node.layer_name],
axis=[2,3])
def Scale(self, node):
if node.data is None:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.name, node.layer_type))
self.params[node.name + "_cparam1"] = np.zeros([
node.in_shapes[0][1],
]).astype("float32")
self.params[node.name + "_cparam2"] = np.zeros([
node.in_shapes[0][1],
]).astype("float32")
else:
self.params[node.name + "_cparam1"] = np.squeeze(node.data[
0]).astype("float32")
if not node.layer.scale_param.bias_term:
self.params[node.layer_name + "_cparam2"] = np.zeros([
node.in_shapes[0][1],
]).astype("float32")
else:
self.params[node.layer_name + "_cparam2"] = np.squeeze(node.data[
1]).astype("float32")
params = node.layer.scale_param
axis = params.axis
inputs = []
if len(node.inputs) == 2:
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input0_name = input0.name
input1_name = input1.name
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.name + "_mul"],
axis=1)
else:
self.paddle_graph.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[node.name + "_cparam1"],
shape=self.params[node.name + "_cparam1"].shape,
dtype=string(str(self.params[node.name + "_cparam1"].dtype)),
name=string(node.name + "_cparam1"))
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input0_name = input0.name
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = node.name + "_cparam1"
if len(node.in_shapes[0]) == 2:
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"])
else:
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"],
axis=axis)
self.paddle_graph.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[node.name + "_cparam2"],
shape=self.params[node.name + "_cparam2"].shape,
dtype=string(str(self.params[node.name + "_cparam2"].dtype)),
name=string(node.name + "_cparam2"))
inputs_dict = {}
inputs_dict['x'] = node.name + "_mul"
inputs_dict['y'] = node.name + "_cparam2"
output_shape = node.out_shapes[0]
if axis == -1:
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name])
else:
if axis < 0:
axis = axis + len(output_shape)
param2_shape = self.params[node.name + "_cparam2"].shape
param2_shape_len = len(param2_shape)
diff_len = len(output_shape) - axis - param2_shape_len
new_shape = list(param2_shape) + [1] * diff_len
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": node.name + "_cparam2"},
outputs=[node.name + "_cparam2"],
shape=new_shape)
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name])
def Reshape(self, node):
input = self.graph.get_input_node(node, idx=0, copy=True)
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[node.name],
shape=output_shape)
def ArgMax(self, node):
assert len(node.inputs) == 1 and len(
node.outputs
) == 1, "The count of ArgMax node\'s input and output is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
in_shapes = node.in_shapes[0]
params = node.layer.argmax_param
out_max_val = params.out_max_val if hasattr(params,
out_max_val) else False
top_k = params.top_k if hasattr(params, top_k) else 1
axis = params.axis if hasattr(params, axis) else -1
if axis < 0:
axis += len(in_shapes)
if out_max_val is True:
self.paddle_graph.add_layer(
"paddle.topk",
inputs={"x": input.name},
outputs=[node.name + "_topk_var", node.name + "_index_var"],
k=top_k)
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": node.name + "_index_var"},
outputs=[node.name + "_index_var"],
dtype="{}_topk_var.dtype".format(node.name))
self.paddle_graph.add_layer(
"paddle.concat",
inputs={"x": [node.name + "_topk_var", node.name + "_index_var"]},
outputs=[node.name],
axis=axis)
else:
self.paddle_graph.add_layer(
"paddle.topk",
inputs={"x": input.name},
outputs=["_", node.name],
k=top_k)
def Crop(self, node):
assert len(
node.inputs) == 2, "The count of Crop node\'s input is not 2."
input = self.graph.get_input_node(node, idx=0, copy=True)
example = self.graph.get_input_node(node, idx=1, copy=True)
params = node.layer.crop_param
axis = params.axis
in_shapes = node.in_shapes[0]
if axis < 0:
axis += len(in_shapes)
offset_real = [0] * len(in_shapes)
if hasattr(params, "offset") and len(params.offset) > 0:
offset = list(params.offset)
assert (len(in_shapes) - axis
) == len(offset), "invalid offset[%s] in crop layer" % (
str(offset))
offset_real = [0] * axis + offset
self.paddle_graph.add_layer(
"paddle.crop",
inputs={"x": input.name},
outputs=[node.name],
shape=node.in_shapes[1],
offsets=list(offset_real))
def Flatten(self, node):
assert len(
node.
inputs) == 1, "The count of DetectionOutput node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[node.name],
shape=node.out_shapes[0])
def Power(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.power_param
layer_attrs = {
'scale': params.scale,
'bias': params.shift,
'bias_after_scale': True
}
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
self.paddle_graph.add_layer(
"paddle.pow",
inputs={"x": node.name},
outputs=[node.name],
exponent=params.power)
def Reduction(self, node):
assert len(
node.inputs) == 1, "The count of Reduction node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.reduction_param
operation = params.operation
axis = params.axis
coeff = params.coeff
assert operation >= 1 and operation <= 4, "reduction reduction [%s] error" % (
operation)
input_len = len(node.in_shapes[0])
if axis < 0:
axis += input_len + 1
dim = list(range(input_len))
# operation = SUM
if operation == 1:
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": input.name},
outputs=[node.name],
**layer_attrs)
# operation = ASUM
elif operation == 2:
self.paddle_graph.add_layer(
"paddle.abs",
inputs={"x": input.name},
outputs=[node.name])
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": node.name},
outputs=[node.name],
**layer_attrs)
# operation = SUMSQ
elif operation == 3:
self.paddle_graph.add_layer(
"paddle.pow",
inputs={"x": input.name},
outputs=[node.name],
exponent=2.0)
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": node.name},
outputs=[node.name],
**layer_attrs)
# operation = MEAN
else:
layer_attrs = {
"axis": dim[axis:],
"keepdim": False,
}
self.paddle_graph.add_layer(
"paddle.mean",
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": node.name},
outputs=[node.name],
scale=coeff)
def Axpy(self, node):
assert len(node.inputs) == 1 and len(
node.outputs
) == 1, "The count of Axpy node\'s input and output is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.axpy_param
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input2 = self.graph.get_input_node(node, idx=2, copy=True)
input0_name = input0.name
input1_name = input1.name
input2_name = input2.name
inputs_dict = {}
inputs_dict['x'] = input1_name
inputs_dict['y'] = input0_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.name + "_mul"],
axis=0)
inputs_dict = {}
inputs_dict['x'] = node.name + "_mul"
inputs_dict['y'] = input2_name
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name + "_mul"])
def DetectionOutput(self, node):
assert len(
node.inputs) == 3, "The count of DetectionOutput node\'s input is not 3."
inputs_dict = dict()
for i in range(len(node.inputs)):
input = self.graph.get_input_node(node, idx=i, copy=True)
if i == 1:
input = self.graph.get_input_node(node, idx=i, copy=True)
while input is not None \
and input.layer_type != 'Softmax' \
and input.layer_type != 'Sigmoid':
input = self.graph.get_input_node(input, idx=0, copy=True)
assert input is not None, 'This kind of DetectionOutput is not supported!'
input = self.graph.get_input_node(input, idx=0, copy=True)
inputs_dict["x{}".format(i)] = input.name
params = node.layer.detection_output_param
nms_param = params.nms_param
nms_param_dict = dict()
nms_param_dict["nms_threshold"] = nms_param.nms_threshold
nms_param_dict["top_k"] = nms_param.top_k
nms_param_dict["eta"] = nms_param.eta
if nms_param is None:
nms_param_dict = {"nms_threshold": 0.3, "top_k": 10, "eta": 1.0}
default = {"nms_threshold": 0.3, "top_k": 10, "eta": 1.0}
fields = ["eta", "top_k", "nms_threshold"]
for f in default.keys():
if f not in nms_param_dict:
nms_param_dict[f] = default[f]
layer_attrs = {
"background_label": params.background_label_id,
"nms_threshold": nms_param_dict["nms_threshold"],
"nms_top_k": nms_param_dict["top_k"],
"keep_top_k": params.keep_top_k,
"score_threshold": params.confidence_threshold,
"nms_eta": nms_param_dict["eta"]}
self.paddle_graph.add_layer(
kernel="custom_layer:detectionoutput",
inputs=inputs_dict,
outputs=[node.name],
**layer_attrs)
def Normalize(self, node):
assert len(
node.inputs) == 1, "The count of Normalize node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.norm_param
scale_name = node.name + "_scale"
if node.data is None or len(node.data) != 1:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(scale_name, node.layer_type))
self.params[scale_name] = \
np.zeros([1] if params.channel_shared else [node.in_shapes[0][1]]).astype("float32")
else:
self.params[scale_name] = _adjust_parameters(node)[0]
layer_attrs = {
"axis": -1 if params.channel_shared else 1,
"param_name": string(scale_name),
"param_shape": self.params[scale_name].shape,
"param_dtype": string(self.params[scale_name].dtype)}
self.paddle_graph.add_layer(
"custom_layer:normalize",
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
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.name],
perm=order)
def PriorBox(self, node):
assert len(
node.inputs) == 2, "The count of PriorBox 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.prior_box_param
steps = tuple(params.step) if type(params.step) \
is list or type(params.step) is tuple \
else (params.step, params.step)
layer_attrs = {
"min_sizes": params.min_size,
"max_sizes": params.max_size,
"aspect_ratios": params.aspect_ratio,
"variance": params.variance,
"flip": params.flip,
"clip": params.clip,
"steps": steps,
"offset": params.offset,
"min_max_aspect_ratios_order": True}
self.paddle_graph.add_layer(
"custom_layer:priorbox",
inputs=inputs_dict,
outputs=[node.name],
**layer_attrs)
def ReLU6(self, node):
assert len(
node.inputs) == 1, "The count of RelU6 node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.nn.functional.relu6",
inputs={"x": input.name},
outputs=[node.name])
def ROIPooling(self, node):
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=[node.name],
**layer_attrs)
def ShuffleChannel(self, node):
assert len(
node.inputs) == 1, "The count of ShuffleChannel node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.shuffle_channel_param
self.paddle_graph.add_layer(
"paddle.fluid.layers.shuffle_channel",
inputs={"x": input.name},
outputs=[node.layer_name],
group=params.group)
def Upsample(self, node):
assert len(
node.inputs) == 1, "The count of Upsample node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.upsample_param
layer_attrs = {
"align_corners": False,
"scale_factor": params.scale,
"mode": "nearest"}
self.paddle_graph.add_layer(
"paddle.nn.functional.interpolate",
inputs={"x": input.name},
outputs=[node.layer_name],
**layer_attrs)
def Select(self, node):
assert len(
node.inputs) == 1, "The count of Select node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
in_shapes = node.in_shapes[0]
params = node.layer.select_param
layer_attrs = {
"in_shapes": in_shapes,
"point": params.slice_point,
"axis": params.axis}
self.paddle_graph.add_layer(
"custom_layer:select",
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .one_hot import one_hot
from .pad_two_input import pad_with_two_input
from .pad_all_dim2 import pad_all_dim2
from .pad_all_dim4 import pad_all_dim4
from .pad_all_dim4_one_input import pad_all_dim4_one_input
from .lrn import local_response_norm
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def local_response_norm(x, size, alpha=1e-4, beta=0.75, k=1.):
sizes = x.shape
dim = len(sizes)
if dim < 3:
raise ValueError(
'Expected 3D or higher dimensionality input, but got {} dimensions'.
format(dim))
div = paddle.unsqueeze(paddle.multiply(x, x), axis=1)
pad4d_shape = [size // 2, (size - 1) // 2, 0, 0]
pool2d_shape = (1, size)
pad5d_shape = [size // 2, (size - 1) // 2, 0, 0, 0, 0]
pool3d_shape = (1, 1, size)
if dim == 3:
div = paddle.nn.functional.pad(div, pad=pad4d_shape)
div = paddle.nn.functional.avg_pool2d(
div, kernel_size=pool2d_shape, stride=1)
div = paddle.squeeze(div, axis=1)
else:
tmp = paddle.unsqueeze(x, axis=1)
reshape_shape = paddle.shape(tmp)
new_reshape_shape = paddle.cast(reshape_shape, "float32")
index = paddle.full(shape=[1], fill_value=-2, dtype="int32")
value = paddle.full(shape=[1], fill_value=-1, dtype="float32")
new_reshape_shape = paddle.scatter(new_reshape_shape, index, value)
new_reshape_shape = paddle.cast(new_reshape_shape, "int32")
div = paddle.reshape(div, shape=reshape_shape)
div = paddle.nn.functional.pad(div,
pad=pad5d_shape,
data_format='NCDHW')
div = paddle.nn.functional.avg_pool3d(
div, kernel_size=pool3d_shape, stride=1)
div = paddle.reshape(paddle.squeeze(div, axis=1), sizes)
div = paddle.scale(div, scale=alpha, bias=k)
div = paddle.pow(div, beta)
res = paddle.divide(x, div)
return res
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def one_hot(indices, depth, values, axis):
indices_shape = indices.shape
rank = len(indices.shape)
real_axis = axis
if axis < 0:
real_axis = axis + rank + 1
depth_range = paddle.arange(end=depth)
ls = tuple(indices_shape[0: real_axis])
rs = tuple(indices_shape[real_axis: rank])
targets = paddle.reshape(depth_range, (1,) * (real_axis-0) + tuple(depth_range.shape) + (1,) * (rank-real_axis))
mod = paddle.mod(indices, depth)
v = paddle.reshape(mod, ls + (1,) + rs)
out = targets == v
out = paddle.cast(out, "float32")
on_value = paddle.slice(values, axes=[0], starts=[1], ends=[2])
off_value = paddle.slice(values, axes=[0], starts=[0], ends=[1])
out = out * (on_value - off_value) + off_value
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def pad_all_dim2(x, pad, value, mode):
pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0])
pad = paddle.reverse(pad, axis=[0])
pad = paddle.flatten(pad)
pad = paddle.cast(pad, dtype="int32")
x = paddle.unsqueeze(x, axis=[0, 1])
out = paddle.nn.functional.pad(x=x,
pad=pad,
mode=mode,
data_format='NCHW',
value=value)
out = paddle.squeeze(out, axis=[0, 1])
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def pad_all_dim4(x, pad, value, mode):
pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0])
pad = paddle.reverse(pad, axis=[0])
pad = paddle.flatten(pad)
pad = paddle.cast(pad, dtype="int32")
pad1, pad2 = paddle.split(pad, num_or_sections=2, axis=0)
x = paddle.nn.functional.pad(x=x,
pad=pad1,
mode=mode,
data_format='NCHW',
value=value)
x = paddle.transpose(x, perm=[2, 3, 0, 1])
x = paddle.nn.functional.pad(x=x,
pad=pad2,
mode=mode,
data_format='NCHW',
value=value)
out = paddle.transpose(x, perm=[2, 3, 0, 1])
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def pad_all_dim4_one_input(x, pad, value, mode):
x = paddle.nn.functional.pad(x=x,
pad=pad[0: 4],
mode=mode,
data_format='NCHW',
value=value)
x = paddle.transpose(x, perm=[2, 3, 0, 1])
x = paddle.nn.functional.pad(x=x,
pad=pad[4: 9],
mode=mode,
data_format='NCHW',
value=value)
out = paddle.transpose(x, perm=[2, 3, 0, 1])
return out
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import paddle
def pad_with_two_input(x, pad, value, mode, data_format):
pad = paddle.reshape(pad, shape=[2, -1])
pad = paddle.transpose(pad, perm=[1, 0])
pad = paddle.reverse(pad, axis=[0])
pad = paddle.flatten(pad)
pad = paddle.cast(pad, dtype="int32")
out = paddle.nn.functional.pad(x=x,
pad=pad,
value=value,
mode=mode,
data_format=data_format)
return out
\ No newline at end of file
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import sys
from x2paddle.op_mapper.static.onnx2paddle.opset9 import OpSet9
from x2paddle.core.op_mapper import OpMapper
from x2paddle.decoder.onnx_decoder import ONNXGraphNode
from x2paddle.core.program import PaddleGraph
class ONNXOpMapper(OpMapper):
def __init__(self, decoder):
super(ONNXOpMapper, self).__init__()
self.support_op_sets = [9, ]
self.default_op_set = 9
self.graph = decoder.graph
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="static", source_type="onnx")
self.paddle_graph.outputs = self.graph.output_nodes
self.opset = self.create_opset(decoder)
if not self.op_checker():
raise Exception("Model is not supported yet.")
print("Total nodes: {}".format(
sum([
isinstance(node, ONNXGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if hasattr(self.opset, op):
func = getattr(self.opset, op)
func(node)
elif op in self.opset.directly_map_ops:
self.opset.directly_map(node)
elif op in self.opset.elementwise_ops:
self.opset.elementwise_map(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.opset.params)
self.paddle_graph.set_inputs_info(self.opset.inputs_info)
self.paddle_graph.inputs = self.graph.input_nodes
self.paddle_graph.outputs = self.graph.output_nodes
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self.opset, op) and \
op not in self.opset.directly_map_ops and \
op not in self.opset.elementwise_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def create_opset(self, decoder):
run_op_set = self.default_op_set
opset = ''
if decoder.op_set in self.support_op_sets:
opset = 'OpSet' + str(decoder.op_set)
elif decoder.op_set < self.default_op_set:
opset = 'OpSet' + str(self.default_op_set)
else:
for op_set in self.support_op_sets:
if decoder.op_set > op_set:
run_op_set = op_set
else:
break
opset = 'OpSet' + str(run_op_set)
print(
'Now, onnx2paddle support convert onnx model opset_verison {},'
'opset_verison of your onnx model is {}, automatically treated as op_set: {}.'
.format(self.support_op_sets, decoder.op_set, run_op_set))
return eval(opset)(decoder, self.paddle_graph)
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode
from x2paddle.core.graph import GraphNode
from x2paddle.core.util import string
from functools import reduce
import numpy as np
import onnx
import onnx.numpy_helper as numpy_helper
from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE
import logging as _logging
from collections import OrderedDict
import math
import os
import copy
import sys
import shutil
_logger = _logging.getLogger(__name__)
def _const_weight_or_none(node, necessary=False):
if 'Constant' in node.layer_type:
return node.value
if isinstance(node, ONNXGraphDataNode):
return node.weight
if necessary:
assert '{} should be an initializer or Constant operator.'.format(
node.layer_name)
return None
def _is_static_shape(shape):
negtive_dims = 0
error_dims = 0
for dim in shape:
if dim < 0:
negtive_dims += 1
if dim < -1:
error_dims += 1
if negtive_dims > 1:
return False
if error_dims > 0:
return False
return True
def _get_same_padding(in_size, kernel_size, stride):
new_size = int(math.ceil(in_size * 1.0 / stride))
pad_size = (new_size - 1) * stride + kernel_size - in_size
pad0 = int(pad_size / 2)
pad1 = pad_size - pad0
return [pad0, pad1]
def print_mapping_info(func):
def run_mapping(*args, **kwargs):
node = args[1]
try:
res = func(*args, **kwargs)
except:
print("convert failed node:{}, op_type is {}".format(
node.layer_name[9:], node.layer_type))
raise
else:
#print("convert successfully node:{}, op_type is {}".format(
# node.layer_name[9:], node.layer_type))
return res
return run_mapping
class OpSet9():
elementwise_ops = {
'Add': 'paddle.add',
'Div': 'paddle.divide',
'Sub': 'paddle.subtract',
'Mul': 'paddle.multiply',
'Pow': 'paddle.pow',
'Less': 'paddle.less_than',
}
directly_map_ops = {
'Ceil': ['paddle.ceil'],
# reduce function
'ReduceMean': [
'paddle.mean', dict(
axes='axis', keepdims='keepdim'), dict(
axes=None, keepdims=1)
],
'ReduceSum': [
'paddle.sum', dict(
axes='axis', keepdims='keepdim'), dict(
axes=None, keepdims=1)
],
'ReduceMin': [
'paddle.min', dict(
axes='axis', keepdims='keepdim'), dict(
axes=None, keepdim=1)
],
'ReduceMax': [
'paddle.max', dict(
axes='axis', keepdims='keepdim'), dict(
axes=None, keepdim=1)
],
'ReduceProd': [
'paddle.prod', dict(
axes='axis', keepdims='keepdim'), dict(
axes=None, keepdim=1)
],
# active function
'Relu': ['paddle.nn.functional.relu'],
'LeakyRelu': [
'paddle.nn.functional.leaky_relu', dict(alpha='negative_slope'),
dict(negative_slope=.01)
],
'Elu':
['paddle.nn.functional.elu', dict(alpha='alpha'), dict(alpha=1.)],
'ThresholdedRelu': [
'paddle.nn.functional.thresholded_relu', dict(alpha='threshold'),
dict(alpha=1.)
],
'Tanh': ['paddle.nn.functional.tanh'],
'Sigmoid': ['paddle.nn.functional.sigmoid'],
'Softsign': ['paddle.nn.functional.softsign'],
'Softplus': [
'paddle.nn.functional.softplus', dict(threshold='threshold'),
dict(threshold=float(sys.maxsize))
],
'Exp': ['paddle.exp'],
'Log': ['paddle.log'],
'Softmax':
['paddle.nn.functional.softmax', dict(axis='axis'), dict(axis=1)],
'Sqrt': ['paddle.sqrt'],
'Floor': ['paddle.floor'],
'Abs': ['paddle.abs'],
'Erf': ['paddle.erf'],
}
def __init__(self, decoder, paddle_graph):
super(OpSet9, self).__init__()
self.graph = decoder.graph
self.paddle_graph = paddle_graph
self.input_index = 0
self.inputs_info = dict()
self.params = dict()
@print_mapping_info
def directly_map(self, node, *args, **kwargs):
inputs = node.layer.input
assert len(inputs) == 1, 'directly_map error with multi inputs'
input = self.graph.get_input_node(node, idx=0, copy=True)
onnx_attrs = node.attr_map
if '' in onnx_attrs:
onnx_attrs.pop('')
if '_' in onnx_attrs:
onnx_attrs.pop('_')
op_info = self.directly_map_ops[node.layer_type]
paddle_op = op_info[0]
layer_attrs = dict()
if len(op_info) > 1:
attrs_name_map_dict = op_info[1]
for onnx_attr_name, pd_attr_name in attrs_name_map_dict.items():
if onnx_attr_name in onnx_attrs:
layer_attrs[pd_attr_name] = onnx_attrs[onnx_attr_name]
else:
layer_attrs[pd_attr_name] = op_info[2][onnx_attr_name]
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def elementwise_map(self, node):
op_type = self.elementwise_ops[node.layer_type]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
inputs_dict = {'x': val_x.name, 'y': val_y.name}
self.paddle_graph.add_layer(
op_type, inputs=inputs_dict, outputs=[node.name])
@print_mapping_info
def place_holder(self, node):
shape = node.out_shapes[0]
for i, dim_shape in enumerate(shape):
if dim_shape == 0 and i == 0:
shape[i] = 1
if dim_shape == 0 and i != 0:
assert 'shape of input is not assigned'
self.paddle_graph.add_layer(
kernel="paddle.static.data",
inputs={},
outputs=[node.name],
dtype=string(node.dtype),
shape=shape,
name=string(node.name))
self.inputs_info["x{}".format(self.input_index)] = [shape, node.dtype]
self.input_index += 1
@print_mapping_info
def create_parameter(self, node, parameter=None):
if parameter is not None:
node = parameter
dtype = node.dtype
shape = node.out_shapes[0]
if hasattr(node.weight, "shape") and len(node.weight.shape) == 0:
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=node.weight)
else:
self.params[node.name] = node.weight
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=shape,
name=string(node.name),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
def _pad_if_asymmetric(self, node, pads, val_name): # pads: SSEE
assert len(pads) & 1 == 0
symmetric = True
ndims = len(pads) // 2
for idx_dim in range(ndims):
if pads[idx_dim] != pads[ndims + idx_dim]:
symmetric = False
break
if symmetric:
return pads[:ndims], val_name
val_padded = self.Pad(node, op_independent=False)
return [0] * ndims, val_padded
def _interpolate(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
inputs = {'x': val_x.name}
attrs = dict()
if node.layer_type == 'Resize':
if len(node.layer.input) == 2:
# opset 10
val_scales = self.graph.get_input_node(node, idx=1, copy=True)
# TODO(syf): paddle.nn.functional.interpolate will support the length
# which is the same as the rank of input.
# inputs['scale_factor'] = val_scales.name
attrs['scale_factor'] = self.params[val_scales.name].tolist()[
2:]
elif len(node.layer.input) == 3:
# opset 11
val_scales = self.graph.get_input_node(node, idx=2, copy=True)
# TODO(syf): paddle.nn.functional.interpolate will support the length
# which is the same as the rank of input.
# inputs['scale_factor'] = val_scales.name
attrs['scale_factor'] = self.params[val_scales.name].tolist()[
2:]
elif len(node.layer.input) == 4:
# opset 11
val_sizes = self.graph.get_input_node(node, idx=3, copy=True)
var_nc, var_hw = val_sizes.name + '_nc', val_sizes.name + '_hw'
self.paddle_graph.add_layer(
'paddle.split',
inputs={"x": val_sizes.name},
outputs=[var_nc, var_hw],
num_or_sections=[2, 2],
axis=0)
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": var_hw},
outputs=[var_hw],
dtype=string('int32'))
inputs['size'] = var_hw
attrs = {
"align_corners": False,
"mode": string(node.get_attr('mode', 'nearest'))
}
mode = node.get_attr('mode', 'nearest')
if mode == "linear":
attrs["mode"] = string("bilinear")
if node.get_attr('coordinate_transformation_mode',
'half_pixel') == 'pytorch_half_pixel':
attrs["align_corners"] = False
attrs["align_mode"] = 0
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
return
elif node.layer_type == 'Upsample':
val_scales = self.graph.get_input_node(node, idx=1, copy=True)
self.paddle_graph.add_layer(
"paddle.slice",
inputs={"input": val_scales.name},
outputs=[val_scales.name],
axes=[0],
starts=[2],
ends=[4])
inputs['scale_factor'] = val_scales.name
mode = node.get_attr('mode', 'nearest')
attrs.update({
"align_corners": False,
"mode": string(mode),
"align_mode": 1
})
val_x_shape = val_x.out_shapes[0]
if mode == "linear" and len(val_x_shape) == 4:
attrs["mode"] = string("bilinear")
if node.get_attr('coordinate_transformation_mode',
'half_pixel') == 'pytorch_half_pixel':
attrs["align_corners"] = False
attrs["align_mode"] = 0
else:
attrs["align_corners"] = True
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
@print_mapping_info
def HardSigmoid(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
alpha = node.get_attr('alpha', 0.2)
beta = node.get_attr('beta', 0.5)
self.paddle_graph.add_layer(
kernel="paddle.scale",
inputs={"x": val_x.name},
outputs=[node.name + "_val"],
scale=alpha,
bias=beta)
self.paddle_graph.add_layer(
kernel="paddle.clip",
inputs={"x": node.name + "_val"},
outputs=[node.name],
min=0.0,
max=1.0)
@print_mapping_info
def Shape(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": val_x.name},
outputs=[node.name])
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": node.name},
outputs=[node.name],
dtype=string('int64'))
@print_mapping_info
def RoiAlign(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_rois = self.graph.get_input_node(node, idx=1, copy=True)
pooled_height = node.get_attr('output_height')
pooled_width = node.get_attr('output_width')
spatial_scale = node.get_attr('spatial_scale')
sampling_ratio = node.get_attr('sampling_ratio')
layer_attrs = {
'pooled_height': pooled_height,
'pooled_width': pooled_width,
'spatial_scale': spatial_scale,
'sampling_ratio': sampling_ratio,
}
self.paddle_graph.add_layer(
'paddle.fluid.layers.roi_align',
inputs={'input': val_x.name,
'rois': val_rois.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def MaxRoiPool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_rois = self.graph.get_input_node(node, idx=1, copy=True)
spatial_scale = node.get_attr('spatial_scale')
pooled_height, pooled_width = node.get_attr('pooled_shape')
layer_attrs = {
'pooled_height': pooled_height,
'pooled_width': pooled_width,
'spatial_scale': spatial_scale,
}
self.paddle_graph.add_layer(
'paddle.fluid.layers.roi_pool',
inputs={'input': val_x.name,
'rois': val_rois.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Pad(self, node, op_independent=True):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
pads = node.get_attr('pads')
is_pads_attr = True
if pads is None:
val_pad = self.graph.get_input_node(node, idx=1, copy=True)
pad_shape = val_pad.out_shapes[0]
is_pads_attr = False
pads = _const_weight_or_none(val_pad)
if pads is not None:
is_pads_attr = True
mode = node.get_attr('mode', 'constant')
value = node.get_attr('value', 0.)
data_shape = val_x.out_shapes[0]
output_shape = node.out_shapes[0]
assume_pad = False
layer_attrs = {}
layer_attrs['mode'] = string(mode)
layer_attrs['value'] = value
if not op_independent:
output_name = node.name + '_paded'
else:
output_name = node.name
layer_outputs = [output_name]
if is_pads_attr:
paddings = []
paddle_op = 'paddle.nn.functional.pad'
if len(pads) == 10 and sum(pads) == 0:
pads = pads[0:6]
if len(pads) in [2, 4, 6]:
if data_shape:
assume_pad |= data_shape and 2 * (len(data_shape) - 2
) == len(pads) # NCHW
if output_shape:
assume_pad |= output_shape and 2 * (len(output_shape) - 2
) == len(pads) # NCHW
if assume_pad:
if len(pads) == 2:
data_format = "NCL"
elif len(pads) == 4:
data_format = "NCHW"
else:
data_format = "NCDHW"
paddings = np.array(pads).reshape(
(2, -1)).transpose().astype("int32")
paddings = np.flip(paddings, axis=0).flatten().tolist()
layer_attrs['pad'] = paddings
layer_attrs['data_format'] = string(data_format)
else:
if data_shape:
assume_pad |= data_shape and 2 * len(data_shape) == len(
pads) # NCHW
if output_shape:
assume_pad |= output_shape and 2 * len(
output_shape) == len(pads) # NCHW
if assume_pad:
paddings = np.array(pads).reshape(
(2,
-1)).transpose().astype("int32").flatten().tolist()
layer_attrs['pad'] = paddings
else:
raise Exception("The padding value {} is wrong!".format(
pads))
elif len(pads) == 8:
if data_shape:
assume_pad |= data_shape and 2 * len(data_shape) == len(
pads) # NCHW
if output_shape:
assume_pad |= output_shape and 2 * len(output_shape) == len(
pads) # NCHW
if assume_pad:
paddings = np.array(pads).reshape(
(2, -1)).transpose().astype("int32")
paddings = np.flip(paddings, axis=0).flatten().tolist()
if sum(paddings[:4]) == 0:
paddings = paddings[4:]
layer_attrs['pad'] = paddings
else:
layer_attrs['pad'] = paddings
paddle_op = "custom_layer:pad_all_dim4_one_input"
else:
raise Exception("The padding value {} is wrong!".format(pads))
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=layer_outputs,
**layer_attrs)
if not op_independent:
return node.name + '_paded'
else:
pads_len = val_pad.out_shapes[0][0]
if pads_len in [2, 4, 6]:
if data_shape:
assume_pad |= data_shape and 2 * (len(data_shape) - 2
) == pads_len # NCHW
if output_shape:
assume_pad |= output_shape and 2 * (len(output_shape) - 2
) == pads_len # NCHW
if assume_pad:
if pads_len == 2:
data_format = "NCL"
elif pads_len == 4:
data_format = "NCHW"
else:
data_format = "NCDHW"
self.paddle_graph.add_layer(
"custom_layer:pad_with_two_input",
inputs={'x': val_x.name,
'pad': val_pad.name},
outputs=layer_outputs,
value=value,
mode=string(mode),
data_format=string(data_format))
else:
if data_shape:
assume_pad |= data_shape and 2 * len(
data_shape) == pads_len # NCHW
if output_shape:
assume_pad |= output_shape and 2 * len(
output_shape) == pads_len # NCHW
if assume_pad:
if pads_len == 4:
self.paddle_graph.add_layer(
"custom_layer:pad_all_dim2",
inputs={'x': val_x.name,
'pad': val_pad.name},
outputs=layer_outputs,
value=value,
mode=string(mode))
else:
raise Exception("The padding value is wrong!")
elif pads_len == 8:
if data_shape:
assume_pad |= data_shape and 2 * len(
data_shape) == pads_len # NCHW
if output_shape:
assume_pad |= output_shape and 2 * len(
output_shape) == pads_len # NCHW
if assume_pad:
self.paddle_graph.add_layer(
"custom_layer:pad_all_dim4",
inputs={'x': val_x.name,
'pad': val_pad.name},
outputs=layer_outputs,
value=value,
mode=string(mode))
else:
print(pads_len)
raise Exception("The padding value is wrong!")
if not op_independent:
return node.name + '_paded'
@print_mapping_info
def Unsqueeze(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
axes = node.get_attr('axes')
layer_attrs = {'axis': axes}
if len(val_x.out_shapes[0]) == 0:
if node.name:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=[1])
else:
self.paddle_graph.add_layer(
'paddle.unsqueeze',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Shrink(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
bias = node.get_attr('bias')
lambd = node.get_attr('lambd')
assert bias == 0.0, 'not support bias!=0'
self.paddle_graph.add_layer(
'paddle.nn.functional.hardshrink',
inputs={"x": val_x.name},
outputs=[node.name],
threshold=lambd)
@print_mapping_info
def Constant(self, node):
val_output = self.graph.get_node(node.layer.output[0], copy=True)
value = node.get_attr('value')
dtype = np.dtype(value.dtype)
output_dtype = val_output.dtype
if output_dtype:
assert dtype == output_dtype, 'tensor dtype unmatches storage dtype'
shape = node.get_attr('shape', None)
if shape is None:
shape = val_output.out_shapes[0]
if shape is None:
shape = list(value.shape)
_logger.warning('in (Constant -> %s): '
'attribute "shape" of %s not inferred, '
'using value as 1-D tensor may lead to fails',
val_output.name, val_output.name)
if len(value) == 1:
value = value.tolist()
value = value[0]
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=value)
else:
value = np.reshape(value, shape)
self.params[node.name] = value
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=shape,
name=string(node.name),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
@print_mapping_info
def Resize(self, node):
self._interpolate(node)
@print_mapping_info
def Upsample(self, node):
self._interpolate(node)
@print_mapping_info
def InstanceNormalization(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_scale = self.graph.get_input_node(node, idx=1, copy=True)
val_b = self.graph.get_input_node(node, idx=2, copy=True)
epsilon = node.get_attr('epsilon', 1e-5)
layer_attrs = {'eps': epsilon, }
dim = len(val_x.out_shapes[0])
if dim == 2:
layer_attrs["data_format"] = string("NC")
elif dim == 3:
layer_attrs["data_format"] = string("NCL")
elif dim == 4:
layer_attrs["data_format"] = string("NCHW")
elif dim == 5:
layer_attrs["data_format"] = string("NCDHW")
else:
raise Exception(
"The paddle only support 2D, 3D, 4D or 5D input in InstanceNormalization."
)
self.paddle_graph.add_layer(
"paddle.nn.functional.instance_norm",
inputs={
"x": val_x.name,
"weight": val_scale.name,
"bias": val_b.name
},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Expand(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_shape = self.graph.get_input_node(node, idx=1, copy=True)
val_x_dtype = val_x.dtype
name_ones = node.name + '_ones'
attr_ones = {
'shape': val_shape.name,
'dtype': string(val_x_dtype),
'fill_value': 1
}
self.paddle_graph.add_layer(
'paddle.full', inputs={}, outputs=[name_ones], **attr_ones)
inputs_dict = {'x': name_ones, 'y': val_x.name}
self.paddle_graph.add_layer(
'paddle.multiply', inputs=inputs_dict, outputs=[node.name])
@print_mapping_info
def Gather(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
indices = self.graph.get_input_node(node, idx=1, copy=True)
indices_shape = indices.out_shapes[0]
axis = node.get_attr('axis', 0)
#assert len(
# indices_shape) <= 2, "Gather op don't support dim of indice >2 "
if axis == 0 and len(indices_shape) <= 1:
if len(val_x.out_shapes[0]) <= 1:
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[node.name])
elif len(val_x.out_shapes[0]) > 1:
if len(indices_shape) == 0:
gather_ = node.name + '_1'
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[gather_])
self.paddle_graph.add_layer(
'paddle.squeeze',
inputs={'x': gather_},
outputs=[node.name],
axis=[0])
else:
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[node.name])
elif axis > 0 and len(indices_shape) <= 1:
perm = list(range(len(val_x.out_shapes[0])))
perm = [axis] + perm[:axis] + perm[axis + 1:]
name_trans = val_x.name + '_trans'
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": val_x.name},
outputs=[name_trans],
perm=perm)
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': name_trans,
'index': indices.name},
outputs=[node.name])
new_perm = [0] * len(perm)
for i in range(len(perm)):
new_perm[perm[i]] = i
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[node.name],
perm=new_perm)
if len(indices_shape) < 1:
self.paddle_graph.add_layer(
'paddle.squeeze',
inputs={'x': node.name},
outputs=[node.name],
axis=[axis])
elif axis == 0 and len(indices_shape) > 1:
if val_x.out_shapes[0] is not None and isinstance(
val_x, ONNXGraphDataNode):
indices_cast = indices.name + '_cast'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": indices.name},
outputs=[indices_cast],
dtype=string('int64'))
self.paddle_graph.add_layer(
'paddle.nn.functional.embedding',
inputs={"x": indices_cast,
"weight": val_x.name},
outputs=[node.name])
else:
from functools import reduce
reshape_shape = reduce(lambda x, y: x * y, indices_shape)
indices_reshape = indices.name + '_shape'
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices_reshape],
shape=[reshape_shape, ])
perm = list(range(len(val_x.out_shapes[0])))
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices_reshape},
outputs=[node.name])
val_x_shape = val_x.out_shapes[0]
reshaped_shape = []
for i in perm:
reshaped_shape.append(indices_shape[i])
for i in val_x_shape[:axis] + val_x_shape[axis + 1:]:
reshaped_shape.append(i)
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": node.name},
outputs=[node.name],
shape=reshaped_shape)
elif axis > 0 and len(indices_shape) > 1:
from functools import reduce
reshape_shape = reduce(lambda x, y: x * y, indices_shape)
indices_reshape = indices.name + '_shape'
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices_reshape],
shape=[reshape_shape, ])
perm = list(range(len(val_x.out_shapes[0])))
perm = [axis] + perm[:axis] + perm[axis + 1:]
name_trans = val_x.name + '_transpose'
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": val_x.name},
outputs=[name_trans],
perm=perm)
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': name_trans,
'index': indices_reshape},
outputs=[node.name])
input_transpose = node.name + '_transpose'
new_perm = [0] * len(perm)
for i in range(len(perm)):
new_perm[perm[i]] = i
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[input_transpose],
perm=new_perm)
perm = new_perm
val_x_shape = val_x.out_shapes[0]
reshaped_shape = []
for i in perm:
reshaped_shape.append(indices_shape[i])
for i in val_x_shape[:axis] + val_x_shape[axis + 1:]:
reshaped_shape.append(i)
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": input_transpose},
outputs=[node.name],
shape=reshaped_shape)
@print_mapping_info
def ScatterND(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
indices = self.graph.get_input_node(node, idx=1, copy=True)
updates = self.graph.get_input_node(node, idx=2, copy=True)
if len(indices.out_shapes[0]) == 1:
self.paddle_graph.add_layer(
'paddle.scatter',
inputs={
'x': val_x.name,
'index': indices.name,
'updates': updates.name
},
outputs=[node.name])
else:
input_inner_indices = node.name + '_input_inner_indices'
shape = val_x.out_shapes[0]
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices.name],
shape=indices.out_shapes[0])
zeros_like_val_x = val_x.name + '_zeros'
self.paddle_graph.add_layer(
'paddle.zeros_like',
inputs={"x": val_x.name},
outputs=[zeros_like_val_x])
self.paddle_graph.add_layer(
'paddle.scatter_nd_add',
inputs={
'x': zeros_like_val_x,
'index': indices.name,
'updates': updates.name
},
outputs=[input_inner_indices])
indices_mask = node.name + '_indices_mask'
constant_minus_one = node.name + '_constant_minus_one'
# full_like support create tensor shape like input tensor
self.paddle_graph.add_layer(
'paddle.full_like',
inputs={"x": updates.name},
outputs=[constant_minus_one],
dtype=string(updates.dtype),
fill_value=-1)
self.paddle_graph.add_layer(
'paddle.scatter_nd_add',
inputs={
'x': zeros_like_val_x,
'index': indices.name,
'updates': constant_minus_one
},
outputs=[indices_mask])
constant_one = node.name + '_constant_1'
# full_like support create tensor shape like input tensor
self.paddle_graph.add_layer(
'paddle.full_like',
inputs={"x": val_x.name},
outputs=[constant_one],
dtype=string(val_x.dtype),
fill_value=1)
input_out_indices_mask = node.name + '_input_out_indices_mask'
self.paddle_graph.add_layer(
"paddle.add",
inputs={"x": indices_mask,
"y": constant_one},
outputs=[input_out_indices_mask])
input_out_indices = node.name + '_input_out_indices'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={"x": val_x.name,
"y": input_out_indices_mask},
outputs=[input_out_indices])
self.paddle_graph.add_layer(
"paddle.add",
inputs={"x": input_inner_indices,
"y": input_out_indices},
outputs=[node.name])
@print_mapping_info
def Range(self, node):
val_start = self.graph.get_input_node(node, idx=0, copy=True)
val_limit = self.graph.get_input_node(node, idx=1, copy=True)
val_delta = self.graph.get_input_node(node, idx=2, copy=True)
dtype = val_start.dtype
inputs = {
'start': val_start.name,
'end': val_limit.name,
'step': val_delta.name
}
self.paddle_graph.add_layer(
'paddle.arange',
inputs=inputs,
outputs=[node.name],
dtype=string(dtype))
@print_mapping_info
def Slice(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
starts, ends, axes, steps = None, None, None, None
layer_attrs = {}
if len(node.inputs) > 1:
starts = self.graph.get_input_node(node, idx=1, copy=True)
ends = self.graph.get_input_node(node, idx=2, copy=True)
starts_value = _const_weight_or_none(starts)
if starts_value is not None:
starts_value = starts_value.tolist()
ends_value = _const_weight_or_none(ends)
if ends_value is not None:
ends_value = ends_value.tolist()
if len(node.inputs) > 2:
s_len = len(val_x.out_shapes[0])
axes = list(range(s_len))
if len(node.inputs) > 3:
axes_node = self.graph.get_input_node(node, idx=3, copy=True)
axes = _const_weight_or_none(axes_node, necessary=True).tolist()
if len(node.inputs) > 4:
steps = self.graph.get_input_node(node, idx=4, copy=True)
steps = _const_weight_or_none(steps).tolist()
layer_attrs = {
"axes": axes,
"starts": starts.name,
"ends": ends.name
}
if starts_value is not None and ends_value is not None and axes is not None:
starts_value = starts_value.copy()
ends_value = ends_value.copy()
#for idx in range(len(ends_value)):
# if ends_value[idx] > 2**31 - 1:
# ends_value[idx] = 2**31 - 1
#print(val_x.out_shapes)
for idx in range(len(ends_value)):
if starts_value[idx] >= val_x.out_shapes[0][axes[
idx]] and val_x.out_shapes[0][axes[idx]] > 0:
starts_value[idx] = val_x.out_shapes[0][axes[idx]] - 1
ends_value[idx] = val_x.out_shapes[0][axes[idx]]
elif ends_value[idx] > 2**31 - 1:
ends_value[idx] = 2**31 - 1
layer_attrs = {
"axes": axes,
"starts": starts_value,
"ends": ends_value
}
else:
if starts.dtype != 'int32':
starts_cast = starts.name + '_cast'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": starts.name},
outputs=[starts_cast],
dtype=string('int32'))
layer_attrs['starts'] = starts_cast
if ends.dtype != 'int32':
ends_cast = ends.name + '_cast'
else:
ends_cast = ends.name
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": ends.name},
outputs=[ends_cast],
dtype=string('int32'))
layer_attrs['ends'] = ends_cast
else:
starts = node.get_attr('starts')
ends = node.get_attr('ends')
axes = node.get_attr('axes')
for idx in range(len(ends)):
if ends[idx] > 2**31 - 1:
ends[idx] = 2**31 - 1
layer_attrs = {"axes": axes, "starts": starts, "ends": ends}
if steps is not None:
layer_attrs['strides'] = steps
self.paddle_graph.add_layer(
'paddle.strided_slice',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
else:
self.paddle_graph.add_layer(
'paddle.slice',
inputs={"input": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def ConstantOfShape(self, node):
val_shape = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_node(node.layer.output[0], copy=True)
value = node.get_attr('value')
dtype = value.dtype
value = value.tolist()
assert len(value) == 1, ('given value not Scalar, shape of value > 1, '
'this is not supported')
if len(value) == 1:
value = value[0]
layer_attrs = {'dtype': string(dtype), 'fill_value': value}
self.paddle_graph.add_layer(
"paddle.full",
inputs={'shape': val_shape.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Clip(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_node(node.layer.output[0], copy=True)
max_value, min_value = None, None
if len(node.inputs) == 1:
max_value = node.get_attr('max')
min_value = node.get_attr('min')
layer_attrs = {
'max': max_value,
'min': min_value,
}
self.paddle_graph.add_layer(
'paddle.clip',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
else:
min_ipt = self.graph.get_input_node(node, idx=1, copy=True)
max_ipt = self.graph.get_input_node(node, idx=2, copy=True)
min_value = _const_weight_or_none(min_ipt)
max_value = _const_weight_or_none(max_ipt)
if max_value.shape == (1, ):
max_value = max_value[0]
if min_value.shape == (1, ):
min_value = min_value[0]
if max_value is not None and min_value is not None:
layer_attrs = {'max': max_value, 'min': min_value}
self.paddle_graph.add_layer(
'paddle.clip',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
else:
raise
@print_mapping_info
def Split(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
paddle_op = 'split'
split = node.get_attr('split')
axis = node.get_attr('axis', 0)
layer_attrs = {
'num_or_sections': split,
'axis': axis,
}
outputs_list = list()
if isinstance(split, list) or isinstance(split, tuple):
if len(split) == 1:
outputs_list.append(node.name)
else:
for i in range(len(split)):
outputs_list.append("{}_p{}".format(node.layer_name, i))
else:
outputs_list.append(node.name)
self.paddle_graph.add_layer(
'paddle.split',
inputs={"x": val_x.name},
outputs=outputs_list,
**layer_attrs)
@print_mapping_info
def Reshape(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_shape = self.graph.get_input_node(node, idx=1, copy=True)
val_reshaped = self.graph.get_node(node.layer.output[0], copy=True)
shape_value = _const_weight_or_none(val_shape)
shape_dims = len(val_shape.out_shapes[0])
if shape_value is not None:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name},
outputs=[node.name],
shape=shape_value.tolist())
elif len(node.out_shapes[0]) > 0 and _is_static_shape(node.out_shapes[
0]):
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name},
outputs=[node.name],
shape=node.out_shapes[0])
else:
# shape may be [], come form Gather by scalar indices
if len(val_shape.out_shapes[0]) > 0:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_shape.name},
outputs=[val_shape.name],
shape=val_shape.out_shapes[0])
if val_shape.dtype != "int32":
self.paddle_graph.add_layer(
'paddle.cast',
inputs={'x': val_shape.name},
outputs=[val_shape.name],
dtype=string("int32"))
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name,
'shape': val_shape.name},
outputs=[node.name])
@print_mapping_info
def Cast(self, node):
val_input = self.graph.get_input_node(node, idx=0, copy=True)
val_output = self.graph.get_node(node.layer.output[0], copy=True)
dtype = node.get_attr('to')
if not isinstance(dtype, np.dtype):
dtype = TENSOR_TYPE_TO_NP_TYPE[dtype]
output_dtype = val_output.dtype
if output_dtype:
assert dtype == output_dtype, 'dtype of to unmatches output'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={'x': val_input.name},
outputs=[node.name],
dtype=string(dtype))
@print_mapping_info
def Not(self, node):
val_input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
'paddle.logical_not',
inputs={'x': val_input.name},
outputs=[node.name])
@print_mapping_info
def AveragePool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
kernel_shape = node.get_attr("kernel_shape")
poolnd = len(kernel_shape)
strides = node.get_attr("strides")
pad_mode = node.get_attr("pads")
ceil_mode = bool(node.get_attr('ceil_mode', 0))
pads = node.get_attr('pads', [0] * (poolnd * 2))
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
input_shape = val_x.out_shapes[0]
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
paddle_op = 'paddle.nn.functional.avg_pool{}d'.format(poolnd)
assert 1 <= poolnd <= 3, 'only avg_pool1d, avg_pool2d and avg_pool3d are supported'
layer_attrs = {
"kernel_size": kernel_shape,
"stride": strides,
"padding": paddings,
"ceil_mode": ceil_mode,
"exclusive": True,
"name": string(node.name)
}
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x if isinstance(val_x, str) else val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Concat(self, node):
inputs_list = []
dtypes = set()
for i in range(len(node.layer.input)):
ipt = self.graph.get_input_node(node, idx=i, copy=True)
inputs_list.append(ipt.name)
dtypes.add(ipt.dtype)
if len(dtypes) > 1:
assert 'Unspported situation happened, please create issue on https://github.com/PaddlePaddle/X2Paddle/issues.'
axis = node.get_attr('axis')
self.paddle_graph.add_layer(
'paddle.concat',
inputs={"x": inputs_list},
outputs=[node.name],
axis=axis)
@print_mapping_info
def Flatten(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
output_shape = node.out_shapes[0]
axis = node.get_attr('axis', 1)
shape_list = [1, 1]
if axis == 0:
for s in output_shape:
shape_list[1] *= s
else:
for s in output_shape[:axis]:
shape_list[0] *= s
for s in output_shape[axis:]:
shape_list[1] *= s
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=shape_list)
@print_mapping_info
def Gemm(self, node):
val_a = self.graph.get_input_node(node, idx=0, copy=True)
val_b = self.graph.get_input_node(node, idx=1, copy=True)
val_c = self.graph.get_input_node(node, idx=2, copy=True)
alpha = node.get_attr('alpha', 1.) # optional
beta = node.get_attr('beta', 1.) # optional
trans_a = bool(node.get_attr('transA', 0)) # optional
trans_b = bool(node.get_attr('transB', 0)) # optional
val_mm = node.name + '_mm'
matmul_inputs = {"x": val_a.name, "y": val_b.name}
attr_matmul = {
"transpose_x": trans_a,
"transpose_y": trans_b,
}
self.paddle_graph.add_layer(
'paddle.matmul',
inputs=matmul_inputs,
outputs=[val_mm],
**attr_matmul)
self.paddle_graph.add_layer(
"paddle.scale", inputs={"x": val_mm}, outputs=[val_mm], scale=alpha)
if beta != 0:
if beta == 1.:
add_inputs = {"x": val_mm, "y": val_c.name}
self.paddle_graph.add_layer(
"paddle.add", inputs=add_inputs, outputs=[node.name])
else:
var_beta = node.name + '_beta'
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": val_c.name},
outputs=[var_beta],
scale=beta)
add_inputs = {"x": val_mm, "y": var_beta}
self.paddle_graph.add_layer(
"paddle.add", inputs=add_inputs, outputs=[node.name])
@print_mapping_info
def Sum(self, node):
val_inps = node.layer.input
inputs_dict = {
"x": self.graph.get_input_node(
node, idx=0, copy=True).name,
"y": self.graph.get_input_node(
node, idx=1, copy=True).name,
}
self.paddle_graph.add_layer(
"paddle.add", inputs=inputs_dict, outputs=[node.name])
for idx, ipt in enumerate(val_inps[2:]):
y = self.graph.get_input_node(node, idx=idx, copy=True)
inputs_dict = {
"x": node.name,
"y": y.name,
}
self.paddle_graph.add_layer(
"paddle.add", inputs=inputs_dict, outputs=[node.name])
@print_mapping_info
def MatMul(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
x_shape = val_x.out_shapes[0]
y_shape = val_y.out_shapes[0]
inputs_dict = {"x": val_x.name, "y": val_y.name}
if y_shape[0] == 1 and x_shape[-1] != 1 and x_shape[0] != 1:
y_squeeze = val_y.name + '_squeeze'
self.paddle_graph.add_layer(
"paddle.squeeze",
inputs={"x": val_y.name},
outputs=[y_squeeze],
axis=[0])
inputs_dict['y'] = y_squeeze
self.paddle_graph.add_layer(
"paddle.matmul", inputs=inputs_dict, outputs=[node.name])
else:
self.paddle_graph.add_layer(
"paddle.matmul", inputs=inputs_dict, outputs=[node.name])
@print_mapping_info
def BatchNormalization(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_scale = self.graph.get_input_node(node, idx=1, copy=True)
val_b = self.graph.get_input_node(node, idx=2, copy=True)
val_mean = self.graph.get_input_node(node, idx=3, copy=True)
val_var = self.graph.get_input_node(node, idx=4, copy=True)
momentum = node.get_attr('momentum', .9)
epsilon = node.get_attr('epsilon', 1e-5)
# Attribute: spatial is used in BatchNormalization-1,6,7
spatial = bool(node.get_attr('spatial'))
layer_attrs = {
"momentum": momentum,
"epsilon": epsilon,
}
self.paddle_graph.add_layer(
"paddle.nn.functional.batch_norm",
inputs={
"x": val_x.name,
"weight": val_scale.name,
"bias": val_b.name,
"running_mean": val_mean.name,
"running_var": val_var.name
},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Transpose(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
s_len = len(val_x.out_shapes[0])
perm_default = list(range(s_len))
perm_default.reverse()
perm = node.get_attr('perm', perm_default)
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": val_x.name},
outputs=[node.name],
perm=perm)
@print_mapping_info
def PRelu(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_slope = self.graph.get_input_node(node, idx=1, copy=True)
mode = 'channel'
shape_slope = val_slope.out_shapes[0]
if shape_slope == [1]:
mode = 'all'
if mode == "element":
self.paddle_graph.add_layer(
"paddle.static.nn.prelu",
inputs={"x": val_x.name,
"param_attr": val_slope.name},
outputs=[node.name],
mode="element")
else:
if mode == 'channel':
if len(shape_slope) > 1:
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": val_slope.name},
outputs=[val_slope.name],
shape=[shape_slope[0]])
self.paddle_graph.add_layer(
"paddle.nn.functional.prelu",
inputs={"x": val_x.name,
"weight": val_slope.name},
outputs=[node.name])
@print_mapping_info
def Squeeze(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
axes = node.get_attr('axes')
if len(val_x.out_shapes[0]) == 1:
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": val_x.name},
outputs=[node.name],
dtype=string(val_x.dtype))
else:
self.paddle_graph.add_layer(
"paddle.squeeze",
inputs={"x": val_x.name},
outputs=[node.name],
axis=axes)
@print_mapping_info
def Equal(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
self.paddle_graph.add_layer(
"paddle.equal",
inputs={'x': val_x.name,
'y': val_y.name},
outputs=[node.name])
@print_mapping_info
def Greater(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
self.paddle_graph.add_layer(
"paddle.greater_than",
inputs={'x': val_x.name,
'y': val_y.name},
outputs=[node.name])
@print_mapping_info
def Where(self, node):
condition = self.graph.get_input_node(node, idx=0, copy=True)
val_x = self.graph.get_input_node(node, idx=1, copy=True)
val_y = self.graph.get_input_node(node, idx=2, copy=True)
not_condition = condition.name + '_not'
self.paddle_graph.add_layer(
"paddle.logical_not",
inputs={"x": condition.name},
outputs=[not_condition])
cast_not_condition = not_condition + '_cast'
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": not_condition},
outputs=[cast_not_condition],
dtype=string(val_x.dtype))
cast_condition = condition.name + '_cast'
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": condition.name},
outputs=[cast_condition],
dtype=string(val_x.dtype))
mul_val_x = val_x.name + '_mul'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={'x': val_x.name,
'y': cast_condition},
outputs=[mul_val_x])
mul_val_y = val_y.name + '_mul'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={'x': val_y.name,
'y': cast_not_condition},
outputs=[mul_val_y])
self.paddle_graph.add_layer(
"paddle.add",
inputs={'x': mul_val_x,
'y': mul_val_y},
outputs=[node.name])
@print_mapping_info
def NonZero(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_x_dim = len(val_x.out_shapes[0])
if val_x_dim == 1:
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": val_x.name},
outputs=[val_x.name])
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": val_x.name},
outputs=[node.layer_name],
perm=[1, 0])
if val_x_dim > 1:
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": val_x.name},
outputs=[val_x.name])
self.paddle_graph.add_layer(
"paddle.split",
inputs={"x": val_x.name},
outputs=[val_x.name],
num_or_sections=1,
axis=val_x_dim)
self.paddle_graph.add_layer(
"paddle.concat", inputs={"x": val_x.name}, outputs=[node.name])
@print_mapping_info
def Identity(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.assign", inputs={"x": val_x.name}, outputs=[node.name])
@print_mapping_info
def Tile(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_repeats = self.graph.get_input_node(node, idx=1, copy=True)
repeats = _const_weight_or_none(val_repeats)
if repeats is None:
repeats = val_repeats.name
if val_repeats.dtype != 'int32':
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": repeats},
outputs=["{}_tmp".format(repeats)],
dtype=string("int32"))
repeats = "{}_tmp".format(repeats)
elif isinstance(repeats, int):
repeats = [repeats]
elif type(repeats) is np.ndarray:
repeats = repeats.tolist()
attr = {
'expand_times': repeats,
"name": string(node.name),
}
self.paddle_graph.add_layer(
"paddle.tile",
inputs={"x": val_x.name},
outputs=[node.name],
repeat_times=repeats)
@print_mapping_info
def MaxPool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
assert node.get_attr(
"dilations") is None, 'only dilations = 0 is supported' # optional
kernel_shape = node.get_attr("kernel_shape")
poolnd = len(kernel_shape)
strides = node.get_attr("strides")
pad_mode = node.get_attr("pads")
ceil_mode = bool(node.get_attr('ceil_mode', 0)) # optional
pads = node.get_attr('pads', [0] * (poolnd * 2)) # optional
paddle_op = 'paddle.nn.functional.max_pool{}d'.format(poolnd)
assert 1 <= poolnd <= 3, 'only max_pool1d, max_pool2d and max_pool3d are supported'
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
input_shape = val_x.out_shapes[0]
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
layer_attrs = {
"kernel_size": kernel_shape,
"stride": strides,
"padding": paddings,
"ceil_mode": ceil_mode,
}
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x if isinstance(val_x, str) else val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def GlobalMaxPool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = val_x.out_shapes[0]
if len(input_shape) == 4:
poolnd = 2
elif len(input_shape) == 5:
poolnd = 3
elif len(input_shape) == 3:
poolnd = 1
paddle_op = 'paddle.nn.functional.adaptive_max_pool{}d'.format(poolnd)
assert 1 <= poolnd <= 3, 'only adaptive_max_pool1d, adaptive_max_pool2d and adaptive_max_pool3d are supported'
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=[node.name],
output_size=output_shape[2:])
@print_mapping_info
def GlobalAveragePool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = val_x.out_shapes[0]
if len(input_shape) == 4:
poolnd = 2
elif len(input_shape) == 5:
poolnd = 3
elif len(input_shape) == 3:
poolnd = 1
paddle_op = 'paddle.nn.functional.adaptive_avg_pool{}d'.format(poolnd)
assert 1 <= poolnd <= 3, 'only Pool1D, Pool2D and Pool3D are supported'
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=[node.name],
output_size=output_shape[2:])
@print_mapping_info
def Conv(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_w = self.graph.get_input_node(node, idx=1, copy=True)
has_bias = len(node.layer.input) == 3
if has_bias:
val_b = self.graph.get_input_node(node, idx=2, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
kernel_shape = node.get_attr('kernel_shape')
convnd = len(kernel_shape)
assert 2 <= convnd <= 3, 'only conv2d and conv3d is supported'
num_out_channels = val_w.out_shapes[0][0]
num_in_channels = val_w.out_shapes[0][1]
paddle_op = 'paddle.nn.functional.conv{}d'.format(convnd)
num_groups = node.get_attr('group', 1)
strides = node.get_attr('strides', [1] * convnd)
dilations = node.get_attr('dilations', [1] * convnd)
pads = node.get_attr('pads', [0] * (convnd * 2))
input_shape = val_x.out_shapes[0]
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
layer_attrs = {
"stride": strides,
"padding": paddings,
"dilation": dilations,
"groups": num_groups,
}
layer_inputs = {
"x": val_x if isinstance(val_x, str) else val_x.name,
"weight": val_w.name
}
if has_bias:
layer_inputs["bias"] = val_b.name
if reduce(lambda x, y: x * y,
input_shape) in [1, -1] and 1 not in input_shape:
input_shape[1] = num_in_channels * num_groups
input_shape[0] = 0
input_shape[2] = 0
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": layer_inputs["x"]},
outputs=[layer_inputs["x"]],
shape=input_shape)
self.paddle_graph.add_layer(
paddle_op, inputs=layer_inputs, outputs=[node.name], **layer_attrs)
@print_mapping_info
def ConvTranspose(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_w = self.graph.get_input_node(node, idx=1, copy=True)
val_b = None
if len(node.layer.input) > 2:
val_b = self.graph.get_input_node(node, idx=2, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
out_padding = node.get_attr('output_padding', [0, 0])
kernel_shape = node.get_attr('kernel_shape')
assert kernel_shape, 'kernel_shape not inferred'
convnd = len(kernel_shape)
assert 2 <= convnd <= 3, 'only conv2d_transpose and conv3d_transpose supported'
num_in_channels = val_w.out_shapes[0][0]
num_out_channels = val_w.out_shapes[0][1]
paddle_op = 'paddle.nn.functional.conv{}d_transpose'.format(convnd)
num_groups = node.get_attr('group', 1)
strides = node.get_attr('strides', [1] * convnd)
dilations = node.get_attr('dilations', [1] * convnd)
output_size = node.get_attr('output_shape', [])
pads = node.get_attr('pads', [0] * (convnd * 2))
paddings, var_x = self._pad_if_asymmetric(node, pads, val_x)
output_size = [0, 0]
output_size[0] = (val_x.out_shapes[0][2] - 1
) * strides[0] - 2 * paddings[0] + dilations[0] * (
kernel_shape[0] - 1) + 1 + out_padding[0]
output_size[1] = (val_x.out_shapes[0][3] - 1
) * strides[1] - 2 * paddings[1] + dilations[1] * (
kernel_shape[1] - 1) + 1 + out_padding[1]
layer_inputs = {'x': val_x.name, "weight": val_w.name}
layer_attrs = {
"stride": strides,
"dilation": dilations,
"padding": paddings,
"groups": num_groups,
"output_size": node.out_shapes[0][2:]
}
if val_b is not None:
layer_inputs["bias"] = val_b.name
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs=layer_inputs,
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def ArgMax(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
axis = node.get_attr('axis')
keepdims = False if node.get_attr('keepdims') == 0 else True
layer_attrs = {'axis': axis, 'keepdim': keepdims}
self.paddle_graph.add_layer(
'paddle.argmax',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Size(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.shape", inputs={"input": val_x.name}, outputs=[node.name])
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": node.name},
outputs=[node.name],
dtype=string('int64'))
self.paddle_graph.add_layer(
"paddle.prod", inputs={"x": node.name}, outputs=[node.name])
@print_mapping_info
def Sign(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
if node.dtype not in ["float16", "float32", "float64"]:
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": val_x.name},
outputs=[val_x.name],
dtype=string("float32"))
self.paddle_graph.add_layer(
"paddle.sign", inputs={"x": val_x.name}, outputs=[node.name])
if node.dtype not in ["float16", "float32", "float64"]:
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": node.name},
outputs=[node.name],
dtype=string(node.dtype))
@print_mapping_info
def OneHot(self, node):
indices = self.graph.get_input_node(node, idx=0, copy=True)
depth = self.graph.get_input_node(node, idx=1, copy=True)
values = self.graph.get_input_node(node, idx=2, copy=True)
axis = node.get_attr('axis', -1)
self.paddle_graph.add_layer(
"custom_layer:one_hot",
inputs={
"indices": indices.name,
"depth": depth.name,
"values": values.name
},
outputs=[node.name],
axis=axis)
@print_mapping_info
def Reciprocal(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.reciprocal", inputs={"x": val_x.name}, outputs=[node.name])
@print_mapping_info
def TopK(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_k = self.graph.get_input_node(node, idx=1, copy=True)
layer_attrs = dict()
layer_attrs["axis"] = node.get_attr('axis', -1)
layer_attrs["largest"] = True if node.get_attr('largest',
1) == 1 else False
layer_attrs["sorted"] = True if node.get_attr('sorted',
1) == 1 else False
self.paddle_graph.add_layer(
"paddle.topk",
inputs={"x": val_x.name,
"k": val_k.name},
outputs=[
"{}_p{}".format(node.layer_name, 0),
"{}_p{}".format(node.layer_name, 1)
],
**layer_attrs)
@print_mapping_info
def LRN(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_x = self.graph.get_input_node(node, idx=0, copy=True)
alpha = node.get_attr('alpha', 0.0001)
beta = node.get_attr('beta', 0.75)
bias = node.get_attr('bias', 1.0)
size = node.get_attr('size')
layer_attrs = {'size': size, 'alpha': alpha, 'beta': beta, 'k': bias}
self.paddle_graph.add_layer(
"custom_layer:local_response_norm",
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def DepthToSpace(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
blocksize = node.get_attr('blocksize')
mode = node.get_attr('mode', "DCR")
val_x_shape = val_x.out_shapes[0]
b, c, h, w = val_x_shape
if mode == "DCR":
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=[b, blocksize, blocksize, c // (blocksize**2), h, w])
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 3, 4, 1, 5, 2])
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": node.name},
outputs=[node.name],
shape=[b, c // (blocksize**2), h * blocksize, w * blocksize])
else:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=[b, c // (blocksize**2), blocksize, blocksize, h, w])
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 1, 4, 2, 5, 3])
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": node.name},
outputs=[node.name],
shape=[b, c // (blocksize**2), h * blocksize, w * blocksize])
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.decoder.tf_decoder import TFGraph, TFGraphNode
from x2paddle.core.program import PaddleGraph
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle import program
import traceback
import math
import inspect
import numpy
import sys
name_counter = dict()
def gen_name(op_name, var_name):
name = "{}_{}".format(op_name, var_name)
if name not in name_counter:
name_counter[name] = 0
else:
name_counter[name] += 1
name = name + '_' + str(name_counter[name])
return name
# compute padding size for SAME mode
def get_same_padding(in_size, kernel_size, stride):
new_size = int(math.ceil(in_size * 1.0 / stride))
pad_size = (new_size - 1) * stride + kernel_size - in_size
if pad_size < 0:
pad_size = 0
pad0 = int(pad_size / 2)
pad1 = pad_size - pad0
return [pad0, pad1]
class TFOpMapper(OpMapper):
directly_map_ops = {
'Relu': ['paddle.nn.functional.relu'],
'Relu6': ['paddle.nn.functional.relu6'],
'Abs': ['paddle.abs'],
'Sigmoid': ['paddle.nn.functional.sigmoid'],
'Softmax': ['paddle.nn.functional.softmax'],
'Exp': ['paddle.exp'],
'Rsqrt': ['paddle.rsqrt'],
'Sqrt': ['paddle.sqrt'],
'swish_f32': ['paddle.nn.functional.swish'],
'Tanh': ['paddle.tanh'],
'Softplus': ['paddle.nn.functional.softplus'],
'LeakyRelu':
['paddle.nn.functional.leaky_relu', dict(alpha='negative_slope')],
'Floor': ['paddle.floor'],
'Erf': ['paddle.erf'],
'Square': ['paddle.square']
}
elementwise_ops = {
'Add': 'paddle.add',
'AddV2': 'paddle.add',
'RealDiv': 'paddle.divide',
'DivNoNan': 'paddle.divide',
# TODO (syf): replace
'Sub': 'paddle.subtract',
'Maximum': 'paddle.maximum',
'Minimum': 'paddle.minimum',
'Mul': 'paddle.multiply',
'FloorDiv': 'paddle.floor_divide',
'FloorMod': 'paddle.floor_mod',
'LogicalAnd': 'logical_and',
}
bool_ops = {
'LessEqual': 'paddle.less_equal',
'GreaterEqual': 'paddle.greater_equal',
'Greater': 'paddle.greater_than',
'NotEqual': 'paddle.not_equal',
'Equal': 'paddle.equal',
}
def __init__(self, decoder):
super(TFOpMapper, self).__init__()
self.decoder = decoder
self.graph = decoder.tf_graph
if not self.op_checker():
raise Exception("Model is not supported yet.")
self.params = dict()
self.paddle_graph = PaddleGraph(
parent_layer=None, graph_type="static", source_type="tf")
self.params_output2id = dict()
not_placeholder = list()
for name in self.graph.input_nodes:
if self.graph.get_node(
name).layer_type != "Placeholder" and self.graph.get_node(
name
).layer_type != "OneShotIterator" and self.graph.get_node(
name).layer_type != "IteratorV2":
not_placeholder.append(name)
for name in not_placeholder:
idx = self.graph.input_nodes.index(name)
del self.graph.input_nodes[idx]
self.paddle_graph.inputs = self.graph.input_nodes
self.paddle_graph.outputs = self.graph.output_nodes
print("Total nodes: {}".format(
sum([
isinstance(node, TFGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if op in self.directly_map_ops:
self.directly_map(node)
elif op in self.elementwise_ops:
self.elementwise_map(node)
elif op in self.bool_ops:
self.bool_map(node)
elif hasattr(self, op):
func = getattr(self, op)
func(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.params)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op) and \
op not in self.directly_map_ops and \
op not in self.elementwise_ops and \
op not in self.bool_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".
format(len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def directly_map(self, node):
assert node.layer_type in self.directly_map_ops
op_info = self.directly_map_ops[node.layer_type]
input = self.graph.get_node(node.layer.input[0])
attr = dict()
for param in op_info[1:]:
tf_param_name = list(param.keys())[0]
pd_param_name = list(param.values())[0]
tf_param = node.get_attr(tf_param_name)
attr[pd_param_name] = tf_param
self.paddle_graph.add_layer(
kernel=op_info[0],
inputs={"x": input.name},
outputs=[node.name],
**attr)
def elementwise_map(self, node, op_type=None):
if op_type is None:
assert node.layer_type in self.elementwise_ops
op_type = self.elementwise_ops[node.layer_type]
x = self.graph.get_node(node.layer.input[0])
y = self.graph.get_node(node.layer.input[1])
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
layer_id = self.paddle_graph.add_layer(
kernel=op_type,
inputs={"x": x.name,
"y": y.name},
outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {
"x": x_shape,
"y": y_shape
}
def bool_map(self, node):
op_type = self.bool_ops[node.layer_type]
self.elementwise_map(node, op_type)
node.set_dtype("bool")
def Placeholder(self, node):
shape = node.out_shapes[0]
assert len(shape) != 0, "Unknown shape of input nodes[{}].".format(
node.layer_name)
dtype = node.dtype
self.paddle_graph.add_layer(
kernel="paddle.static.data",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=shape,
name=string(node.name))
def Const(self, node):
shape = node.out_shapes[0]
dtype = node.dtype
value = node.value
if len(shape) == 0:
assert value.size == 1, "Unexpected situation happend"
shape = [1]
if value == float('inf'):
value = "float('inf')"
self.paddle_graph.add_layer(
kernel="paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=value)
return
self.params[node.name] = node.value
layer_id = self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=shape,
name=string(node.name),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
self.params_output2id[node.name] = layer_id
def Transpose(self, node):
input = self.graph.get_node(node.layer.input[0])
perm = self.graph.get_node(node.layer.input[1])
if perm.layer_type == "Const":
perm = perm.value.tolist()
else:
perm = self.decoder.infer_tensor(
perm, use_diff_inputs=False).tolist()
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[node.name],
perm=perm)
def Fill(self, node):
dims = self.graph.get_node(node.layer.input[0])
input_value = self.graph.get_node(node.layer.input[1])
inputs = dict()
attr = dict()
assert input_value.layer_type == "Const", "Value of fill OP should be Const"
if dims.layer_type == "Const":
attr["shape"] = dims.value.tolist()
else:
inputs["shape"] = dims.name
attr["dtype"] = string(input_value.dtype)
attr["fill_value"] = input_value.value
self.paddle_graph.add_layer(
"paddle.full", inputs=inputs, outputs=[node.name], **attr)
if dims.layer_type != "Const":
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def DepthToSpace(self, node):
input = self.graph.get_node(node.layer.input[0])
block_size = node.get_attr("block_size")
data_format = node.get_attr("data_format").decode()
if data_format == "NHWC":
n, h, w, c = input.out_shapes[0]
else:
n, c, h, w = input.out_shapes[0]
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("depth_to_space", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
shape = [0, block_size * block_size, -1, h, w]
reshape_name = gen_name("depth_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[reshape_name],
shape=shape)
transpose_name = gen_name("depth_to_space", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": reshape_name},
outputs=[transpose_name],
perm=[0, 2, 1, 3, 4])
reshape_name = gen_name("depth_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": transpose_name},
outputs=[reshape_name],
shape=[0, c, h, w])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pixel_shuffle",
inputs={"x": reshape_name},
outputs=[node.name],
upscale_factor=block_size)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Where(self, node):
if len(node.layer.input) == 1:
cond = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.nonzero", inputs={"x": cond.name}, outputs=[node.name])
else:
cond = self.graph.get_input_node(node, 0)
x = self.graph.get_input_node(node, 1)
y = self.graph.get_input_node(node, 2)
self.paddle_graph.add_layer(
"paddle.where",
inputs={"condition": cond.name,
"x": x.name,
"y": y.name},
outputs=[node.name])
def Neg(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input.name},
outputs=[node.name],
scale=-1)
def MaxPool(self, node):
input = self.graph.get_node(node.layer.input[0])
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("max_pool", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
strides = [strides[i] for i in [0, 3, 1, 2]]
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.max_pool2d",
inputs={"x": input_name},
outputs=[node.name],
kernel_size=k_size[2:4],
stride=strides[2:4],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Conv2D(self, node):
input = self.graph.get_node(node.layer.input[0])
kernel = self.graph.get_node(node.layer.input[1])
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if data_format == "NHWC":
n, h, w, c = input.out_shapes[0]
else:
n, c, h, w = input.out_shapes[0]
if kernel.layer_type == 'Const':
kernel_value = kernel.value
kernel_weight_name = kernel.name.replace('/', '_')
else:
kernel_value = self.decoder.infer_tensor(
kernel, use_diff_inputs=False)
if kernel.layer_type == 'Split':
kernel_weight_name = "{}_{}_kernel".format(node.name,
kernel.name)
else:
kernel_weight_name = kernel.name.replace('/', '_')
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(3, 2, 0, 1))
self.paddle_graph.add_layer(
kernel="paddle.static.nn.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
input_name = input.name
if data_format == "NHWC":
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2d", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
if c == -1:
attr = {"shape": [0, k_size[2], 0, 0]}
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs={"x": input_name,
"weight": kernel_weight_name},
outputs=[node.name],
bias=None,
stride=strides[2:4],
dilation=dilations[2:4],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Conv3D(self, node):
input = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if data_format == "NDHWC":
n, d, h, w, c = input.out_shapes[0]
else:
n, c, d, h, w = input.out_shapes[0]
if kernel.layer_type == 'Const':
kernel_value = kernel.value
kernel_weight_name = kernel.name.replace('/', '_')
else:
kernel_value = self.decoder.infer_tensor(
kernel, use_diff_inputs=False)
if kernel.layer_type == 'Split':
kernel_weight_name = "{}_{}_kernel".format(node.name,
kernel.name)
else:
kernel_weight_name = kernel.name.replace('/', '_')
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(4, 3, 0, 1, 2))
self.paddle_graph.add_layer(
kernel="paddle.static.nn.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
input_name = input.name
if data_format == "NDHWC":
strides = [strides[i] for i in [0, 4, 1, 2, 3]]
dilations = [dilations[i] for i in [0, 4, 1, 2, 3]]
transpose_name = gen_name("conv3d", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 4, 1, 2, 3])
input_name = transpose_name
if c == -1:
attr = {"shape": [0, k_size[2], 0, 0, 0]}
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0, 0])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv3d",
inputs={"x": input_name,
"weight": kernel_weight_name},
outputs=[node.name],
bias=None,
stride=strides[2:5],
dilation=dilations[2:5],
padding=string(pad_mode))
if data_format == "NDHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 4, 1])
def BiasAdd(self, node):
input = self.graph.get_node(node.layer.input[0])
bias = self.graph.get_node(node.layer.input[1])
self.paddle_graph.add_layer(
kernel="paddle.add",
inputs={"x": input.name,
"y": bias.name},
outputs=[node.name])
def FusedBatchNorm(self, node):
input = self.graph.get_node(node.layer.input[0])
gamma = self.graph.get_node(node.layer.input[1])
beta = self.graph.get_node(node.layer.input[2])
moving_mean = self.graph.get_node(node.layer.input[3])
moving_var = self.graph.get_node(node.layer.input[4])
data_format = node.get_attr("data_format").decode()
assert gamma.layer_type == "Const"
assert beta.layer_type == "Const"
assert moving_mean.layer_type == "Const"
assert moving_var.layer_type == "Const"
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("batch_norm", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.batch_norm",
inputs={
"x": input_name,
"running_mean": moving_mean.name,
"running_var": moving_var.name,
"weight": gamma.name,
"bias": beta.name
},
outputs=[node.name],
epsilon=node.get_attr("epsilon"))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def FusedBatchNormV3(self, node):
self.FusedBatchNorm(node)
def Mean(self, node):
input = self.graph.get_node(node.layer.input[0])
reduce_idx = self.graph.get_node(node.layer.input[1])
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
dims = reduce_idx.value.tolist()
keep_dims = node.get_attr("keep_dims")
self.paddle_graph.add_layer(
kernel="paddle.mean",
inputs={"x": input.name},
outputs=[node.name],
axis=dims,
keepdim=keep_dims)
def Reshape(self, node):
input = self.graph.get_input_node(node, 0)
param = self.graph.get_input_node(node, 1)
input_name = input.name
if param.layer_type == "Const":
shape = param.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[node.name],
shape=shape)
else:
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name,
"shape": param.name},
outputs=[node.name])
if param.layer_type != "Const":
out_shape = numpy.array(node.out_shapes[0])
if (out_shape > 0).any():
out_shape[out_shape < 0] = 0
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape.tolist())
def Pad(self, node):
input = self.graph.get_input_node(node, 0)
paddings = self.graph.get_input_node(node, 1)
assert paddings.layer_type == "Const", "Padding should be Const"
paddings = paddings.value.flatten().tolist()
constant_values = 0
if len(node.layer.input) > 2:
constant_values = self.graph.get_input_node(node, 2)
assert constant_values.layer_type == "Const", "Padding should be Const"
constant_values = constant_values.value
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pad",
inputs={"x": input.name},
outputs=[node.name],
pad=paddings,
value=constant_values)
def MirrorPad(self, node):
self.Pad(node)
def PadV2(self, node):
self.Pad(node)
def Squeeze(self, node):
input = self.graph.get_input_node(node, 0)
squeeze_dims = node.get_attr('squeeze_dims')
self.paddle_graph.add_layer(
kernel="paddle.squeeze",
inputs={"x": input.name},
outputs=[node.name],
axis=squeeze_dims)
def Shape(self, node):
input = self.graph.get_input_node(node, 0)
input_name = input.name
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
def Size(self, node):
input = self.graph.get_input_node(node, 0)
input_name = input.name
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
self.paddle_graph.add_layer(
kernel="paddle.prod", inputs={"x": node.name}, outputs=[node.name])
def Ceil(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
kernel="paddle.ceil", inputs={"x": input.name},
outputs=[node.name])
def ArgMax(self, node):
input = self.graph.get_input_node(node, 0)
axis = self.graph.get_input_node(node, 1)
assert axis.layer_type == "Const", "ArgMax only support Const parameter"
axis = axis.value
self.paddle_graph.add_layer(
kernel="paddle.argmax",
inputs={"x": input.name},
outputs=[node.name],
axis=axis)
def TopKV2(self, node):
input = self.graph.get_input_node(node, 0)
k = self.graph.get_input_node(node, 1)
assert k.layer_type == "Const", "ArgMax only support Const parameter"
k = k.value
sort = node.get_attr('sorted')
self.paddle_graph.add_layer(
kernel="paddle.topk",
inputs={"x": input.name},
outputs=[node.name],
k=k,
sorted=sort)
def MatMul(self, node):
x = self.graph.get_input_node(node, 0)
y = self.graph.get_input_node(node, 1)
transpose_a = node.get_attr('transpose_a')
transpose_b = node.get_attr('transpose_b')
if transpose_a is None:
transpose_a = node.get_attr('adj_x')
if transpose_b is None:
transpose_b = node.get_attr('adj_y')
self.paddle_graph.add_layer(
kernel="paddle.matmul",
inputs={"x": x.name,
"y": y.name},
outputs=[node.name],
transpose_x=transpose_a,
transpose_y=transpose_b)
def BatchMatMul(self, node):
return self.MatMul(node)
def BatchMatMulV2(self, node):
return self.MatMul(node)
def DepthwiseConv2dNative(self, node):
input = self.graph.get_node(node.layer.input[0])
kernel = self.graph.get_node(node.layer.input[1])
assert kernel.layer_type == "Const", "Kernel of DepthwiseConv2DNative should be Const"
in_shape = input.out_shapes[0]
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if len(kernel.outputs) == 1:
self.params[kernel.name] = numpy.transpose(self.params[kernel.name],
(2, 3, 0, 1))
layer = self.paddle_graph.layers[self.params_output2id[kernel.name]]
layer.attrs["shape"] = self.params[kernel.name].shape
else:
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": kernel.name},
outputs=[kernel.name],
perm=[2, 3, 0, 1])
input_name = input.name
if data_format == "NHWC":
in_shape = [in_shape[i] for i in [0, 3, 1, 2]]
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name('depthwise_conv2d', 'transpose')
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs={"x": input_name,
"weight": kernel.name},
outputs=[node.name],
stride=strides[2:4],
dilation=dilations[2:4],
groups=k_size[3] * in_shape[1],
padding=string(pad_mode),
bias=None)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def AvgPool(self, node):
input = self.graph.get_input_node(node, 0)
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("avg_pool", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
strides = [strides[i] for i in [0, 3, 1, 2]]
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
# TODO(syf): The op has diff.
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.avg_pool2d",
inputs={"x": input_name},
outputs=[node.name],
kernel_size=k_size[2:4],
stride=strides[2:4],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Pack(self, node):
inputs_list = list()
for i in range(len(node.inputs)):
inputs_list.append(self.graph.get_input_node(node, i))
input_names = [i.name for i in inputs_list]
axis = node.get_attr("axis")
self.paddle_graph.add_layer(
kernel="paddle.stack",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
if len(node.out_shapes[0]) == 1:
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=[-1])
def Unpack(self, node):
input = self.graph.get_input_node(node, 0)
axis = node.get_attr("axis")
num = node.get_attr("num")
shape = input.out_shapes[0]
input_name = input.name
if len(shape) == 1:
if shape[0] > 0 and num == shape[0]:
self.paddle_graph.add_layer(
kernel="paddle.unsqueeze",
inputs={"x": input.name},
outputs=[node.name],
axis=[0])
input_name = node.name
axis = 1
else:
raise Exception("Unexpected situation happend in Unpack OP")
layer_outputs = [
"{}_p{}".format(node.layer_name, i) for i in range(num)
]
if len(layer_outputs) == 1:
layer_outputs[0] = "[{}]".format(node.layer_name)
self.paddle_graph.add_layer(
kernel="paddle.unstack",
inputs={"x": input_name},
outputs=layer_outputs,
axis=axis,
num=num)
def ConcatV2(self, node):
inputs_list = list()
for i in range(len(node.inputs) - 1):
inputs_list.append(self.graph.get_input_node(node, i))
axis = self.graph.get_input_node(node, -1)
assert axis.layer_type == "Const", "axis for ConcatV2 must be type Const"
axis = axis.value
if axis < 0:
axis += len(inputs_list[0].out_shapes[0])
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
def Concat(self, node):
inputs_list = list()
for i in range(1, len(node.inputs)):
inputs_list.append(self.graph.get_input_node(node, i))
axis = self.graph.get_input_node(node, 0)
assert axis.layer_type == "Const", "axis for ConcatV2 must be type Const"
axis = axis.value
if axis < 0:
axis += len(inputs_list[0].out_shapes[0])
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
def AddN(self, node):
inputs_list = list()
for i in range(len(node.inputs) - 1):
inputs_list.append(self.graph.get_input_node(node, i))
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.add_n",
inputs={"inputs": input_names},
outputs=[node.name])
def StridedSlice(self, node):
input = self.graph.get_input_node(node, 0)
begin = self.graph.get_input_node(node, 1)
end = self.graph.get_input_node(node, 2)
strides = self.graph.get_input_node(node, 3)
if strides.layer_type == "Const":
strides = strides.value.tolist()
else:
strides = self.decoder.infer_tensor(strides)
if begin.layer_type == "Const":
begin = begin.value.tolist()
else:
begin = self.decoder.infer_tensor(begin)
if end.layer_type == "Const":
end = end.value.tolist()
else:
end = self.decoder.infer_tensor(end)
assert len(set(strides)) == 1 and strides[
0] == 1, "Only support strides be 1 in StridedSlice OP"
if len(begin) < len(input.out_shapes[0]):
begin = begin + [0] * (len(input.out_shapes[0]) - len(begin))
if len(end) < len(input.out_shapes[0]):
end = end + [0] * (len(input.out_shapes[0]) - len(end))
for i in range(len(end)):
if end[i] == 0:
end[i] = 999999
begin_mask = node.get_attr('begin_mask')
end_mask = node.get_attr('end_mask')
ellipsis_mask = node.get_attr('ellipsis_mask')
new_axis_mask = node.get_attr('new_axis_mask')
shrink_axis_mask = node.get_attr('shrink_axis_mask')
assert ellipsis_mask == 0, "(OP:{} Name:{})Only support ellipsis_mask be 0[now: {}] n StridedSlice OP".format(
node.layer_type, node.layer.name, ellipsis_mask)
# TODO codes without validation
# Use it carefully
new_begin = list()
new_end = list()
new_axes = list()
shrink_axes = list()
for i, item in enumerate(begin):
mask = (new_axis_mask >> i) & 1
if mask != 0:
new_axes.append(i)
continue
mask = (shrink_axis_mask >> i) & 1
if mask != 0:
shrink_axes.append(i)
mask = (begin_mask >> i) & 1
if mask != 0:
new_begin.append(0)
else:
new_begin.append(item)
mask = (end_mask >> i) & 1
if mask != 0:
new_end.append(999999)
else:
new_end.append(end[i])
if input.dtype == "bool":
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": input.name},
outputs=[input.name],
dtype=string("int32"))
self.paddle_graph.add_layer(
kernel="paddle.slice",
inputs={"input": input.name},
outputs=[node.name],
axes=[i for i in range(len(new_begin))],
starts=new_begin,
ends=new_end)
if input.dtype == "bool":
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": node.name},
outputs=[node.name],
dtype=string("bool"))
if len(new_axes) > 0:
self.paddle_graph.add_layer(
kernel="paddle.unsqueeze",
inputs={"x": node.name},
outputs=[node.name],
axis=new_axes)
if len(shrink_axes) > 0:
if len(input.out_shapes[0]) + len(new_axes) <= 1:
pass
else:
self.paddle_graph.add_layer(
kernel="paddle.squeeze",
inputs={"x": node.name},
outputs=[node.name],
axis=shrink_axes)
def Prod(self, node):
input = self.graph.get_input_node(node, 0)
reduction_indices = self.graph.get_input_node(node, 1)
assert reduction_indices.layer_type == "Const"
keep_dims = node.get_attr('keep_dims')
axis = reduction_indices.value
self.paddle_graph.add_layer(
kernel="paddle.prod",
inputs={"x": input.name},
outputs=[node.layer_name],
keepdim=keep_dims,
axis=axis)
def Split(self, node):
dim = self.graph.get_input_node(node, 0)
input = self.graph.get_input_node(node, 1)
assert dim.layer_type == "Const"
num_split = node.get_attr('num_split')
dim = dim.value
self.paddle_graph.add_layer(
kernel="paddle.split",
inputs={"x": input.name},
outputs=[
"{}_p{}".format(node.layer_name, i) for i in range(num_split)
],
num_or_sections=num_split,
axis=dim)
def SplitV(self, node):
input = self.graph.get_input_node(node, 0)
size_splits = self.graph.get_input_node(node, 1)
assert size_splits.layer_type == "Const", "size_splits of SplitV OP should be Const"
size_splits = size_splits.value.tolist()
dim = self.graph.get_input_node(node, 2)
assert dim.layer_type == "Const", "dim of SplitV OP should be Const"
dim = dim.value
self.paddle_graph.add_layer(
kernel="paddle.split",
inputs={"x": input.name},
outputs=[
"{}_p{}".format(node.layer_name, i)
for i in range(len(size_splits))
],
num_or_sections=size_splits,
axis=dim)
def Slice(self, node):
input = self.graph.get_input_node(node, 0)
begin = self.graph.get_input_node(node, 1)
size = self.graph.get_input_node(node, 2)
inputs = {"x": input.name}
attrs = {}
if begin.layer_type == "Const":
begin = begin.value.tolist()
attrs['offsets'] = begin
else:
begin = self.decoder.infer_tensor(
begin, use_diff_inputs=False).tolist()
attrs['offsets'] = begin
if size.layer_type == "Const":
size = size.value.tolist()
attrs['shape'] = size
else:
shape = size.out_shapes[0]
reshape_name = gen_name("slice", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": size.name},
outputs=[reshape_name],
shape=shape)
inputs['shape'] = reshape_name
self.paddle_graph.add_layer(
kernel="paddle.crop", inputs=inputs, outputs=[node.name], **attrs)
def ResizeNearestNeighbor(self, node):
input = self.graph.get_input_node(node, 0)
resize_shape = self.graph.get_input_node(node, 1)
data_format = "NHWC"
inputs = {"x": input.name}
attrs = {
"align_corners": node.get_attr("align_corners"),
"mode": string("nearest"),
"align_mode": 1
}
if resize_shape.layer_type == "Const":
resize_shape = resize_shape.value.tolist()
attrs["size"] = resize_shape
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_nearest", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
shape=shape)
inputs["size"] = reshape_name
if data_format == "NHWC":
transpose_name = gen_name("resize_nearest", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["x"] = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def ResizeBilinear(self, node):
input = self.graph.get_input_node(node, 0)
resize_shape = self.graph.get_input_node(node, 1)
data_format = "NHWC"
inputs = {"x": input.name}
attrs = {
"align_corners": node.get_attr("align_corners"),
"mode": string("bilinear"),
"align_mode": 1
}
if resize_shape.layer_type == "Const":
resize_shape = resize_shape.value.tolist()
attrs["size"] = resize_shape
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_bilinear", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
shape=shape)
inputs["size"] = reshape_name
if data_format == "NHWC":
transpose_name = gen_name("resize_bilinear", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["x"] = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Cast(self, node):
input = self.graph.get_input_node(node, 0)
dtype = node.dtype
self.paddle_graph.add_layer(
kernel="paddle.cast",
inputs={"x": input.name},
outputs=[node.name],
dtype=string(dtype))
def Sum(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.sum",
inputs={"x": input.name},
outputs=[node.name],
axis=dim,
keepdim=keep_dims)
def Max(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.max",
inputs={"x": input.name},
outputs=[node.name],
axis=dim,
keepdim=keep_dims)
def RandomUniform(self, node):
shape = self.graph.get_input_node(node, 0)
if shape.layer_type == "Const":
shape = shape.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.uniform",
inputs={},
outputs=[node.name],
shape=shape,
min=0.0,
max=0.9999)
else:
self.paddle_graph.add_layer(
kernel="paddle.uniform",
inputs={'shape': shape.name},
outputs=[node.name],
min=0.0,
max=0.9999)
def Conv2DBackpropInput(self, node):
out_shape = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
input = self.graph.get_input_node(node, 2)
assert kernel.layer_type == "Const", "Kernel of Conv2DBackpropInput should be Const"
if out_shape.layer_type == "Const":
out_shape = out_shape.value.tolist()
else:
out_shape = self.decoder.infer_tensor(
out_shape, out_shape=node.out_shapes[0])
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(
input, use_diff_inputs=False).shape
k_size = kernel.out_shapes[0]
if k_size.count(-1) > 2:
k_size = self.decoder.infer_tensor(
kernel, use_diff_inputs=False).shape
pad_mode = node.get_attr("padding").decode()
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
kernel_name = node.name + ".weight"
self.params[kernel_name] = numpy.transpose(kernel.value, (3, 2, 0, 1))
input_name = input.name
if data_format == "NHWC":
in_shape = [in_shape[i] for i in [0, 3, 1, 2]]
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2dbackpropinput", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.static.create_parameter",
inputs={},
outputs=["{}_{}".format(node.name, kernel_name).replace(".", "_")],
dtype=string(str(self.params[kernel_name].dtype)),
shape=self.params[kernel_name].shape,
name=string(kernel_name))
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d_transpose",
inputs={
"x": input_name,
"weight":
"{}_{}".format(node.name, kernel_name).replace(".", "_")
},
outputs=[node.name],
bias=None,
stride=strides[2:4],
dilation=dilations[2:4],
padding=string(pad_mode),
output_size=out_shape[1:3])
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Tile(self, node):
input = self.graph.get_node(node.layer.input[0])
repeat_times = self.graph.get_node(node.layer.input[1])
inputs = {"x": input.name}
attr = dict()
if repeat_times.layer_type == "Const":
repeat_times = repeat_times.value.tolist()
attr["repeat_times"] = repeat_times
else:
inputs["repeat_times"] = repeat_times.name
self.paddle_graph.add_layer(
kernel="paddle.tile", inputs=inputs, outputs=[node.name], **attr)
if not isinstance(repeat_times,
list) and repeat_times.layer_type != "Const":
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def Range(self, node):
start = self.graph.get_node(node.layer.input[0])
limit = self.graph.get_node(node.layer.input[1])
delta = self.graph.get_node(node.layer.input[2])
inputs = dict()
attr = dict()
dtype = 'int32'
if start.dtype.startswith('float'):
dtype = start.dtype
if start.layer_type == "Const":
attr["start"] = start.value
else:
inputs["start"] = start.name
if limit.dtype.startswith('float'):
dtype = limit.dtype
if limit.layer_type == "Const":
attr["end"] = limit.value
else:
inputs["end"] = limit.name
if delta.dtype.startswith('float'):
dtype = delta.dtype
if delta.layer_type == "Const":
attr["step"] = delta.value
else:
inputs["step"] = delta.name
node.set_dtype(dtype)
attr["dtype"] = string(node.dtype)
self.paddle_graph.add_layer(
kernel="paddle.arange", inputs=inputs, outputs=[node.name], **attr)
if start.layer_type != "Const" or \
limit.layer_type != "Const" or \
delta.layer_type != "Const":
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def SquaredDifference(self, node):
x = self.graph.get_input_node(node, 0)
y = self.graph.get_input_node(node, 1)
inputs = {"x": x.name, "y": y.name}
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
# TODO(syf)
layer_id = self.paddle_graph.add_layer(
"paddle.subtract", inputs=inputs, outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {
"x": x_shape,
"y": y_shape
}
inputs = {"x": node.name, "y": node.name}
x_shape = node.out_shapes[0]
y_shape = node.out_shapes[0]
layer_id = self.paddle_graph.add_layer(
"paddle.multiply", inputs=inputs, outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {
"x": x_shape,
"y": y_shape
}
def OneHot(self, node):
input = self.graph.get_input_node(node, 0)
depth = self.graph.get_input_node(node, 1)
on_value = self.graph.get_input_node(node, 2)
off_value = self.graph.get_input_node(node, 3)
assert depth.layer_type == 'Const', 'Parameter depth should be Const in OneHot'
assert on_value.layer_type == 'Const', 'Parameter on_value should be Const in OneHot'
assert off_value.layer_type == 'Const', 'Parameter off_value should be Const in OneHot'
attr = {'depth': depth.value}
on_value = on_value.value
off_value = off_value.value
assert math.fabs(on_value -
1.0) < 1e-06, "on_value should be 1 in OneHot"
assert math.fabs(off_value -
0.0) < 1e-06, "off_value should be 0 in OneHot"
self.paddle_graph.add_layer(
"paddle.nn.functional.one_hot",
inputs={"x": input.name},
outputs=[node.name],
num_classes=depth.value)
def Pow(self, node):
x = self.graph.get_input_node(node, 0)
factor = self.graph.get_input_node(node, 1)
inputs = {"x": x.name}
attr = dict()
if factor.layer_type == 'Const':
attr["y"] = factor.value.tolist()
else:
inputs["y"] = factor.name
self.paddle_graph.add_layer(
"paddle.pow", inputs=inputs, outputs=[node.name], **attr)
def All(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
attr = dict()
attr["axis"] = reduce_idx.value.tolist()
attr["keepdim"] = node.get_attr("keep_dims")
input_name = input.name
if input.dtype != "bool":
input_name = gen_name("all", "cast")
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": input.name},
outputs=[input_name],
dtype=string("bool"))
self.paddle_graph.add_layer(
"paddle.all", inputs={"x": input_name}, outputs=[node.name], **attr)
node.layer.attr['dtype'].type = 10
def GatherV2(self, node):
embeddings = self.graph.get_input_node(node, 0)
index = self.graph.get_input_node(node, 1)
axis = self.graph.get_input_node(node, 2)
assert axis.layer_type == 'Const', "Only support Const parameter[axis]"
axis = axis.value
index_name = index.name
if len(index.out_shapes[0]) != 1:
reshape_name = gen_name("gather", "reshape")
index_name = reshape_name
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": index.name},
outputs=[reshape_name],
shape=[-1])
inputs = {'x': embeddings.name, 'index': index_name}
self.paddle_graph.add_layer(
"paddle.gather", inputs=inputs, outputs=[node.name], axis=axis)
if len(index.out_shapes[0]) != 1:
out_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape)
def GatherNd(self, node):
x = self.graph.get_input_node(node, 0)
index = self.graph.get_input_node(node, 1)
inputs = {'x': x.name, 'index': index.name}
self.paddle_graph.add_layer(
"paddle.gather_nd", inputs=inputs, outputs=[node.name])
def ExpandDims(self, node):
x = self.graph.get_input_node(node, 0, copy=True)
y = self.graph.get_input_node(node, 1, copy=True)
inputs = {"x": x.name}
attr = dict()
if y.layer_type == 'Const':
dim = y.value.tolist()
if not isinstance(dim, list):
dim = [dim]
attr['axis'] = dim
else:
inputs['axis'] = y.name
self.paddle_graph.add_layer(
"paddle.unsqueeze", inputs=inputs, outputs=[node.name], **attr)
def ReverseV2(self, node):
x = self.graph.get_input_node(node, 0)
axis = self.graph.get_input_node(node, 1)
inputs = {"x": x.name}
attr = dict()
if axis.layer_type == 'Const':
axis = axis.value.tolist()
if not isinstance(axis, list):
axis = [axis]
attr['axis'] = axis
else:
inputs['axis'] = axis.name
self.paddle_graph.add_layer(
"paddle.flip", inputs=inputs, outputs=[node.name], **attr)
def BatchToSpaceND(self, node):
'''
reshape->transpose->reshape->crop
'''
x = self.graph.get_input_node(node, 0)
block_shape = self.graph.get_input_node(node, 1)
crops = self.graph.get_input_node(node, 2)
if block_shape.layer_type == "Const":
block_shape = block_shape.value.tolist()
if crops.layer_type == "Const":
crops = crops.value.tolist()
data_format = x.get_attr("data_format").decode()
if data_format == "NHWC":
n, h, w, c = x.out_shapes[0]
else:
n, c, h, w = x.out_shapes[0]
input_name = x.name
#reshape
shape = block_shape + [-1, h, w, c]
reshape_name = gen_name("batch_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[reshape_name],
shape=shape)
#transpose
perm = [len(block_shape)] + list(j for i in range(len(block_shape)) for j in (i + len(block_shape) + 1, i)) +\
list(i + 2*len(block_shape) + 1 for i in range(len(x.out_shapes[0]) - len(block_shape) - 1))
transpose_name = gen_name("batch_to_space", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": reshape_name},
outputs=[transpose_name],
perm=perm)
#reshape
shape = [-1] + list(i * j
for i, j in zip(block_shape, x.out_shapes[0][
1:])) + x.out_shapes[0][1 + len(block_shape):]
reshape_name = gen_name("batch_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": transpose_name},
outputs=[reshape_name],
shape=shape)
#crop
attrs = {}
crop_shape = shape
crop_offsets = [0] * len(shape)
for i in range(len(crops)):
crop_shape[i + 1] = crop_shape[i + 1] - crops[i][0] - crops[i][1]
crop_offsets[i + 1] = crops[i][0]
attrs['shape'] = crop_shape
attrs['offsets'] = crop_offsets
self.paddle_graph.add_layer(
kernel="paddle.crop",
inputs={"x": reshape_name},
outputs=[node.name],
**attrs)
def SpaceToBatchND(self, node):
'''
zero-pad->reshape->transpose->reshape
'''
x = self.graph.get_input_node(node, 0)
block_shape = self.graph.get_input_node(node, 1)
paddings = self.graph.get_input_node(node, 2)
if block_shape.layer_type == "Const":
block_shape = block_shape.value.tolist()
if paddings.layer_type == "Const":
paddings = paddings.value.flatten().tolist()
input_name = x.name
#zero-pad
constant_values = 0
pad_name = gen_name("space_to_batch", "pad")
paddings = [0, 0] + paddings + [0, 0]
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pad",
inputs={"x": input_name},
outputs=[pad_name],
pad=paddings,
value=constant_values)
#reshape
n, h, w, c = x.out_shapes[0]
h = h + paddings[2] + paddings[3]
w = w + paddings[4] + paddings[5]
shape = [
n, h // block_shape[0], block_shape[0], w // block_shape[1],
block_shape[1], c
]
reshape_name = gen_name("space_to_batch", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": pad_name},
outputs=[reshape_name],
shape=shape)
#transpose
transpose_name = gen_name("space_to_batch", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": reshape_name},
outputs=[transpose_name],
perm=[2, 4, 0, 1, 3, 5])
#reshape
shape = [-1, h // block_shape[0], w // block_shape[1], c]
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": transpose_name},
outputs=[node.name],
shape=shape)
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
from x2paddle.decoder.tf_decoder import TFGraph, TFGraphNode from x2paddle.decoder.tf_decoder import TFGraph, TFGraphNode
from x2paddle.core.program import PaddleGraph from x2paddle.core.program import PaddleGraph
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import * from x2paddle.core.util import *
import traceback import traceback
import math import math
...@@ -46,7 +45,7 @@ def get_same_padding(in_size, kernel_size, stride): ...@@ -46,7 +45,7 @@ def get_same_padding(in_size, kernel_size, stride):
return [pad0, pad1] return [pad0, pad1]
class TFOpMapper(OpMapper): class TFOpMapper():
directly_map_ops = { directly_map_ops = {
'Relu': ['paddle.nn.ReLU'], 'Relu': ['paddle.nn.ReLU'],
'Relu6': ['paddle.nn.ReLU6'], 'Relu6': ['paddle.nn.ReLU6'],
...@@ -86,7 +85,6 @@ class TFOpMapper(OpMapper): ...@@ -86,7 +85,6 @@ class TFOpMapper(OpMapper):
} }
def __init__(self, decoder): def __init__(self, decoder):
super(TFOpMapper, self).__init__()
self.decoder = decoder self.decoder = decoder
self.graph = decoder.tf_graph self.graph = decoder.tf_graph
if not self.op_checker(): if not self.op_checker():
...@@ -95,8 +93,7 @@ class TFOpMapper(OpMapper): ...@@ -95,8 +93,7 @@ class TFOpMapper(OpMapper):
self.nn_name2id = dict() self.nn_name2id = dict()
self.input_index = 0 self.input_index = 0
self.inputs_info = dict() self.inputs_info = dict()
self.paddle_graph = PaddleGraph( self.paddle_graph = PaddleGraph(parent_layer=None, source_type="tf")
parent_layer=None, graph_type="dygraph", source_type="tf")
self.paddle_graph.outputs = self.graph.output_nodes self.paddle_graph.outputs = self.graph.output_nodes
not_placeholder = list() not_placeholder = list()
...@@ -649,16 +646,16 @@ class TFOpMapper(OpMapper): ...@@ -649,16 +646,16 @@ class TFOpMapper(OpMapper):
paddings = self.graph.get_input_node(node, 1) paddings = self.graph.get_input_node(node, 1)
assert paddings.layer_type == "Const", "Padding should be Const" assert paddings.layer_type == "Const", "Padding should be Const"
paddings = paddings.value.flatten().tolist() paddings = paddings.value.flatten().tolist()
constant_values = 0 constant_values = 0
if len(node.layer.input) > 2: if len(node.layer.input) > 2:
constant_values = self.graph.get_input_node(node, 2) constant_values = self.graph.get_input_node(node, 2)
assert constant_values.layer_type == "Const", "Padding should be Const" assert constant_values.layer_type == "Const", "Padding should be Const"
constant_values = constant_values.value constant_values = constant_values.value
if len(paddings) == 8 and sum(paddings[:2]) == 0 \ if len(paddings) == 8 and sum(paddings[:2]) == 0 \
and sum(paddings[-2:]) == 0: and sum(paddings[-2:]) == 0:
paddings = paddings[2: -2] paddings = paddings[2:-2]
self.paddle_graph.add_layer( self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pad", kernel="paddle.nn.functional.pad",
inputs={"x": input.name}, inputs={"x": input.name},
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .transpose_elimination import TransposeElimination
from .transpose_eliminate_pass import TransposeEliminatePass
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .transpose_elimination import DygraphTransposeElimination
from .transpose_eliminate_pass import DygraphTransposeEliminatePass
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .transpose_elimination import StaticTransposeElimination
from .transpose_eliminate_pass import StaticTransposeEliminatePass
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.elimination.static import StaticTransposeElimination
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class StaticTransposeEliminatePass(Pass):
name = "static_transpose_eliminate_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = StaticTransposeElimination()
fuser.operate(graph)
# 用于注册
static_transpose_eliminate_pass = StaticTransposeEliminatePass()
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import copy
import sys
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class StaticTransposeElimination(FuseBase):
def __init__(self):
super(StaticTransposeElimination, self).__init__(graph_type="static")
self.direct_layers = [
'paddle.nn.functional.relu', 'paddle.nn.functional.relu6', 'paddle.abs',
'paddle.nn.functional.sigmoid', 'paddle.exp', 'paddle.rsqrt',
'paddle.nn.functional.swish', 'paddle.tanh',
'paddle.nn.functional.softplus', 'paddle.nn.functional.leaky_relu',
'paddle.floor', 'paddle.erf', 'paddle.square'
]
self.elementwise_layers = [
'paddle.add', 'fluid.layers.elementwise_sub',
'paddle.multiply', 'paddle.divide'
]
self.reduce_layers = [
'paddle.mean', 'paddle.all',
'paddle.max', 'paddle.any',
'paddle.sum', 'paddle.prod'
]
def get_transpose_num(self, graph):
count = 0
for layer_id, layer in graph.layers.items():
if layer.kernel == "paddle.transpose":
count += 1
return count
def operate(self, graph):
total_layer_num = len(graph.layers)
scanned_layers = set()
optimized_transpose_layers = list()
optimized_reduce_layers = list()
optimized_concat_layers = list()
optimized_elementwise_layers = list()
def get_index(layer):
if layer.kernel.startswith("paddle.nn") and "functional" not in layer.kernel:
return 1
else:
return 0
def strip_transpose(_graph):
layers = copy.deepcopy(_graph.layers)
for layer_id, layer in layers.items():
if layer_id in scanned_layers:
continue
scanned_layers.add(layer_id)
percent = round(len(scanned_layers) / total_layer_num * 100, 2)
sys.stderr.write("\rOptimize Transpose Layers...{}%".format(
percent))
if layer.kernel != "paddle.transpose":
continue
if layer.attrs["perm"] != [0, 2, 3, 1]:
continue
transpose_layers = list()
propagate_layers = list()
reduce_layers = list()
concat_layers = list()
# 此elementwise_layers专用于存储shape(4) + shape(1)的形式layer
elementwise_layers = list()
can_be_optimized = True
for out in _graph.edges_out.get(layer_id, []):
if _graph.layers[out].kernel == "paddle.transpose":
if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]:
can_be_optimized = False
break
transpose_layers.append(out)
elif _graph.layers[out].kernel in self.elementwise_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers:
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers:
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[out].attrs.get('keepdim', False):
can_be_optimized = False
break
propagate_layers.append(out)
reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat":
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
propagate_layers.append(out)
concat_layers.append(out)
else:
can_be_optimized = False
break
visited_layers = set()
while len(propagate_layers) > 0 and can_be_optimized:
current_id = propagate_layers.pop(0)
visited_layers.add(current_id)
for out in _graph.edges_out.get(current_id, []):
if _graph.layers[
out].kernel == "paddle.transpose":
if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]:
can_be_optimized = False
break
transpose_layers.append(out)
elif _graph.layers[
out].kernel in self.elementwise_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[out].attrs.get('keepdim',
False):
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat":
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
concat_layers.append(out)
else:
can_be_optimized = False
break
for ipt in _graph.edges_in.get(current_id, []):
if _graph.layers[
current_id].kernel in self.elementwise_layers:
try:
x_shape = _graph.layers[
current_id].input_shapes['x']
y_shape = _graph.layers[
current_id].input_shapes['y']
output_index = get_index(_graph.layers[ipt])
if _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[
'x']:
if list(x_shape)==[1] or len(x_shape) < 1:
elementwise_layers.append(current_id)
continue
elif _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[
'y']:
if list(y_shape)==[1] or len(y_shape) < 1:
elementwise_layers.append(current_id)
continue
else:
raise Exception(
"Unexcepted situation happend while optimizing transpose"
)
except Exception as e:
can_be_optimized = False
break
output_index = get_index(_graph.layers[ipt])
if _graph.layers[
ipt].kernel == "paddle.transpose":
if _graph.layers[ipt].attrs["perm"] != [0, 2, 3, 1]:
can_be_optimized = False
break
if ipt not in visited_layers:
transpose_layers.append(ipt)
elif _graph.layers[
ipt].kernel in self.elementwise_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.direct_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.reduce_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[ipt].attrs.get('keepdim',
False):
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
reduce_layers.append(ipt)
elif _graph.layers[ipt].kernel == "paddle.concat":
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
concat_layers.append(ipt)
else:
can_be_optimized = False
break
if not can_be_optimized:
break
if not can_be_optimized:
continue
transpose_layers.append(layer_id)
transpose_layers = list(set(transpose_layers))
for l in transpose_layers:
output_index = get_index(graph.layers[l])
if graph.layers[l].outputs[output_index] in graph.outputs:
can_be_optimized = False
break
if not can_be_optimized:
continue
for l in transpose_layers:
_graph.del_layer(l)
optimized_transpose_layers.extend(transpose_layers)
optimized_reduce_layers.extend(reduce_layers)
optimized_concat_layers.extend(concat_layers)
optimized_elementwise_layers.extend(elementwise_layers)
return True
return False
before_transpose_num = self.get_transpose_num(graph)
opt_graph = copy.deepcopy(graph)
total_layer_num = len(opt_graph.layers)
while strip_transpose(opt_graph):
pass
for layer_id in list(set(optimized_transpose_layers)):
graph.del_layer(layer_id)
for layer_id in list(set(optimized_reduce_layers)):
dim = graph.layers[layer_id].attrs.get('axis', None)
if dim is not None:
for i in range(len(dim)):
dim[i] = [0, 2, 3, 1][dim[i]]
graph.layers[layer_id].attrs['axis'] = dim
for layer_id in list(set(optimized_concat_layers)):
axis = graph.layers[layer_id].attrs.get('axis', 0)
graph.layers[layer_id].attrs['axis'] = [0, 2, 3, 1][axis]
current_transpose_num = self.get_transpose_num(graph)
print(
"\nTranspose layers optimized, before: transpose_num={}, after: transpose_num={}".
format(before_transpose_num, current_transpose_num))
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.elimination.dygraph import DygraphTransposeElimination from x2paddle.optimizer.elimination import TransposeElimination
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphTransposeEliminatePass(Pass): class TransposeEliminatePass(Pass):
name = "transpose_eliminate_pass" name = "transpose_eliminate_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphTransposeElimination() fuser = TransposeElimination()
fuser.operate(graph) fuser.operate(graph)
# 用于注册 # 用于注册
transpose_eliminate_pass = DygraphTransposeEliminatePass() transpose_eliminate_pass = TransposeEliminatePass()
\ No newline at end of file
...@@ -20,23 +20,21 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -20,23 +20,21 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphTransposeElimination(FuseBase): class TransposeElimination(FuseBase):
def __init__(self): def __init__(self):
super(DygraphTransposeElimination, self).__init__(graph_type="dygraph") super(TransposeElimination, self).__init__()
self.direct_layers = [ self.direct_layers = [
'paddle.nn.ReLU', 'paddle.nn.ReLU6', 'paddle.abs', 'paddle.nn.ReLU', 'paddle.nn.ReLU6', 'paddle.abs',
'paddle.nn.Sigmoid', 'paddle.exp', 'paddle.rsqrt', 'paddle.nn.Sigmoid', 'paddle.exp', 'paddle.rsqrt',
'paddle.nn.Swish', 'paddle.nn.Tanh', 'paddle.nn.Swish', 'paddle.nn.Tanh', 'paddle.nn.Softplus',
'paddle.nn.Softplus', 'paddle.nn.LeakyReLU', 'paddle.nn.LeakyReLU', 'paddle.floor', 'paddle.erf', 'paddle.square'
'paddle.floor', 'paddle.erf', 'paddle.square'
] ]
self.elementwise_layers = [ self.elementwise_layers = [
'paddle.add', 'fluid.layers.elementwise_sub', 'paddle.add', 'fluid.layers.elementwise_sub', 'paddle.multiply',
'paddle.multiply', 'paddle.divide' 'paddle.divide'
] ]
self.reduce_layers = [ self.reduce_layers = [
'paddle.mean', 'paddle.all', 'paddle.mean', 'paddle.all', 'paddle.max', 'paddle.any',
'paddle.max', 'paddle.any',
'paddle.sum', 'paddle.prod' 'paddle.sum', 'paddle.prod'
] ]
...@@ -46,7 +44,7 @@ class DygraphTransposeElimination(FuseBase): ...@@ -46,7 +44,7 @@ class DygraphTransposeElimination(FuseBase):
if layer.kernel == "paddle.transpose": if layer.kernel == "paddle.transpose":
count += 1 count += 1
return count return count
def operate(self, graph): def operate(self, graph):
total_layer_num = len(graph.layers) total_layer_num = len(graph.layers)
scanned_layers = set() scanned_layers = set()
...@@ -54,12 +52,13 @@ class DygraphTransposeElimination(FuseBase): ...@@ -54,12 +52,13 @@ class DygraphTransposeElimination(FuseBase):
optimized_reduce_layers = list() optimized_reduce_layers = list()
optimized_concat_layers = list() optimized_concat_layers = list()
optimized_elementwise_layers = list() optimized_elementwise_layers = list()
def get_index(layer): def get_index(layer):
if layer.kernel.startswith("paddle.nn") and "functional" not in layer.kernel: if layer.kernel.startswith(
"paddle.nn") and "functional" not in layer.kernel:
return 1 return 1
else: else:
return 0 return 0
def strip_transpose(_graph): def strip_transpose(_graph):
layers = copy.deepcopy(_graph.layers) layers = copy.deepcopy(_graph.layers)
...@@ -92,13 +91,15 @@ class DygraphTransposeElimination(FuseBase): ...@@ -92,13 +91,15 @@ class DygraphTransposeElimination(FuseBase):
propagate_layers.append(out) propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers: elif _graph.layers[out].kernel in self.direct_layers:
ouput_index = get_index(_graph.layers[out]) ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs: if _graph.layers[out].outputs[
ouput_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
propagate_layers.append(out) propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers: elif _graph.layers[out].kernel in self.reduce_layers:
ouput_index = get_index(_graph.layers[out]) ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs: if _graph.layers[out].outputs[
ouput_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if not _graph.layers[out].attrs.get('keepdim', False): if not _graph.layers[out].attrs.get('keepdim', False):
...@@ -108,7 +109,8 @@ class DygraphTransposeElimination(FuseBase): ...@@ -108,7 +109,8 @@ class DygraphTransposeElimination(FuseBase):
reduce_layers.append(out) reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat": elif _graph.layers[out].kernel == "paddle.concat":
ouput_index = get_index(_graph.layers[out]) ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs: if _graph.layers[out].outputs[
ouput_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
propagate_layers.append(out) propagate_layers.append(out)
...@@ -122,8 +124,7 @@ class DygraphTransposeElimination(FuseBase): ...@@ -122,8 +124,7 @@ class DygraphTransposeElimination(FuseBase):
current_id = propagate_layers.pop(0) current_id = propagate_layers.pop(0)
visited_layers.add(current_id) visited_layers.add(current_id)
for out in _graph.edges_out.get(current_id, []): for out in _graph.edges_out.get(current_id, []):
if _graph.layers[ if _graph.layers[out].kernel == "paddle.transpose":
out].kernel == "paddle.transpose":
if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]: if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]:
can_be_optimized = False can_be_optimized = False
break break
...@@ -131,21 +132,24 @@ class DygraphTransposeElimination(FuseBase): ...@@ -131,21 +132,24 @@ class DygraphTransposeElimination(FuseBase):
elif _graph.layers[ elif _graph.layers[
out].kernel in self.elementwise_layers: out].kernel in self.elementwise_layers:
output_index = get_index(_graph.layers[out]) output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs: if _graph.layers[out].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if out not in visited_layers: if out not in visited_layers:
propagate_layers.append(out) propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers: elif _graph.layers[out].kernel in self.direct_layers:
output_index = get_index(_graph.layers[out]) output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs: if _graph.layers[out].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if out not in visited_layers: if out not in visited_layers:
propagate_layers.append(out) propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers: elif _graph.layers[out].kernel in self.reduce_layers:
output_index = get_index(_graph.layers[out]) output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs: if _graph.layers[out].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if not _graph.layers[out].attrs.get('keepdim', if not _graph.layers[out].attrs.get('keepdim',
...@@ -157,7 +161,8 @@ class DygraphTransposeElimination(FuseBase): ...@@ -157,7 +161,8 @@ class DygraphTransposeElimination(FuseBase):
reduce_layers.append(out) reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat": elif _graph.layers[out].kernel == "paddle.concat":
output_index = get_index(_graph.layers[out]) output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs: if _graph.layers[out].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if out not in visited_layers: if out not in visited_layers:
...@@ -176,15 +181,15 @@ class DygraphTransposeElimination(FuseBase): ...@@ -176,15 +181,15 @@ class DygraphTransposeElimination(FuseBase):
current_id].input_shapes['y'] current_id].input_shapes['y']
output_index = get_index(_graph.layers[ipt]) output_index = get_index(_graph.layers[ipt])
if _graph.layers[ipt].outputs[ if _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[ output_index] == _graph.layers[
'x']: current_id].inputs['x']:
if list(x_shape)==[1] or len(x_shape) < 1: if list(x_shape) == [1] or len(x_shape) < 1:
elementwise_layers.append(current_id) elementwise_layers.append(current_id)
continue continue
elif _graph.layers[ipt].outputs[ elif _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[ output_index] == _graph.layers[
'y']: current_id].inputs['y']:
if list(y_shape)==[1] or len(y_shape) < 1: if list(y_shape) == [1] or len(y_shape) < 1:
elementwise_layers.append(current_id) elementwise_layers.append(current_id)
continue continue
else: else:
...@@ -195,8 +200,7 @@ class DygraphTransposeElimination(FuseBase): ...@@ -195,8 +200,7 @@ class DygraphTransposeElimination(FuseBase):
can_be_optimized = False can_be_optimized = False
break break
output_index = get_index(_graph.layers[ipt]) output_index = get_index(_graph.layers[ipt])
if _graph.layers[ if _graph.layers[ipt].kernel == "paddle.transpose":
ipt].kernel == "paddle.transpose":
if _graph.layers[ipt].attrs["perm"] != [0, 2, 3, 1]: if _graph.layers[ipt].attrs["perm"] != [0, 2, 3, 1]:
can_be_optimized = False can_be_optimized = False
break break
...@@ -204,19 +208,22 @@ class DygraphTransposeElimination(FuseBase): ...@@ -204,19 +208,22 @@ class DygraphTransposeElimination(FuseBase):
transpose_layers.append(ipt) transpose_layers.append(ipt)
elif _graph.layers[ elif _graph.layers[
ipt].kernel in self.elementwise_layers: ipt].kernel in self.elementwise_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs: if _graph.layers[ipt].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if ipt not in visited_layers: if ipt not in visited_layers:
propagate_layers.append(ipt) propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.direct_layers: elif _graph.layers[ipt].kernel in self.direct_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs: if _graph.layers[ipt].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if ipt not in visited_layers: if ipt not in visited_layers:
propagate_layers.append(ipt) propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.reduce_layers: elif _graph.layers[ipt].kernel in self.reduce_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs: if _graph.layers[ipt].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if not _graph.layers[ipt].attrs.get('keepdim', if not _graph.layers[ipt].attrs.get('keepdim',
...@@ -227,7 +234,8 @@ class DygraphTransposeElimination(FuseBase): ...@@ -227,7 +234,8 @@ class DygraphTransposeElimination(FuseBase):
propagate_layers.append(ipt) propagate_layers.append(ipt)
reduce_layers.append(ipt) reduce_layers.append(ipt)
elif _graph.layers[ipt].kernel == "paddle.concat": elif _graph.layers[ipt].kernel == "paddle.concat":
if _graph.layers[ipt].outputs[output_index] in _graph.outputs: if _graph.layers[ipt].outputs[
output_index] in _graph.outputs:
can_be_optimized = False can_be_optimized = False
break break
if ipt not in visited_layers: if ipt not in visited_layers:
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .adaptive_pool2d_fuser import AdaptivePool2dFuser
from .adaptive_pool2d_fuse_pass import AdaptivePool2dFusePass
from .batchnorm2d_fuser import BatchNorm2dFuser
from .batchnorm2d_fuse_pass import BatchNorm2dFusePass
from .bn_scale_fuser import BNScaleFuser
from .bn_scale_fuse_pass import BNScaleFusePass
from .constant_fuser import ConstantFuser
from .constant_fuse_pass import ConstantFusePass
from .conv2d_add_fuser import Conv2DAddFuser
from .conv2d_add_fuse_pass import Conv2DAddFusePass
from .dropout_fuser import DropoutFuser
from .dropout_fuse_pass import DropoutFusePass
from .fc_fuser import FcFuser
from .fc_fuse_pass import FcFusePass
from .if_fuser import IfFuser
from .if_fuse_pass import IfFusePass
from .interpolate_bilinear_fuser import InterpolateBilinearFuser
from .interpolate_bilinear_fuse_pass import InterpolateBilinearFusePass
from .prelu_fuser import PReLUFuser
from .prelu_fuse_pass import PReLUFusePass
from .reshape_fuser import ReshapeFuser
from .reshape_fuse_pass import ReshapeFusePass
from .tf_batchnorm_fuser import TFBatchNormFuser
from .tf_batchnorm_fuse_pass import TFBatchNormFusePass
from .trace_fc_fuser import TraceFcFuser
from .trace_fc_fuse_pass import TraceFcFusePass
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion import AdaptivePool2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class AdaptivePool2dFusePass(Pass):
name = "adaptive_pool2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = AdaptivePool2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
adaptive_pool2d_fuse_pass = AdaptivePool2dFusePass()
...@@ -13,15 +13,15 @@ ...@@ -13,15 +13,15 @@
# limitations under the License. # limitations under the License.
import numpy as np import numpy as np
import copy import copy
from x2paddle.optimizer.pattern_matcher import FuseBase from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphAdaptivePool2dFuser(FuseBase): class AdaptivePool2dFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphAdaptivePool2dFuser, self).__init__(graph_type="dygraph") super(AdaptivePool2dFuser, self).__init__()
self.patterns = list() self.patterns = list()
def build_pattern(self): def build_pattern(self):
...@@ -42,7 +42,7 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -42,7 +42,7 @@ class DygraphAdaptivePool2dFuser(FuseBase):
x80 = [6, 6][_x79] x80 = [6, 6][_x79]
x73.append(x80) x73.append(x80)
x81 = paddle.nn.functional.adaptive_avg_pool2d(input=x60, pool_size=x73, pool_type='avg') x81 = paddle.nn.functional.adaptive_avg_pool2d(input=x60, pool_size=x73, pool_type='avg')
模式二: 模式二:
x64 = x60.shape x64 = x60.shape
x65 = len(x64) x65 = len(x64)
...@@ -56,9 +56,9 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -56,9 +56,9 @@ class DygraphAdaptivePool2dFuser(FuseBase):
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
# 模式一: # 模式一:
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"prim.shape", "prim.shape",
inputs={'input': "pool-input-0"}, inputs={'input': "pool-input-0"},
...@@ -69,14 +69,14 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -69,14 +69,14 @@ class DygraphAdaptivePool2dFuser(FuseBase):
"prim.le", inputs={"x": gen_name(6)}, outputs=[gen_name(8)], y=2) "prim.le", inputs={"x": gen_name(6)}, outputs=[gen_name(8)], y=2)
pattern.add_layer("prim.if", {'input': gen_name(8)}, [gen_name(9)]) pattern.add_layer("prim.if", {'input': gen_name(8)}, [gen_name(9)])
if_layer = pattern.layers[list(pattern.layers.keys())[-1]] if_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph") pattern_block0 = PaddleGraph(parent_layer=if_layer)
pattern_block0.add_layer( pattern_block0.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
outputs=[gen_name(9)], outputs=[gen_name(9)],
input="Exception") input="Exception")
if_layer.add_block(pattern_block0) if_layer.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph") pattern_block1 = PaddleGraph(parent_layer=if_layer)
if_layer.add_block(pattern_block1) if_layer.add_block(pattern_block1)
pattern.add_layer("prim.list", inputs={}, outputs=[gen_name(10)]) pattern.add_layer("prim.list", inputs={}, outputs=[gen_name(10)])
pattern.add_layer( pattern.add_layer(
...@@ -92,9 +92,9 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -92,9 +92,9 @@ class DygraphAdaptivePool2dFuser(FuseBase):
pattern.add_layer( pattern.add_layer(
"prim.min", inputs={"input": gen_name(15)}, outputs=[gen_name(16)]) "prim.min", inputs={"input": gen_name(15)}, outputs=[gen_name(16)])
pattern.add_layer("prim.loop", {'input': gen_name(16)}, pattern.add_layer("prim.loop", {'input': gen_name(16)},
[gen_name(17), gen_name(18)]) [gen_name(17), gen_name(18)])
loop_layer = pattern.layers[list(pattern.layers.keys())[-1]] loop_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph") pattern_block = PaddleGraph(loop_layer)
pattern_block.add_layer( pattern_block.add_layer(
"prim.getitem", "prim.getitem",
inputs={"index": gen_name(18)}, inputs={"index": gen_name(18)},
...@@ -115,9 +115,9 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -115,9 +115,9 @@ class DygraphAdaptivePool2dFuser(FuseBase):
**pool_attrs) **pool_attrs)
pattern.build(inputs={"input-0": "pool-input-0", }) pattern.build(inputs={"input-0": "pool-input-0", })
self.patterns.append(pattern) self.patterns.append(pattern)
# 模式二: # 模式二:
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"prim.shape", "prim.shape",
inputs={'input': "pool-input-0"}, inputs={'input': "pool-input-0"},
...@@ -128,9 +128,9 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -128,9 +128,9 @@ class DygraphAdaptivePool2dFuser(FuseBase):
"prim.gt", inputs={"x": gen_name(1)}, outputs=[gen_name(2)], y=2) "prim.gt", inputs={"x": gen_name(1)}, outputs=[gen_name(2)], y=2)
pattern.add_layer("prim.if", {'input': gen_name(2)}, [gen_name(3)]) pattern.add_layer("prim.if", {'input': gen_name(2)}, [gen_name(3)])
if_layer = pattern.layers[list(pattern.layers.keys())[-1]] if_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph") pattern_block0 = PaddleGraph(parent_layer=if_layer)
if_layer.add_block(pattern_block0) if_layer.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph") pattern_block1 = PaddleGraph(parent_layer=if_layer)
pattern_block1.add_layer( pattern_block1.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
...@@ -138,14 +138,15 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -138,14 +138,15 @@ class DygraphAdaptivePool2dFuser(FuseBase):
input="Exception") input="Exception")
if_layer.add_block(pattern_block1) if_layer.add_block(pattern_block1)
pattern.add_layer( pattern.add_layer(
"paddle.nn.AdaptiveAvgPool2D", "paddle.nn.AdaptiveAvgPool2D",
inputs={"input": "pool-input-0"}, inputs={"input": "pool-input-0"},
outputs=["pool1", gen_name(5)]) outputs=["pool1", gen_name(5)])
pattern.build(inputs={"input-0": "pool-input-0", pattern.build(inputs={
"input-1": "pool-input-0",}) "input-0": "pool-input-0",
"input-1": "pool-input-0",
})
self.patterns.append(pattern) self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
parameters = graph.parameters parameters = graph.parameters
new_layer = self.gen_new_layer(parameters, matches) new_layer = self.gen_new_layer(parameters, matches)
...@@ -155,7 +156,8 @@ class DygraphAdaptivePool2dFuser(FuseBase): ...@@ -155,7 +156,8 @@ class DygraphAdaptivePool2dFuser(FuseBase):
def gen_new_layer(self, parameters, matches): def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys()) layers_id = list(matches.keys())
if matches[layers_id[-1]].kernel == "paddle.nn.functional.adaptive_avg_pool2d": if matches[layers_id[
-1]].kernel == "paddle.nn.functional.adaptive_avg_pool2d":
layer = matches[layers_id[11]] layer = matches[layers_id[11]]
pool_size = layer.attrs["list"] pool_size = layer.attrs["list"]
layer = matches[layers_id[0]] layer = matches[layers_id[0]]
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion import BatchNorm2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class BatchNorm2dFusePass(Pass):
name = "batchnorm2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = BatchNorm2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
batchnorm2d_fuse_pass = BatchNorm2dFusePass()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphBatchNorm2dFuser(FuseBase): class BatchNorm2dFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphBatchNorm2dFuser, self).__init__(graph_type="dygraph") super(BatchNorm2dFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的batchnorm2d图结构。 """ 描述需要替换的batchnorm2d图结构。
...@@ -51,8 +51,7 @@ class DygraphBatchNorm2dFuser(FuseBase): ...@@ -51,8 +51,7 @@ class DygraphBatchNorm2dFuser(FuseBase):
return "x" + str(id) return "x" + str(id)
self.pattern.add_layer( self.pattern.add_layer(
"prim.shape", "prim.shape", inputs={'input': "bn-input-0"},
inputs={'input': "bn-input-0"},
outputs=[gen_name(0)]) outputs=[gen_name(0)])
self.pattern.add_layer( self.pattern.add_layer(
"prim.len", inputs={'input': gen_name(0)}, outputs=[gen_name(0)]) "prim.len", inputs={'input': gen_name(0)}, outputs=[gen_name(0)])
...@@ -60,21 +59,20 @@ class DygraphBatchNorm2dFuser(FuseBase): ...@@ -60,21 +59,20 @@ class DygraphBatchNorm2dFuser(FuseBase):
"prim.ne", inputs={"x": gen_name(0)}, outputs=[gen_name(1)], y=4) "prim.ne", inputs={"x": gen_name(0)}, outputs=[gen_name(1)], y=4)
self.pattern.add_layer("prim.if", {'input': gen_name(1)}, [gen_name(2)]) self.pattern.add_layer("prim.if", {'input': gen_name(1)}, [gen_name(2)])
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]] if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph") pattern_block0 = PaddleGraph(parent_layer=if_layer1)
pattern_block0.add_layer( pattern_block0.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
outputs=[gen_name(3)], outputs=[gen_name(3)],
input="Exception") input="Exception")
if_layer1.add_block(pattern_block0) if_layer1.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph") pattern_block1 = PaddleGraph(parent_layer=if_layer1)
if_layer1.add_block(pattern_block1) if_layer1.add_block(pattern_block1)
self.pattern.add_layer("prim.if", {}, [gen_name(4)], input=False) self.pattern.add_layer("prim.if", {}, [gen_name(4)], input=False)
if_layer2 = self.pattern.layers[list(self.pattern.layers.keys())[-1]] if_layer2 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph") pattern_block0 = PaddleGraph(parent_layer=if_layer2)
pattern_block0.add_layer( pattern_block0.add_layer(
"prim.shape", "prim.shape", inputs={'input': "bn-input-0"},
inputs={'input': "bn-input-0"},
outputs=[gen_name(5)]) outputs=[gen_name(5)])
pattern_block0.add_layer( pattern_block0.add_layer(
"prim.getitem", "prim.getitem",
...@@ -93,7 +91,7 @@ class DygraphBatchNorm2dFuser(FuseBase): ...@@ -93,7 +91,7 @@ class DygraphBatchNorm2dFuser(FuseBase):
outputs=[gen_name(8.1), gen_name(10)]) outputs=[gen_name(8.1), gen_name(10)])
loop_layer = pattern_block0.layers[list(pattern_block0.layers.keys())[ loop_layer = pattern_block0.layers[list(pattern_block0.layers.keys())[
-1]] -1]]
pattern_block0_block0 = PaddleGraph(parent_layer=loop_layer, graph_type="dygraph") pattern_block0_block0 = PaddleGraph(parent_layer=loop_layer)
pattern_block0_block0.add_layer( pattern_block0_block0.add_layer(
"prim.add", inputs={"x": gen_name(10)}, outputs=[gen_name(11)], y=2) "prim.add", inputs={"x": gen_name(10)}, outputs=[gen_name(11)], y=2)
pattern_block0_block0.add_layer( pattern_block0_block0.add_layer(
...@@ -119,17 +117,17 @@ class DygraphBatchNorm2dFuser(FuseBase): ...@@ -119,17 +117,17 @@ class DygraphBatchNorm2dFuser(FuseBase):
"prim.if", inputs={"input": gen_name(14)}, outputs=[gen_name(15)]) "prim.if", inputs={"input": gen_name(14)}, outputs=[gen_name(15)])
if_layer21 = pattern_block0.layers[list(pattern_block0.layers.keys())[ if_layer21 = pattern_block0.layers[list(pattern_block0.layers.keys())[
-1]] -1]]
pattern_block0_block0 = PaddleGraph(parent_layer=if_layer21, graph_type="dygraph") pattern_block0_block0 = PaddleGraph(parent_layer=if_layer21)
pattern_block0_block0.add_layer( pattern_block0_block0.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
outputs=[gen_name(15)], outputs=[gen_name(15)],
input="Exception") input="Exception")
if_layer21.add_block(pattern_block0_block0) if_layer21.add_block(pattern_block0_block0)
pattern_block0_block1 = PaddleGraph(parent_layer=if_layer21, graph_type="dygraph") pattern_block0_block1 = PaddleGraph(parent_layer=if_layer21)
if_layer21.add_block(pattern_block0_block1) if_layer21.add_block(pattern_block0_block1)
if_layer2.add_block(pattern_block0) if_layer2.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph") pattern_block1 = PaddleGraph(parent_layer=if_layer2)
if_layer2.add_block(pattern_block1) if_layer2.add_block(pattern_block1)
if_layer2.inputs["input-0"] = "bn-input-0" if_layer2.inputs["input-0"] = "bn-input-0"
self.pattern.add_layer( self.pattern.add_layer(
...@@ -145,7 +143,6 @@ class DygraphBatchNorm2dFuser(FuseBase): ...@@ -145,7 +143,6 @@ class DygraphBatchNorm2dFuser(FuseBase):
graph.layers[new_layer_id] = new_layer graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id) matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches): def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys()) layers_id = list(matches.keys())
layer = matches[layers_id[-1]] layer = matches[layers_id[-1]]
......
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.static import Static_BNScaleFuser from x2paddle.optimizer.fusion import BNScaleFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class Static_BNScaleFusePass(Pass): class BNScaleFusePass(Pass):
name = "static_bn_scale_fuse_pass" name = "bn_scale_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = Static_BNScaleFuser() fuser = BNScaleFuser()
fuser.operate(graph, match_kind="topo") fuser.operate(graph, match_kind="topo")
# 用于注册 # 用于注册
bn_scale_fuse_pass = Static_BNScaleFusePass() bn_scale_fuse_pass = BNScaleFusePass()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphBNScaleFuser(FuseBase): class BNScaleFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphBNScaleFuser, self).__init__(graph_type="dygraph") super(BNScaleFuser, self).__init__()
patterns = list() patterns = list()
def build_pattern(self): def build_pattern(self):
...@@ -43,72 +43,52 @@ class DygraphBNScaleFuser(FuseBase): ...@@ -43,72 +43,52 @@ class DygraphBNScaleFuser(FuseBase):
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"paddle.nn.BatchNorm2D", "paddle.nn.BatchNorm2D",
inputs={"input": "bn-input-0"}, inputs={"input": "bn-input-0"},
outputs=[gen_name(0)]) outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(1)])
inputs={},
outputs=[gen_name(1)])
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = gen_name(0) inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(1) inputs_dict['y'] = gen_name(1)
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply", inputs=inputs_dict, outputs=[gen_name(2)])
inputs=inputs_dict,
outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(3)])
inputs={},
outputs=[gen_name(3)])
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = gen_name(2) inputs_dict['x'] = gen_name(2)
inputs_dict['y'] = gen_name(3) inputs_dict['y'] = gen_name(3)
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict, outputs=[gen_name(4)])
inputs=inputs_dict,
outputs=[gen_name(4)])
pattern.build(inputs={"input-0": "bn-input-0"}) pattern.build(inputs={"input-0": "bn-input-0"})
self.patterns.append(pattern) self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"paddle.nn.BatchNorm2D", "paddle.nn.BatchNorm2D",
inputs={"input": "bn-input-0"}, inputs={"input": "bn-input-0"},
outputs=[gen_name(0)]) outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(1)])
inputs={},
outputs=[gen_name(1)])
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = gen_name(0) inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(1) inputs_dict['y'] = gen_name(1)
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply", inputs=inputs_dict, outputs=[gen_name(2)])
inputs=inputs_dict,
outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(3)])
inputs={},
outputs=[gen_name(3)])
pattern.add_layer( pattern.add_layer(
"paddle.reshape", "paddle.reshape", inputs={"x": gen_name(3)}, outputs=[gen_name(3)])
inputs={"x": gen_name(3)},
outputs=[gen_name(3)])
inputs_dict = {} inputs_dict = {}
inputs_dict['x'] = gen_name(2) inputs_dict['x'] = gen_name(2)
inputs_dict['y'] = gen_name(3) inputs_dict['y'] = gen_name(3)
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add", inputs=inputs_dict, outputs=[gen_name(4)])
inputs=inputs_dict,
outputs=[gen_name(4)])
pattern.build(inputs={"input-0": "bn-input-0"}) pattern.build(inputs={"input-0": "bn-input-0"})
self.patterns.append(pattern) self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches) new_layer = self.gen_new_layer(parameters, matches)
...@@ -116,7 +96,6 @@ class DygraphBNScaleFuser(FuseBase): ...@@ -116,7 +96,6 @@ class DygraphBNScaleFuser(FuseBase):
graph.layers[new_layer_id] = new_layer graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id) matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches): def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys()) layers_id = list(matches.keys())
layer = matches[layers_id[0]] layer = matches[layers_id[0]]
...@@ -141,4 +120,4 @@ class DygraphBNScaleFuser(FuseBase): ...@@ -141,4 +120,4 @@ class DygraphBNScaleFuser(FuseBase):
inputs=layer_inputs, inputs=layer_inputs,
outputs=layer_outputs, outputs=layer_outputs,
**layer_attrs) **layer_attrs)
return new_layer return new_layer
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion import ConstantFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class ConstantFusePass(Pass):
name = "constant_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = ConstantFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
constant_fuse_pass = ConstantFuser()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphConstantFuser(FuseBase): class ConstantFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphConstantFuser, self).__init__(graph_type="dygraph") super(ConstantFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的constant图结构。 """ 描述需要替换的constant图结构。
......
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphPReLUFuser from x2paddle.optimizer.fusion import Conv2DAddFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphPReLUFusePass(Pass): class Conv2DAddFusePass(Pass):
name = "dygraph_prelu_fuse_pass" name = "conv2d_add_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphPReLUFuser() fuser = Conv2DAddFuser()
fuser.operate(graph, match_kind="edge") fuser.operate(graph, match_kind="edge")
# 用于注册 # 用于注册
dygraph_prelu_fuse_pass = DygraphPReLUFusePass() conv2d_add_fuse_pass = Conv2DAddFusePass()
\ No newline at end of file
...@@ -19,9 +19,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -19,9 +19,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphConv2DAddFuser(FuseBase): class Conv2DAddFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphConv2DAddFuser, self).__init__(graph_type="dygraph") super(Conv2DAddFuser, self).__init__()
self.patterns = list() self.patterns = list()
def build_pattern(self): def build_pattern(self):
...@@ -42,11 +42,9 @@ class DygraphConv2DAddFuser(FuseBase): ...@@ -42,11 +42,9 @@ class DygraphConv2DAddFuser(FuseBase):
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
kernel="paddle.transpose", kernel="paddle.transpose",
inputs={"x": "conv-input-0"}, inputs={"x": "conv-input-0"},
...@@ -68,12 +66,10 @@ class DygraphConv2DAddFuser(FuseBase): ...@@ -68,12 +66,10 @@ class DygraphConv2DAddFuser(FuseBase):
outputs=[gen_name(3)]) outputs=[gen_name(3)])
pattern.build(inputs={"input-0": "conv-input-0", }) pattern.build(inputs={"input-0": "conv-input-0", })
self.patterns.append(pattern) self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
kernel="paddle.nn.Conv2D", kernel="paddle.nn.Conv2D",
inputs={"input": "conv-input-0"}, inputs={"input": "conv-input-0"},
...@@ -112,4 +108,3 @@ class DygraphConv2DAddFuser(FuseBase): ...@@ -112,4 +108,3 @@ class DygraphConv2DAddFuser(FuseBase):
if layer.kernel == "paddle.transpose": if layer.kernel == "paddle.transpose":
if conv_id in graph.edges_in[layer_id]: if conv_id in graph.edges_in[layer_id]:
layer.outputs[0] = output_name layer.outputs[0] = output_name
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphDropoutFuser from x2paddle.optimizer.fusion import DropoutFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphDropoutFusePass(Pass): class DropoutFusePass(Pass):
name = "dygraph_dropout_fuse_pass" name = "dropout_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphDropoutFuser() fuser = DropoutFuser()
fuser.operate(graph, match_kind="topo") fuser.operate(graph, match_kind="topo")
# 用于注册 # 用于注册
dropout_fuse_pass = DygraphDropoutFuser() dropout_fuse_pass = DropoutFuser()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphDropoutFuser(FuseBase): class DropoutFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphDropoutFuser, self).__init__(graph_type="dygraph") super(DropoutFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的constant图结构。 """ 描述需要替换的constant图结构。
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .adaptive_pool2d_fuser import DygraphAdaptivePool2dFuser
from .adaptive_pool2d_fuse_pass import DygraphAdaptivePool2dFusePass
from .batchnorm2d_fuser import DygraphBatchNorm2dFuser
from .batchnorm2d_fuse_pass import DygraphBatchNorm2dFusePass
from .bn_scale_fuser import DygraphBNScaleFuser
from .bn_scale_fuse_pass import DygraphBNScaleFusePass
from .constant_fuser import DygraphConstantFuser
from .constant_fuse_pass import DygraphConstantFusePass
from .conv2d_add_fuser import DygraphConv2DAddFuser
from .conv2d_add_fuse_pass import DygraphConv2DAddFusePass
from .dropout_fuser import DygraphDropoutFuser
from .dropout_fuse_pass import DygraphDropoutFusePass
from .fc_fuser import DygraphFcFuser
from .fc_fuse_pass import DygraphFcFusePass
from .if_fuser import DygraphIfFuser
from .if_fuse_pass import DygraphIfFusePass
from .interpolate_bilinear_fuser import DygraphInterpolateBilinearFuser
from .interpolate_bilinear_fuse_pass import DygraphInterpolateBilinearFusePass
from .prelu_fuser import DygraphPReLUFuser
from .prelu_fuse_pass import DygraphPReLUFusePass
from .reshape_fuser import DygraphReshapeFuser
from .reshape_fuse_pass import DygraphReshapeFusePass
from .tf_batchnorm_fuser import DygraphTFBatchNormFuser
from .tf_batchnorm_fuse_pass import DygraphTFBatchNormFusePass
from .trace_fc_fuser import TraceFcFuser
from .trace_fc_fuse_pass import TraceFcFusePass
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphAdaptivePool2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphAdaptivePool2dFusePass(Pass):
name = "dygraph_adaptive_pool2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphAdaptivePool2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
adaptive_pool2d_fuse_pass = DygraphAdaptivePool2dFusePass()
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphBatchNorm2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphBatchNorm2dFusePass(Pass):
name = "dygraph_batchnorm2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphBatchNorm2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
batchnorm2d_fuse_pass = DygraphBatchNorm2dFusePass()
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphConstantFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphConstantFusePass(Pass):
name = "dygraph_constant_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphConstantFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
constant_fuse_pass = DygraphConstantFuser()
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphConv2DAddFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphConv2DAddFusePass(Pass):
name = "dygraph_conv2d_add_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphConv2DAddFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
dygraph_conv2d_add_fuse_pass = DygraphConv2DAddFusePass()
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphInterpolateBilinearFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphInterpolateBilinearFusePass(Pass):
name = "dygraph_interpolate_bilinear_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphInterpolateBilinearFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
interpolate_bilinear_fuse_pass = DygraphInterpolateBilinearFusePass()
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphTFBatchNormFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphTFBatchNormFusePass(Pass):
name = "dygraph_tf_batchnorm_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphTFBatchNormFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
dygraph_tf_batchnorm_fuse_pass = DygraphTFBatchNormFusePass()
\ No newline at end of file
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphFcFuser from x2paddle.optimizer.fusion import FcFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphFcFusePass(Pass): class FcFusePass(Pass):
name = "dygraph_fc_fuse_pass" name = "fc_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphFcFuser() fuser = FcFuser()
fuser.operate(graph, match_kind="topo") fuser.operate(graph, match_kind="topo")
# 用于注册 # 用于注册
fc_fuse_pass = DygraphFcFusePass() fc_fuse_pass = FcFusePass()
...@@ -18,10 +18,10 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,10 +18,10 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphFcFuser(FuseBase): class FcFuser(FuseBase):
def __init__(self): def __init__(self):
self.linear_index = 0 self.linear_index = 0
super(DygraphFcFuser, self).__init__(graph_type="dygraph") super(FcFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的fc图结构。 """ 描述需要替换的fc图结构。
...@@ -48,8 +48,7 @@ class DygraphFcFuser(FuseBase): ...@@ -48,8 +48,7 @@ class DygraphFcFuser(FuseBase):
return "x" + str(id) return "x" + str(id)
self.pattern.add_layer( self.pattern.add_layer(
"prim.shape", "prim.shape", inputs={'input': "fc-input-0"},
inputs={'input': "fc-input-0"},
outputs=[gen_name(2)]) outputs=[gen_name(2)])
self.pattern.add_layer( self.pattern.add_layer(
"prim.len", inputs={'input': gen_name(2)}, outputs=[gen_name(2)]) "prim.len", inputs={'input': gen_name(2)}, outputs=[gen_name(2)])
...@@ -61,20 +60,16 @@ class DygraphFcFuser(FuseBase): ...@@ -61,20 +60,16 @@ class DygraphFcFuser(FuseBase):
self.pattern.add_layer("prim.if", {'input': gen_name(3)}, [gen_name(4)]) self.pattern.add_layer("prim.if", {'input': gen_name(3)}, [gen_name(4)])
self.pattern.outputs.append(gen_name(4)) self.pattern.outputs.append(gen_name(4))
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]] if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph") pattern_block0 = PaddleGraph(parent_layer=if_layer1)
pattern_block0.add_layer( pattern_block0.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(5)])
inputs={},
outputs=[gen_name(5)])
pattern_block0.add_layer( pattern_block0.add_layer(
"paddle.transpose", "paddle.transpose",
inputs={"x": gen_name(5)}, inputs={"x": gen_name(5)},
outputs=[gen_name(6)], outputs=[gen_name(6)],
perm=[1, 0]) perm=[1, 0])
pattern_block0.add_layer( pattern_block0.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(7)])
inputs={},
outputs=[gen_name(7)])
pattern_block0.add_layer( pattern_block0.add_layer(
"paddle.addmm", "paddle.addmm",
inputs={"input": gen_name(7), inputs={"input": gen_name(7),
...@@ -88,11 +83,9 @@ class DygraphFcFuser(FuseBase): ...@@ -88,11 +83,9 @@ class DygraphFcFuser(FuseBase):
pattern_block0.add_layer( pattern_block0.add_layer(
"prim.equal", inputs={'input': gen_name(8)}, outputs=[gen_name(4)]) "prim.equal", inputs={'input': gen_name(8)}, outputs=[gen_name(4)])
if_layer1.add_block(pattern_block0) if_layer1.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph") pattern_block1 = PaddleGraph(parent_layer=if_layer1)
pattern_block1.add_layer( pattern_block1.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(5)])
inputs={},
outputs=[gen_name(5)])
pattern_block1.add_layer( pattern_block1.add_layer(
"paddle.transpose", "paddle.transpose",
inputs={"x": gen_name(5)}, inputs={"x": gen_name(5)},
...@@ -105,9 +98,7 @@ class DygraphFcFuser(FuseBase): ...@@ -105,9 +98,7 @@ class DygraphFcFuser(FuseBase):
outputs=[gen_name(9)]) outputs=[gen_name(9)])
if_layer1.inputs["input-1"] = "fc-input-0" if_layer1.inputs["input-1"] = "fc-input-0"
pattern_block1.add_layer( pattern_block1.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(12)])
inputs={},
outputs=[gen_name(12)])
pattern_block1.add_layer( pattern_block1.add_layer(
"prim.add_", "prim.add_",
inputs={"x": gen_name(9), inputs={"x": gen_name(9),
......
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphIfFuser from x2paddle.optimizer.fusion import IfFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphIfFusePass(Pass): class IfFusePass(Pass):
name = "dygraph_if_fuse_pass" name = "if_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphIfFuser() fuser = IfFuser()
fuser.operate(graph, match_kind="op") fuser.operate(graph, match_kind="op")
# 用于注册 # 用于注册
if_fuse_pass = DygraphIfFuser() if_fuse_pass = IfFuser()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphIfFuser(FuseBase): class IfFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphIfFuser, self).__init__(graph_type="dygraph") super(IfFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的if图结构。 """ 描述需要替换的if图结构。
...@@ -38,7 +38,7 @@ class DygraphIfFuser(FuseBase): ...@@ -38,7 +38,7 @@ class DygraphIfFuser(FuseBase):
layer = list(matches.values())[0] layer = list(matches.values())[0]
if "input" not in layer.inputs: if "input" not in layer.inputs:
matches.pop(layer_id) matches.pop(layer_id)
return return
for id in graph.edges_in[layer_id]: for id in graph.edges_in[layer_id]:
input_layer = graph.layers[id] input_layer = graph.layers[id]
input_layer_id = id input_layer_id = id
...@@ -56,11 +56,11 @@ class DygraphIfFuser(FuseBase): ...@@ -56,11 +56,11 @@ class DygraphIfFuser(FuseBase):
if func_name in ["prim_if", "prim_loop"]: if func_name in ["prim_if", "prim_loop"]:
matches.pop(layer_id) matches.pop(layer_id)
return return
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim2code from x2paddle.op_mapper.pytorch2paddle import prim2code
func = getattr(prim2code, func_name) func = getattr(prim2code, func_name)
line = func(input_layer, is_return_line=True) line = func(input_layer, is_return_line=True)
layer.attrs["input"] = line layer.attrs["input"] = line
layer.inputs.pop("input") layer.inputs.pop("input")
matches.pop(layer_id) matches.pop(layer_id)
if len(input_layer.outputs) == 1: if len(input_layer.outputs) == 1:
matches[input_id] = input_layer matches[input_id] = input_layer
\ No newline at end of file
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphBNScaleFuser from x2paddle.optimizer.fusion import InterpolateBilinearFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphBNScaleFusePass(Pass): class InterpolateBilinearFusePass(Pass):
name = "dygraph_bn_scale_fuse_pass" name = "interpolate_bilinear_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphBNScaleFuser() fuser = InterpolateBilinearFuser()
fuser.operate(graph, match_kind="topo") fuser.operate(graph, match_kind="topo")
# 用于注册 # 用于注册
bn_scale_fuse_pass = DygraphBNScaleFusePass() interpolate_bilinear_fuse_pass = InterpolateBilinearFusePass()
...@@ -19,9 +19,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -19,9 +19,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphInterpolateBilinearFuser(FuseBase): class InterpolateBilinearFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphInterpolateBilinearFuser, self).__init__(graph_type="dygraph") super(InterpolateBilinearFuser, self).__init__()
self.pattenrs = list() self.pattenrs = list()
def build_pattern(self): def build_pattern(self):
...@@ -66,29 +66,22 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -66,29 +66,22 @@ class DygraphInterpolateBilinearFuser(FuseBase):
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"prim.shape", "prim.shape",
inputs={"input": "interpolate-input-0"}, inputs={"input": "interpolate-input-0"},
outputs=[gen_name(9)]) outputs=[gen_name(9)])
pattern.add_layer( pattern.add_layer(
"prim.len", "prim.len", inputs={"input": gen_name(9)}, outputs=[gen_name(9)])
inputs={"input": gen_name(9)},
outputs=[gen_name(9)])
pattern.add_layer(
"prim.sub",
inputs={"x": gen_name(9)},
outputs=[gen_name(10)],
y=2)
pattern.add_layer( pattern.add_layer(
"prim.list", inputs={}, outputs=[gen_name(11)]) "prim.sub", inputs={"x": gen_name(9)}, outputs=[gen_name(10)], y=2)
pattern.add_layer("prim.list", inputs={}, outputs=[gen_name(11)])
pattern.add_layer( pattern.add_layer(
"prim.loop", "prim.loop",
inputs={"input": gen_name(10)}, inputs={"input": gen_name(10)},
outputs=[gen_name(12.1), gen_name(12.2)]) outputs=[gen_name(12.1), gen_name(12.2)])
loop_layer = pattern.layers[list(pattern.layers.keys())[ loop_layer = pattern.layers[list(pattern.layers.keys())[-1]]
-1]] pattern_block = PaddleGraph(loop_layer)
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block.add_layer( pattern_block.add_layer(
"prim.append", "prim.append",
inputs={"list": gen_name(11)}, inputs={"list": gen_name(11)},
...@@ -113,12 +106,10 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -113,12 +106,10 @@ class DygraphInterpolateBilinearFuser(FuseBase):
y=3) y=3)
pattern.add_layer( pattern.add_layer(
"prim.if", "prim.if", inputs={"input": gen_name(10.1)},
inputs={"input": gen_name(10.1)},
outputs=[gen_name(14)]) outputs=[gen_name(14)])
if_layer1 = pattern.layers[list(pattern.layers.keys())[ if_layer1 = pattern.layers[list(pattern.layers.keys())[-1]]
-1]] pattern_block = PaddleGraph(parent_layer=if_layer1)
pattern_block = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block.add_layer( pattern_block.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
...@@ -127,29 +118,20 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -127,29 +118,20 @@ class DygraphInterpolateBilinearFuser(FuseBase):
pattern_block.add_layer( pattern_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(14)], input=None) "prim.equal", inputs={}, outputs=[gen_name(14)], input=None)
if_layer1.add_block(pattern_block) if_layer1.add_block(pattern_block)
pattern_block = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph") pattern_block = PaddleGraph(parent_layer=if_layer1)
pattern_block.add_layer( pattern_block.add_layer(
"prim.shape", "prim.shape",
inputs={"input": "interpolate-input-0"}, inputs={"input": "interpolate-input-0"},
outputs=[gen_name(18)]) outputs=[gen_name(18)])
pattern_block.add_layer( pattern_block.add_layer(
"prim.len", "prim.len", inputs={"input": gen_name(18)}, outputs=[gen_name(18)])
inputs={"input": gen_name(18)},
outputs=[gen_name(18)])
pattern_block.add_layer( pattern_block.add_layer(
"prim.eq", "prim.eq", inputs={"x": gen_name(18)}, outputs=[gen_name(19)], y=4)
inputs={"x": gen_name(18)},
outputs=[gen_name(19)],
y=4)
pattern_block.add_layer( pattern_block.add_layer(
"prim.if", "prim.if", inputs={"input": gen_name(19)}, outputs=[gen_name(20)])
inputs={"input": gen_name(19)}, if_layer2 = pattern_block.layers[list(pattern_block.layers.keys())[-1]]
outputs=[gen_name(20)]) pattern_block_block = PaddleGraph(parent_layer=if_layer2)
if_layer2 = pattern_block.layers[list(pattern_block.layers.keys())[
-1]]
pattern_block_block = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph")
pattern_block_block.add_layer( pattern_block_block.add_layer(
"prim.getitem", "prim.getitem",
inputs={"list": gen_name(11)}, inputs={"list": gen_name(11)},
...@@ -170,15 +152,13 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -170,15 +152,13 @@ class DygraphInterpolateBilinearFuser(FuseBase):
outputs=["interpolate-input-0_if1"]) outputs=["interpolate-input-0_if1"])
if_layer_isinstance = pattern_block_block.layers[list( if_layer_isinstance = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]] pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph( pattern_block_block_block = PaddleGraph(if_layer_isinstance)
if_layer_isinstance, graph_type="dygraph")
pattern_block_block_block.add_layer( pattern_block_block_block.add_layer(
"prim.var2list", "prim.var2list",
inputs={"input": "interpolate-input-3"}, inputs={"input": "interpolate-input-3"},
outputs=["interpolate-input-3"]) outputs=["interpolate-input-3"])
if_layer_isinstance.add_block(pattern_block_block_block) if_layer_isinstance.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph( pattern_block_block_block = PaddleGraph(if_layer_isinstance)
if_layer_isinstance, graph_type="dygraph")
if_layer_isinstance.add_block(pattern_block_block_block) if_layer_isinstance.add_block(pattern_block_block_block)
if_layer_isinstance.inputs["input-0"] = "interpolate-input-3" if_layer_isinstance.inputs["input-0"] = "interpolate-input-3"
pattern_block_block.add_layer( pattern_block_block.add_layer(
...@@ -193,36 +173,27 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -193,36 +173,27 @@ class DygraphInterpolateBilinearFuser(FuseBase):
inputs={"input": gen_name(23)}, inputs={"input": gen_name(23)},
outputs=[gen_name(20)]) outputs=[gen_name(20)])
if_layer2.add_block(pattern_block_block) if_layer2.add_block(pattern_block_block)
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph") pattern_block_block = PaddleGraph(if_layer2)
pattern_block_block.add_layer( pattern_block_block.add_layer(
"prim.shape", "prim.shape",
inputs={"input": "interpolate-input-0"}, inputs={"input": "interpolate-input-0"},
outputs=[gen_name(24)]) outputs=[gen_name(24)])
pattern_block_block.add_layer( pattern_block_block.add_layer(
"prim.len", "prim.len", inputs={"input": gen_name(24)}, outputs=[gen_name(24)])
inputs={"input": gen_name(24)},
outputs=[gen_name(24)])
pattern_block_block.add_layer( pattern_block_block.add_layer(
"prim.eq", "prim.eq", inputs={"x": gen_name(24)}, outputs=[gen_name(25)], y=5)
inputs={"x": gen_name(24)},
outputs=[gen_name(25)],
y=5)
pattern_block_block.add_layer( pattern_block_block.add_layer(
"prim.if", "prim.if", inputs={"input": gen_name(25)}, outputs=[gen_name(26)])
inputs={"input": gen_name(25)},
outputs=[gen_name(26)])
if_layer3 = pattern_block_block.layers[list( if_layer3 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]] pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph( pattern_block_block_block = PaddleGraph(parent_layer=if_layer3)
parent_layer=if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer( pattern_block_block_block.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
outputs=[gen_name(27)], outputs=[gen_name(27)],
input="Exception") input="Exception")
if_layer3.add_block(pattern_block_block_block) if_layer3.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph( pattern_block_block_block = PaddleGraph(parent_layer=if_layer3)
parent_layer=if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer( pattern_block_block_block.add_layer(
"prim.exception", "prim.exception",
inputs={}, inputs={},
...@@ -245,11 +216,11 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -245,11 +216,11 @@ class DygraphInterpolateBilinearFuser(FuseBase):
outputs=[gen_name(14)]) outputs=[gen_name(14)])
if_layer1.add_block(pattern_block) if_layer1.add_block(pattern_block)
if_layer1.inputs.update({ if_layer1.inputs.update({
'input-2': 'interpolate-input-0', 'input-2': 'interpolate-input-0',
'input-4': gen_name(11), 'input-4': gen_name(11),
'input-6': gen_name(11), 'input-6': gen_name(11),
'input-8': 'interpolate-input-0', 'input-8': 'interpolate-input-0',
'input-9': 'interpolate-input-3', 'input-9': 'interpolate-input-3',
'input-10': 'interpolate-input-0' 'input-10': 'interpolate-input-0'
}) })
pattern.build(inputs={ pattern.build(inputs={
...@@ -260,8 +231,6 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -260,8 +231,6 @@ class DygraphInterpolateBilinearFuser(FuseBase):
"input-4": "interpolate-input-4" "input-4": "interpolate-input-4"
}) })
self.patterns.append(pattern) self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches) new_layer = self.gen_new_layer(parameters, matches)
...@@ -282,7 +251,6 @@ class DygraphInterpolateBilinearFuser(FuseBase): ...@@ -282,7 +251,6 @@ class DygraphInterpolateBilinearFuser(FuseBase):
matches.clear() matches.clear()
for layer_id, layer in new_matches.items(): for layer_id, layer in new_matches.items():
matches[layer_id] = layer matches[layer_id] = layer
def gen_new_layer(self, parameters, matches): def gen_new_layer(self, parameters, matches):
layers = list() layers = list()
......
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.static import StaticPReLUFuser from x2paddle.optimizer.fusion import PReLUFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class StaticPReLUFusePass(Pass): class PReLUFusePass(Pass):
name = "static_prelu_fuse_pass" name = "prelu_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = StaticPReLUFuser() fuser = PReLUFuser()
fuser.operate(graph, match_kind="edge") fuser.operate(graph, match_kind="edge")
# 用于注册 # 用于注册
static_prelu_fuse_pass = StaticPReLUFusePass() prelu_fuse_pass = PReLUFusePass()
\ No newline at end of file
...@@ -20,10 +20,10 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -20,10 +20,10 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphPReLUFuser(FuseBase): class PReLUFuser(FuseBase):
def __init__(self): def __init__(self):
self.prelu_index = 0 self.prelu_index = 0
super(DygraphPReLUFuser, self).__init__(graph_type="dygraph") super(PReLUFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的prelu图结构。 """ 描述需要替换的prelu图结构。
...@@ -42,9 +42,7 @@ class DygraphPReLUFuser(FuseBase): ...@@ -42,9 +42,7 @@ class DygraphPReLUFuser(FuseBase):
return "x" + str(id) return "x" + str(id)
self.pattern.add_layer( self.pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
self.pattern.add_layer( self.pattern.add_layer(
"paddle.full", "paddle.full",
inputs={}, inputs={},
...@@ -56,9 +54,7 @@ class DygraphPReLUFuser(FuseBase): ...@@ -56,9 +54,7 @@ class DygraphPReLUFuser(FuseBase):
inputs={"x": "prelu-input-0"}, inputs={"x": "prelu-input-0"},
outputs=[gen_name(2)]) outputs=[gen_name(2)])
self.pattern.add_layer( self.pattern.add_layer(
"paddle.abs", "paddle.abs", inputs={"x": "prelu-input-0"}, outputs=[gen_name(3)])
inputs={"x": "prelu-input-0"},
outputs=[gen_name(3)])
self.pattern.add_layer( self.pattern.add_layer(
"paddle.subtract", "paddle.subtract",
inputs={"x": "prelu-input-0", inputs={"x": "prelu-input-0",
...@@ -80,10 +76,10 @@ class DygraphPReLUFuser(FuseBase): ...@@ -80,10 +76,10 @@ class DygraphPReLUFuser(FuseBase):
"y": gen_name(6)}, "y": gen_name(6)},
outputs=[gen_name(7)]) outputs=[gen_name(7)])
self.pattern.build(inputs={"input-0": "prelu-input-0", }) self.pattern.build(inputs={"input-0": "prelu-input-0", })
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph) new_layers, last_layer_id = self.gen_new_layer(matches, parameters,
graph)
matches_copy = copy.deepcopy(matches) matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items(): for layer_id, layer in matches_copy.items():
for i in range(3): for i in range(3):
...@@ -108,7 +104,7 @@ class DygraphPReLUFuser(FuseBase): ...@@ -108,7 +104,7 @@ class DygraphPReLUFuser(FuseBase):
def gen_new_layer(self, matches, parameters, graph): def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys()) layer_id_list = list(matches.keys())
layer_id_list.sort(key = int) layer_id_list.sort(key=int)
for layer_id, layer in matches.items(): for layer_id, layer in matches.items():
if layer.kernel == "paddle.nn.ReLU": if layer.kernel == "paddle.nn.ReLU":
input_name = layer.inputs["x"] input_name = layer.inputs["x"]
...@@ -126,12 +122,13 @@ class DygraphPReLUFuser(FuseBase): ...@@ -126,12 +122,13 @@ class DygraphPReLUFuser(FuseBase):
self.prelu_index += 1 self.prelu_index += 1
param = parameters[param_name] param = parameters[param_name]
c = param.shape[0] c = param.shape[0]
prelu = PaddleLayer(id=layer_id_list[-1] + "_2", prelu = PaddleLayer(
kernel="paddle.nn.PReLU", id=layer_id_list[-1] + "_2",
inputs={"input": "{}_transpose_for_prelu".format(input_name)}, kernel="paddle.nn.PReLU",
outputs=[prelu_name, "{}_prelu".format(input_name)], inputs={"input": "{}_transpose_for_prelu".format(input_name)},
num_parameters=c, outputs=[prelu_name, "{}_prelu".format(input_name)],
weight_attr=string(param_name)) num_parameters=c,
weight_attr=string(param_name))
transpose1 = PaddleLayer( transpose1 = PaddleLayer(
id=layer_id_list[-1] + "_3", id=layer_id_list[-1] + "_3",
kernel="paddle.transpose", kernel="paddle.transpose",
...@@ -139,4 +136,3 @@ class DygraphPReLUFuser(FuseBase): ...@@ -139,4 +136,3 @@ class DygraphPReLUFuser(FuseBase):
outputs=[output_name], outputs=[output_name],
perm=[0, 2, 3, 1]) perm=[0, 2, 3, 1])
return [transpose0, prelu, transpose1], layer_id_list[-1] return [transpose0, prelu, transpose1], layer_id_list[-1]
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphReshapeFuser from x2paddle.optimizer.fusion import ReshapeFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class DygraphReshapeFusePass(Pass): class ReshapeFusePass(Pass):
name = "dygraph_reshape_fuse_pass" name = "reshape_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = DygraphReshapeFuser() fuser = ReshapeFuser()
fuser.operate(graph, match_kind="edge") fuser.operate(graph, match_kind="edge")
# 用于注册 # 用于注册
reshape_fuse_pass = DygraphReshapeFusePass() reshape_fuse_pass = ReshapeFusePass()
...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -18,9 +18,9 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphReshapeFuser(FuseBase): class ReshapeFuser(FuseBase):
def __init__(self): def __init__(self):
super(DygraphReshapeFuser, self).__init__(graph_type="dygraph") super(ReshapeFuser, self).__init__()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的reshape图结构。 """ 描述需要替换的reshape图结构。
......
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from .bn_scale_fuser import Static_BNScaleFuser
from .bn_scale_fuse_pass import Static_BNScaleFusePass
from .conv2d_add_fuser import StaticConv2DAddFuser
from .conv2d_add_fuse_pass import StaticConv2DAddFusePass
from .prelu_fuser import StaticPReLUFuser
from .prelu_fuse_pass import StaticPReLUFusePass
from .tf_batchnorm_fuser import StaticTFBatchNormFuser
from .tf_batchnorm_fuse_pass import StaticTFBatchNormFusePass
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class Static_BNScaleFuser(FuseBase):
def __init__(self):
super(Static_BNScaleFuser, self).__init__(graph_type="static")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的batchnorm2d图结构。
batchnorm2d层模式python实现代码示例:
模式一:
conv1_bn_mean = paddle.static.create_parameter(shape=(128,), dtype='float32', name='conv1_bn_mean')
conv1_bn_variance = paddle.static.create_parameter(shape=(128,), dtype='float32', name='conv1_bn_variance')
conv1_bn = paddle.nn.functional.batch_norm(x=conv1, weight=conv1_bn_weight, bias=conv1_bn_bias, running_mean=conv1_bn_mean, running_var=conv1_bn_variance, epsilon=9.999999747378752e-06, momentum=0.9990000128746033)
conv1_scale_cparam1 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam1')
conv1_scale_mul = paddle.multiply(x=conv1_bn, y=conv1_scale_cparam1, axis=1)
conv1_scale_cparam2 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam2')
conv1_scale_cparam2 = paddle.reshape(x=conv1_scale_cparam2, shape=[32, 1, 1])
conv1_scale = paddle.add(x=conv1_scale_mul, y=conv1_scale_cparam2)
模式二:
conv1_bn_mean = paddle.static.create_parameter(shape=(128,), dtype='float32', name='conv1_bn_mean')
conv1_bn_variance = paddle.static.create_parameter(shape=(128,), dtype='float32', name='conv1_bn_variance')
conv1_bn = paddle.nn.functional.batch_norm(x=conv1, weight=conv1_bn_weight, bias=conv1_bn_bias, running_mean=conv1_bn_mean, running_var=conv1_bn_variance, epsilon=9.999999747378752e-06, momentum=0.9990000128746033)
conv1_scale_cparam1 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam1')
conv1_scale_mul = paddle.multiply(x=conv1_bn, y=conv1_scale_cparam1, axis=1)
conv1_scale_cparam2 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam2')
conv1_scale = paddle.add(x=conv1_scale_mul, y=conv1_scale_cparam2)
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(10)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(11)])
pattern.add_layer(
"paddle.nn.functional.batch_norm",
inputs={"input": "bn-input-0",
"weight": "bn-input-1",
"bias": "bn-input-2",
"running_mean": gen_name(10),
"running_var": gen_name(11)},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(1)])
inputs_dict = {}
inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(1)
pattern.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(3)])
pattern.add_layer(
"paddle.reshape",
inputs={"x": gen_name(3)},
outputs=[gen_name(4)])
inputs_dict = {}
inputs_dict['x'] = gen_name(2)
inputs_dict['y'] = gen_name(4)
pattern.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[gen_name(5)])
pattern.build(inputs={"input-0": "bn-input-0",
"input-1": "bn-input-1",
"input-2": "bn-input-2"})
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(10)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(11)])
pattern.add_layer(
"paddle.nn.functional.batch_norm",
inputs={"input": "bn-input-0",
"weight": "bn-input-1",
"bias": "bn-input-2",
"running_mean": gen_name(10),
"running_var": gen_name(11),},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(1)])
inputs_dict = {}
inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(1)
pattern.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(3)])
inputs_dict = {}
inputs_dict['x'] = gen_name(2)
inputs_dict['y'] = gen_name(3)
pattern.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[gen_name(4)])
pattern.build(inputs={"input-0": "bn-input-0",
"input-1": "bn-input-1",
"input-2": "bn-input-2"})
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches)
new_layer_id = list(matches.keys())[-1]
graph.layers[new_layer_id] = new_layer
matches.pop(list(matches.keys())[0])
matches.pop(list(matches.keys())[0])
matches.pop(list(matches.keys())[1])
matches.pop(list(matches.keys())[2])
matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
bn_layer = matches[layers_id[2]]
layer = matches[layers_id[3]]
bn_layer.inputs["weight"] = layer.outputs[0]
layer = matches[layers_id[5]]
bn_layer.inputs["bias"] = layer.outputs[0]
bn_layer.id = layers_id[-1]
layer = matches[layers_id[-1]]
bn_layer.outputs = layer.outputs
return bn_layer
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import copy
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class StaticConv2DAddFuser(FuseBase):
def __init__(self):
super(StaticConv2DAddFuser, self).__init__(graph_type="static")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的conv2d+add图结构。
conv2d+add层模式python实现代码示例:
模式一:
MobilenetV1_Logits_Conv2d_1c_1x1_biases = paddle.static.create_parameter(dtype='float32', shape=[1001], name='MobilenetV1_Logits_Conv2d_1c_1x1_biases', default_initializer=paddle.nn.initializer.Constant(value=0.0))
conv2d_transpose_14 = paddle.transpose(x=MobilenetV1_Logits_AvgPool_1a_AvgPool, perm=[0, 3, 1, 2])
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = paddle.nn.functional.conv2d(x=conv2d_transpose_14, weight=MobilenetV1_Logits_Conv2d_1c_1x1_weights, bias=None, stride=[1, 1], dilation=[1, 1], padding='SAME')
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = paddle.transpose(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, perm=[0, 2, 3, 1])
MobilenetV1_Logits_Conv2d_1c_1x1_BiasAdd = paddle.add(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, y=MobilenetV1_Logits_Conv2d_1c_1x1_biases)
模式二:
MobilenetV1_Logits_Conv2d_1c_1x1_biases = paddle.static.create_parameter(dtype='float32', shape=[1001], name='MobilenetV1_Logits_Conv2d_1c_1x1_biases', default_initializer=paddle.nn.initializer.Constant(value=0.0))
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = paddle.nn.functional.conv2d(x=conv2d_transpose_14, weight=MobilenetV1_Logits_Conv2d_1c_1x1_weights, bias=None, stride=[1, 1], dilation=[1, 1], padding='SAME')
MobilenetV1_Logits_Conv2d_1c_1x1_BiasAdd = paddle.add(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, y=MobilenetV1_Logits_Conv2d_1c_1x1_biases)
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
kernel="paddle.transpose",
inputs={"x": "conv-input-0"},
outputs=[gen_name(1)],
perm=[0, 3, 1, 2])
pattern.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs={"input": gen_name(1),
"weight": "conv-input-1"},
outputs=[gen_name(2)])
pattern.add_layer(
kernel="paddle.transpose",
inputs={"x": gen_name(2)},
outputs=[gen_name(2)],
perm=[0, 2, 3, 1])
pattern.add_layer(
kernel="paddle.add",
inputs={"x": gen_name(2),
"y": gen_name(0)},
outputs=[gen_name(3)])
pattern.build(inputs={"input-0": "conv-input-0",
"input-1": "conv-input-1"})
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
kernel="paddle.nn.functional.conv2d",
inputs={"input": "conv-input-0",
"weight": "conv-input-1"},
outputs=[gen_name(1)])
pattern.add_layer(
kernel="paddle.add",
inputs={"x": gen_name(1),
"y": gen_name(0)},
outputs=[gen_name(2)])
pattern.build(inputs={"input-0": "conv-input-0",
"input-1": "conv-input-1"})
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
self.gen_new_layer(matches, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
if layer.kernel not in ["paddle.add"]:
matches.pop(layer_id)
def gen_new_layer(self, matches, graph):
is_transpose = False
for layer_id, layer in matches.items():
if layer.kernel == "paddle.static.create_parameter":
bias_name = layer.attrs["name"][1: -1]
if layer.kernel == "paddle.transpose":
is_transpose = True
if layer.kernel == "paddle.add":
output_name = layer.outputs[0]
if layer.kernel == "paddle.nn.functional.conv2d":
conv_id = layer_id
for layer_id, layer in matches.items():
if layer.kernel == "paddle.nn.functional.conv2d":
layer.inputs["bias"] = bias_name
layer.attrs.pop("bias")
if not is_transpose:
layer.outputs[0] = output_name
if layer.kernel == "paddle.transpose":
if conv_id in graph.edges_in[layer_id]:
layer.outputs[0] = output_name
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import copy
import numpy as np
from collections import OrderedDict
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class StaticPReLUFuser(FuseBase):
def __init__(self):
super(StaticPReLUFuser, self).__init__(graph_type="static")
def build_pattern(self):
""" 描述需要替换的prelu图结构。
prelu层模式python实现代码示例:
conv4_alphas = paddle.static.create_parameter(dtype='float32', shape=[128], name='conv4_alphas', default_initializer=paddle.nn.initializer.Constant(value=0.0))
conv4_mul_1_y = paddle.full(dtype='float32', shape=[1], fill_value=0.5)
conv4_Relu = paddle.nn.functional.relu(x=conv4_BiasAdd)
conv4_Abs = paddle.abs(x=conv4_BiasAdd)
conv4_sub = paddle.subtract(x=conv4_BiasAdd, y=conv4_Abs)
conv4_mul = paddle.multiply(x=conv4_alphas, y=conv4_sub)
conv4_mul_1 = paddle.multiply(x=conv4_mul, y=conv4_mul_1_y)
conv4_add = paddle.add(x=conv4_Relu, y=conv4_mul_1)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(0)])
self.pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1],
fill_value=0.5)
self.pattern.add_layer(
"paddle.nn.functional.relu",
inputs={"x": "prelu-input-0"},
outputs=[gen_name(2)])
self.pattern.add_layer(
"paddle.abs",
inputs={"x": "prelu-input-0"},
outputs=[gen_name(3)])
self.pattern.add_layer(
"paddle.subtract",
inputs={"x": "prelu-input-0",
"y": gen_name(3)},
outputs=[gen_name(4)])
self.pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(0),
"y": gen_name(4)},
outputs=[gen_name(5)])
self.pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(5),
"y": gen_name(1)},
outputs=[gen_name(6)])
self.pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(2),
"y": gen_name(6)},
outputs=[gen_name(7)])
self.pattern.build(inputs={"input-0": "prelu-input-0", })
def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
for i in range(4):
if layer_id == new_layers[i].id:
matches.pop(new_layers[i].id)
prefix_layers = OrderedDict()
mid_layers = OrderedDict()
suffix_layers = OrderedDict()
is_need_id = False
for layer_id, layer in graph.layers.items():
if is_need_id:
suffix_layers[layer_id] = layer
else:
if layer_id == last_layer_id:
for i in range(4):
mid_layers[new_layers[i].id] = new_layers[i]
is_need_id = True
prefix_layers[layer_id] = layer
prefix_layers.update(mid_layers)
prefix_layers.update(suffix_layers)
graph.layers = prefix_layers
def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys())
layer_id_list.sort(key = int)
for layer_id, layer in matches.items():
if layer.kernel == "paddle.nn.functional.relu":
input_name = layer.inputs["x"]
if layer.kernel == "paddle.static.create_parameter":
param_layer = layer
param_name = layer.outputs[0]
if layer.kernel == "paddle.add":
output_name = layer.outputs[0]
transpose0 = PaddleLayer(
id=layer_id_list[-1] + "_1",
kernel="paddle.transpose",
inputs={"x": input_name},
outputs=["{}_transpose_for_prelu".format(input_name)],
perm=[0, 3, 1, 2])
param = parameters[param_name]
c = param.shape[0]
prelu = PaddleLayer(id=layer_id_list[-1] + "_2",
kernel="paddle.nn.functional.prelu",
inputs={"x": "{}_transpose_for_prelu".format(input_name),
"weight": param_name},
outputs=["{}_prelu".format(input_name)])
transpose1 = PaddleLayer(
id=layer_id_list[-1] + "_3",
kernel="paddle.transpose",
inputs={"x": "{}_prelu".format(input_name)},
outputs=[output_name],
perm=[0, 2, 3, 1])
return [param_layer, transpose0, prelu, transpose1], layer_id_list[-1]
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.static import StaticTFBatchNormFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class StaticTFBatchNormFusePass(Pass):
name = "static_tf_batchnorm_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = StaticTFBatchNormFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
static_tf_batchnorm_fuse_pass = StaticTFBatchNormFusePass()
\ No newline at end of file
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
import copy
import numpy as np
from collections import OrderedDict
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class StaticTFBatchNormFuser(FuseBase):
def __init__(self):
super(StaticTFBatchNormFuser, self).__init__(graph_type="static")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的batchnorm图结构。
batchnorm层模式python实现代码示例:
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.rsqrt",
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(4)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)},
outputs=[gen_name(5)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(6)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)},
outputs=[gen_name(7)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(8)])
pattern.add_layer(
"paddle.subtract",
inputs={"x": gen_name(8), "y": gen_name(7)},
outputs=[gen_name(9)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)},
outputs=[gen_name(10)])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)},
outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.rsqrt",
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(4)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)},
outputs=[gen_name(5)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)},
outputs=[gen_name(10)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(6)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)},
outputs=[gen_name(7)])
pattern.add_layer(
"paddle.static.create_parameter",
inputs={},
outputs=[gen_name(8)])
pattern.add_layer(
"paddle.subtract",
inputs={"x": gen_name(8), "y": gen_name(7)},
outputs=[gen_name(9)])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)},
outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
for i in range(7):
if layer_id == new_layers[i].id:
matches.pop(new_layers[i].id)
prefix_layers = OrderedDict()
mid_layers = OrderedDict()
suffix_layers = OrderedDict()
is_need_id = False
for layer_id, layer in graph.layers.items():
if is_need_id:
suffix_layers[layer_id] = layer
else:
if layer_id == last_layer_id:
for i in range(7):
mid_layers[new_layers[i].id] = new_layers[i]
is_need_id = True
prefix_layers[layer_id] = layer
prefix_layers.update(mid_layers)
prefix_layers.update(suffix_layers)
graph.layers = prefix_layers
def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys())
layer_id_list.sort(key = int)
for layer_id, layer in matches.items():
if layer.kernel == "paddle.full":
full_layer = layer
out_layer_id = graph.edges_out[layer_id][0]
if matches[out_layer_id].kernel == "paddle.add":
var_layer_id = graph.edges_in[out_layer_id][0]
var_layer = matches[var_layer_id]
if layer.kernel == "paddle.rsqrt":
out_layer_id = graph.edges_out[layer_id][0]
if matches[out_layer_id].kernel == "paddle.multiply":
gamma_layer_id = graph.edges_in[out_layer_id][1]
gamma_layer = matches[gamma_layer_id]
if layer.kernel == "paddle.subtract":
in_layer_id = graph.edges_in[layer_id][0]
beta_layer = matches[in_layer_id]
in_layer_id = graph.edges_in[layer_id][1]
in_layer_id = graph.edges_in[in_layer_id][0]
mean_layer = matches[in_layer_id]
out_layer_id = graph.edges_out[layer_id][0]
add_layer = matches[out_layer_id]
if layer.kernel == "paddle.multiply":
in_layer_id = graph.edges_in[layer_id][1]
mul_layer = matches[in_layer_id]
if mul_layer.kernel == "paddle.multiply":
in_layer_id = graph.edges_in[layer_id][0]
if in_layer_id not in matches:
input_name = layer.inputs["x"]
transpose0 = PaddleLayer(
id=layer_id_list[-1] + "_1",
kernel="paddle.transpose",
inputs={"x": input_name},
outputs=["{}_transpose_for_bn".format(input_name)],
perm=[0, 3, 1, 2])
params = parameters[gamma_layer.outputs[0]]
c = params.shape[0]
bn = PaddleLayer(
id=layer_id_list[-1] + "_2",
kernel="paddle.nn.functional.batch_norm",
inputs={"x": "{}_transpose_for_bn".format(input_name),
"running_mean": mean_layer.outputs[0],
"running_var": var_layer.outputs[0],
"weight": gamma_layer.outputs[0],
"bias": beta_layer.outputs[0]},
outputs=["{}_bn".format(input_name)],
epsilon=full_layer.attrs["fill_value"])
transpose1 = PaddleLayer(
id=layer_id_list[-1] + "_3",
kernel="paddle.transpose",
inputs={"x": "{}_bn".format(input_name)},
outputs=add_layer.outputs,
perm=[0, 2, 3, 1])
mean_layer.id = layer_id_list[-1] + "_01"
var_layer.id = layer_id_list[-1] + "_02"
gamma_layer.id = layer_id_list[-1] + "_03"
beta_layer.id = layer_id_list[-1] + "_04"
return [mean_layer, var_layer, gamma_layer, beta_layer,
transpose0, bn, transpose1], layer_id_list[-1]
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.static import StaticConv2DAddFuser from x2paddle.optimizer.fusion import TFBatchNormFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
@pass_register @pass_register
class StaticConv2DAddFusePass(Pass): class TFBatchNormFusePass(Pass):
name = "static_conv2d_add_fuse_pass" name = "tf_batchnorm_fuse_pass"
def __init__(self): def __init__(self):
Pass.__init__(self) Pass.__init__(self)
def apply(self, graph): def apply(self, graph):
fuser = StaticConv2DAddFuser() fuser = TFBatchNormFuser()
fuser.operate(graph, match_kind="edge") fuser.operate(graph, match_kind="edge")
# 用于注册 # 用于注册
static_conv2d_add_fuse_pass = StaticConv2DAddFusePass() tf_batchnorm_fuse_pass = TFBatchNormFusePass()
\ No newline at end of file
...@@ -20,129 +20,116 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer ...@@ -20,129 +20,116 @@ from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import * from x2paddle.core.util import *
class DygraphTFBatchNormFuser(FuseBase): class TFBatchNormFuser(FuseBase):
def __init__(self): def __init__(self):
self.bn_index = 0 self.bn_index = 0
super(DygraphTFBatchNormFuser, self).__init__(graph_type="dygraph") super(TFBatchNormFuser, self).__init__()
self.patterns = list() self.patterns = list()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的batchnorm图结构。 """ 描述需要替换的batchnorm图结构。
batchnorm层模式python实现代码示例: batchnorm层模式python实现代码示例:
""" """
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"paddle.full", "paddle.full", inputs={}, outputs=[gen_name(1)], shape=[1])
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)}, inputs={"x": gen_name(0),
"y": gen_name(1)},
outputs=[gen_name(2)]) outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"paddle.rsqrt", "paddle.rsqrt", inputs={"x": gen_name(2)}, outputs=[gen_name(3)])
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(4)])
inputs={},
outputs=[gen_name(4)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)}, inputs={"x": gen_name(3),
"y": gen_name(4)},
outputs=[gen_name(5)]) outputs=[gen_name(5)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(6)])
inputs={},
outputs=[gen_name(6)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)}, inputs={"x": gen_name(6),
"y": gen_name(5)},
outputs=[gen_name(7)]) outputs=[gen_name(7)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(8)])
inputs={},
outputs=[gen_name(8)])
pattern.add_layer( pattern.add_layer(
"paddle.subtract", "paddle.subtract",
inputs={"x": gen_name(8), "y": gen_name(7)}, inputs={"x": gen_name(8),
"y": gen_name(7)},
outputs=[gen_name(9)]) outputs=[gen_name(9)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)}, inputs={"x": "bn-input-0",
"y": gen_name(5)},
outputs=[gen_name(10)]) outputs=[gen_name(10)])
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)}, inputs={"x": gen_name(10),
"y": gen_name(9)},
outputs=[gen_name(11)]) outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", }) pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern) self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"paddle.full", "paddle.full", inputs={}, outputs=[gen_name(1)], shape=[1])
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)}, inputs={"x": gen_name(0),
"y": gen_name(1)},
outputs=[gen_name(2)]) outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"paddle.rsqrt", "paddle.rsqrt", inputs={"x": gen_name(2)}, outputs=[gen_name(3)])
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(4)])
inputs={},
outputs=[gen_name(4)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)}, inputs={"x": gen_name(3),
"y": gen_name(4)},
outputs=[gen_name(5)]) outputs=[gen_name(5)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)}, inputs={"x": "bn-input-0",
"y": gen_name(5)},
outputs=[gen_name(10)]) outputs=[gen_name(10)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(6)])
inputs={},
outputs=[gen_name(6)])
pattern.add_layer( pattern.add_layer(
"paddle.multiply", "paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)}, inputs={"x": gen_name(6),
"y": gen_name(5)},
outputs=[gen_name(7)]) outputs=[gen_name(7)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(8)])
inputs={},
outputs=[gen_name(8)])
pattern.add_layer( pattern.add_layer(
"paddle.subtract", "paddle.subtract",
inputs={"x": gen_name(8), "y": gen_name(7)}, inputs={"x": gen_name(8),
"y": gen_name(7)},
outputs=[gen_name(9)]) outputs=[gen_name(9)])
pattern.add_layer( pattern.add_layer(
"paddle.add", "paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)}, inputs={"x": gen_name(10),
"y": gen_name(9)},
outputs=[gen_name(11)]) outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", }) pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern) self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph) new_layers, last_layer_id = self.gen_new_layer(matches, parameters,
graph)
matches_copy = copy.deepcopy(matches) matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items(): for layer_id, layer in matches_copy.items():
for i in range(3): for i in range(3):
...@@ -167,7 +154,7 @@ class DygraphTFBatchNormFuser(FuseBase): ...@@ -167,7 +154,7 @@ class DygraphTFBatchNormFuser(FuseBase):
def gen_new_layer(self, matches, parameters, graph): def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys()) layer_id_list = list(matches.keys())
layer_id_list.sort(key = int) layer_id_list.sort(key=int)
for layer_id, layer in matches.items(): for layer_id, layer in matches.items():
if layer.kernel == "paddle.full": if layer.kernel == "paddle.full":
full_layer = layer full_layer = layer
...@@ -224,4 +211,3 @@ class DygraphTFBatchNormFuser(FuseBase): ...@@ -224,4 +211,3 @@ class DygraphTFBatchNormFuser(FuseBase):
outputs=add_layer.outputs, outputs=add_layer.outputs,
perm=[0, 2, 3, 1]) perm=[0, 2, 3, 1])
return [transpose0, bn, transpose1], layer_id_list[-1] return [transpose0, bn, transpose1], layer_id_list[-1]
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_ import Pass from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import TraceFcFuser from x2paddle.optimizer.fusion import TraceFcFuser
from x2paddle.optimizer.pass_manager import pass_register from x2paddle.optimizer.pass_manager import pass_register
...@@ -30,4 +30,4 @@ class TraceFcFusePass(Pass): ...@@ -30,4 +30,4 @@ class TraceFcFusePass(Pass):
# 用于注册 # 用于注册
trace_fc_fuse_pass = TraceFcFusePass() trace_fc_fuse_pass = TraceFcFusePass()
\ No newline at end of file
...@@ -21,9 +21,9 @@ from x2paddle.core.util import * ...@@ -21,9 +21,9 @@ from x2paddle.core.util import *
class TraceFcFuser(FuseBase): class TraceFcFuser(FuseBase):
def __init__(self): def __init__(self):
self.linear_index = 0 self.linear_index = 0
super(TraceFcFuser, self).__init__(graph_type="dygraph") super(TraceFcFuser, self).__init__()
self.patterns = list() self.patterns = list()
def build_pattern(self): def build_pattern(self):
""" 描述需要替换的fc图结构。 """ 描述需要替换的fc图结构。
fc层模式python实现代码示例: fc层模式python实现代码示例:
...@@ -43,11 +43,9 @@ class TraceFcFuser(FuseBase): ...@@ -43,11 +43,9 @@ class TraceFcFuser(FuseBase):
def gen_name(id): def gen_name(id):
return "x" + str(id) return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"paddle.transpose", "paddle.transpose",
inputs={"x": gen_name(0)}, inputs={"x": gen_name(0)},
...@@ -59,9 +57,7 @@ class TraceFcFuser(FuseBase): ...@@ -59,9 +57,7 @@ class TraceFcFuser(FuseBase):
"y": gen_name(1)}, "y": gen_name(1)},
outputs=[gen_name(2)]) outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(3)])
inputs={},
outputs=[gen_name(3)])
pattern.add_layer( pattern.add_layer(
"prim.add_", "prim.add_",
inputs={"x": gen_name(2), inputs={"x": gen_name(2),
...@@ -70,21 +66,17 @@ class TraceFcFuser(FuseBase): ...@@ -70,21 +66,17 @@ class TraceFcFuser(FuseBase):
alpha=1) alpha=1)
pattern.build(inputs={"input-0": "fc-input-0"}) pattern.build(inputs={"input-0": "fc-input-0"})
self.patterns.append(pattern) self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph") pattern = PaddleGraph()
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(0)])
inputs={},
outputs=[gen_name(0)])
pattern.add_layer( pattern.add_layer(
"paddle.transpose", "paddle.transpose",
inputs={"x": gen_name(0)}, inputs={"x": gen_name(0)},
outputs=[gen_name(1)], outputs=[gen_name(1)],
perm=[1, 0]) perm=[1, 0])
pattern.add_layer( pattern.add_layer(
"self.create_parameter", "self.create_parameter", inputs={}, outputs=[gen_name(2)])
inputs={},
outputs=[gen_name(2)])
pattern.add_layer( pattern.add_layer(
"paddle.addmm", "paddle.addmm",
inputs={"input": gen_name(2), inputs={"input": gen_name(2),
...@@ -95,7 +87,6 @@ class TraceFcFuser(FuseBase): ...@@ -95,7 +87,6 @@ class TraceFcFuser(FuseBase):
beta=1) beta=1)
pattern.build(inputs={"input-0": "fc-input-0"}) pattern.build(inputs={"input-0": "fc-input-0"})
self.patterns.append(pattern) self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches): def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches) new_layer = self.gen_new_layer(parameters, matches)
...@@ -134,4 +125,3 @@ class TraceFcFuser(FuseBase): ...@@ -134,4 +125,3 @@ class TraceFcFuser(FuseBase):
scope_name=scope_name, scope_name=scope_name,
**attrs) **attrs)
return new_layer return new_layer
...@@ -13,54 +13,37 @@ ...@@ -13,54 +13,37 @@
# limitations under the License. # limitations under the License.
from x2paddle.optimizer.pass_manager import PassManager from x2paddle.optimizer.pass_manager import PassManager
from x2paddle.optimizer.fusion.dygraph import * from x2paddle.optimizer.fusion import *
from x2paddle.optimizer.fusion.static import * from x2paddle.optimizer.elimination import *
from x2paddle.optimizer.elimination.dygraph import *
from x2paddle.optimizer.elimination.static import *
class GraphOptimizer(object): class GraphOptimizer(object):
def __init__(self, source_frame, paddle_type="dygraph", jit_type="trace"): def __init__(self, source_frame, jit_type="trace"):
if source_frame == "pytorch": if source_frame == "pytorch":
if jit_type == "trace": if jit_type == "trace":
self.passes = ["trace_fc_fuse_pass"] self.passes = ["trace_fc_fuse_pass"]
else: else:
self.passes = [ self.passes = [
"dygraph_constant_fuse_pass", "constant_fuse_pass", "batchnorm2d_fuse_pass",
"dygraph_batchnorm2d_fuse_pass", "interpolate_bilinear_fuse_pass", "fc_fuse_pass",
"dygraph_interpolate_bilinear_fuse_pass", "adaptive_pool2d_fuse_pass", "reshape_fuse_pass",
"dygraph_fc_fuse_pass", "dropout_fuse_pass", "if_fuse_pass"
"dygraph_adaptive_pool2d_fuse_pass",
"dygraph_reshape_fuse_pass",
"dygraph_dropout_fuse_pass",
"dygraph_if_fuse_pass"
] ]
elif source_frame == "caffe": elif source_frame == "caffe":
if paddle_type == "dygraph": self.passes = ["bn_scale_fuse_pass"]
self.passes = ["dygraph_bn_scale_fuse_pass"]
else:
self.passes = ["static_bn_scale_fuse_pass"]
elif source_frame == "tf": elif source_frame == "tf":
if paddle_type == "dygraph": self.passes = [
self.passes = [ "conv2d_add_fuse_pass", "tf_batchnorm_fuse_pass",
"dygraph_conv2d_add_fuse_pass", "prelu_fuse_pass", "transpose_eliminate_pass"
"dygraph_tf_batchnorm_fuse_pass", ]
"dygraph_prelu_fuse_pass",
"transpose_eliminate_pass"
]
else:
self.passes = [
"static_conv2d_add_fuse_pass",
"static_tf_batchnorm_fuse_pass",
"static_prelu_fuse_pass",
"static_transpose_eliminate_pass"
]
else: else:
self.passes = [] self.passes = []
def optimize(self, graph): def optimize(self, graph):
for pass_name in self.passes: for pass_name in self.passes:
pass_ = PassManager.lookup(pass_name)() pass_ = PassManager.lookup(pass_name)()
if pass_name.endswith("_eliminate_pass") or pass_name.endswith("_conv2d_add_fuse_pass"): if pass_name.endswith("_eliminate_pass") or pass_name.endswith(
"conv2d_add_fuse_pass"):
pass_.apply(graph) pass_.apply(graph)
else: else:
while True: while True:
......
...@@ -99,13 +99,14 @@ class PatternMatcher(object): ...@@ -99,13 +99,14 @@ class PatternMatcher(object):
return False return False
else: else:
subgraph_id2layers.pop(layer_id) subgraph_id2layers.pop(layer_id)
continue continue
else: else:
if len(graph.edges_out[layer_id]) != len( if len(graph.edges_out[layer_id]) != len(
pattern.edges_out[pattern_layer_id]): pattern.edges_out[pattern_layer_id]):
# 如果在每个节点edges_in相同的情况下,edges_out数目相同则说明无节点在subgraph外被用到 # 如果在每个节点edges_in相同的情况下,edges_out数目相同则说明无节点在subgraph外被用到
if "paddle.nn" in layer.kernel and "functional" not in layer.kernel: if "paddle.nn" in layer.kernel and "functional" not in layer.kernel:
pattern_layer_opt = pattern_layer.outputs[1:] pattern_layer_opt = pattern_layer.outputs[
1:]
else: else:
pattern_layer_opt = pattern_layer.outputs pattern_layer_opt = pattern_layer.outputs
if not set(pattern_layer_opt).issubset( if not set(pattern_layer_opt).issubset(
...@@ -118,13 +119,16 @@ class PatternMatcher(object): ...@@ -118,13 +119,16 @@ class PatternMatcher(object):
continue continue
else: else:
layer_out = graph.edges_out[layer_id] layer_out = graph.edges_out[layer_id]
pattern_layer_out = pattern.edges_out[pattern_layer_id] pattern_layer_out = pattern.edges_out[
pattern_layer_id]
is_pop = False is_pop = False
for i in range(len(layer_out)): for i in range(len(layer_out)):
layer_id_out = layer_out[i] layer_id_out = layer_out[i]
pattern_layer_id_out = pattern_layer_out[i] pattern_layer_id_out = pattern_layer_out[i]
if layer_id_out != -1: if layer_id_out != -1:
if graph_layers[layer_id_out].kernel != pattern.layers[pattern_layer_id_out].kernel: if graph_layers[
layer_id_out].kernel != pattern.layers[
pattern_layer_id_out].kernel:
is_pop = True is_pop = True
break break
if is_pop: if is_pop:
...@@ -243,10 +247,11 @@ class PatternMatcher(object): ...@@ -243,10 +247,11 @@ class PatternMatcher(object):
for j, block in enumerate(layer.blocks): for j, block in enumerate(layer.blocks):
if len(block.layers) > 0: if len(block.layers) > 0:
self.detect_patterns_by_edge(layer.blocks[j]) self.detect_patterns_by_edge(layer.blocks[j])
def detect_patterns_by_op(self, graph): def detect_patterns_by_op(self, graph):
""" 当只匹配op时使用此方式。 """ 当只匹配op时使用此方式。
""" """
def get_subgraph(pattern, graph, start_index): def get_subgraph(pattern, graph, start_index):
pattern_id2layers = pattern.get_global_layers() pattern_id2layers = pattern.get_global_layers()
pattern_ids = list(pattern_id2layers.keys()) pattern_ids = list(pattern_id2layers.keys())
...@@ -261,7 +266,7 @@ class PatternMatcher(object): ...@@ -261,7 +266,7 @@ class PatternMatcher(object):
if layer.kernel != pattern_layer.kernel: if layer.kernel != pattern_layer.kernel:
return False return False
subgraph_id2layers[layer_id] = layer subgraph_id2layers[layer_id] = layer
while len(subgraph_id2layers) != len(pattern_id2layers): while len(subgraph_id2layers) != len(pattern_id2layers):
out = update(layer_id, pattern_layer_id) out = update(layer_id, pattern_layer_id)
if out == False: if out == False:
...@@ -271,6 +276,7 @@ class PatternMatcher(object): ...@@ -271,6 +276,7 @@ class PatternMatcher(object):
return subgraph_id2layers return subgraph_id2layers
else: else:
return False return False
for i, (layer_id, layer) in enumerate(graph.layers.items()): for i, (layer_id, layer) in enumerate(graph.layers.items()):
match_info = get_subgraph(self.pattern, graph, i) match_info = get_subgraph(self.pattern, graph, i)
if match_info: if match_info:
...@@ -279,7 +285,6 @@ class PatternMatcher(object): ...@@ -279,7 +285,6 @@ class PatternMatcher(object):
if len(block.layers) > 0: if len(block.layers) > 0:
self.detect_patterns_by_op(layer.blocks[j]) self.detect_patterns_by_op(layer.blocks[j])
def remove_overlapped_match(self): def remove_overlapped_match(self):
""" 如果2个子图有重叠,只取前一个子图。 """ 如果2个子图有重叠,只取前一个子图。
""" """
...@@ -317,8 +322,8 @@ def get_subgraph(prefix_layer_id, suffix_layer_id, graph): ...@@ -317,8 +322,8 @@ def get_subgraph(prefix_layer_id, suffix_layer_id, graph):
class FuseBase(object): class FuseBase(object):
def __init__(self, graph_type): def __init__(self):
self.pattern = PaddleGraph(graph_type=graph_type) self.pattern = PaddleGraph()
self.patterns = list() self.patterns = list()
def operate(self, graph, match_kind="topo"): def operate(self, graph, match_kind="topo"):
...@@ -356,5 +361,3 @@ class FuseBase(object): ...@@ -356,5 +361,3 @@ class FuseBase(object):
if layer_id in subgraph.layers: if layer_id in subgraph.layers:
# layer_id可能是属于子图的,此时删除父layer,即删除整个子图 # layer_id可能是属于子图的,此时删除父layer,即删除整个子图
subgraph.layers.pop(layer_id) subgraph.layers.pop(layer_id)
\ No newline at end of file
...@@ -415,7 +415,7 @@ class HierarchicalTree(Tree): ...@@ -415,7 +415,7 @@ class HierarchicalTree(Tree):
self.update_parameters() self.update_parameters()
import_list = ["import paddle", import_list = ["import paddle",
"import math", "import math",
"from x2paddle.op_mapper.dygraph.pytorch2paddle " + \ "from x2paddle.op_mapper.pytorch2paddle " + \
"import pytorch_custom_layer as x2paddle_nn" "import pytorch_custom_layer as x2paddle_nn"
"\n",] "\n",]
import_str = "\n".join(import_list) import_str = "\n".join(import_list)
......
...@@ -288,7 +288,7 @@ def gen_layer_code(graph, sub_layers, sub_layers_name, different_attrs=dict()): ...@@ -288,7 +288,7 @@ def gen_layer_code(graph, sub_layers, sub_layers_name, different_attrs=dict()):
cur_outputs.extend(layer.outputs[1:]) cur_outputs.extend(layer.outputs[1:])
elif "prim" in layer.kernel: elif "prim" in layer.kernel:
func_name = layer.kernel.replace(".", "_") func_name = layer.kernel.replace(".", "_")
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim2code from x2paddle.op_mapper.pytorch2paddle import prim2code
if hasattr(prim2code, func_name): if hasattr(prim2code, func_name):
for k, v in layer.inputs.items(): for k, v in layer.inputs.items():
if v not in cur_outputs and v not in inputs: if v not in cur_outputs and v not in inputs:
......
...@@ -368,7 +368,7 @@ class ModuleGraph(object): ...@@ -368,7 +368,7 @@ class ModuleGraph(object):
self.update_parameters() self.update_parameters()
import_list = ["import paddle", import_list = ["import paddle",
"import math", "import math",
"from x2paddle.op_mapper.dygraph.pytorch2paddle " + \ "from x2paddle.op_mapper.pytorch2paddle " + \
"import pytorch_custom_layer as x2paddle_nn" "import pytorch_custom_layer as x2paddle_nn"
"\n",] "\n",]
import_str = "\n".join(import_list) import_str = "\n".join(import_list)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册