|
| 1 | +- 一个完整的使用动静转换@to_static导出、可部署的模型完整代码(参考以图搜图),提供 AI Studio 任务链接 |
| 2 | +AI Studio 任务链接:https://aistudio.baidu.com/aistudio/projectdetail/3910079 |
| 3 | + |
| 4 | +- 接口层面: |
| 5 | + |
| 6 | +接口层面相对来说比较全面,指出了模型静态图导出的方法。同时InputSpec也比较好用,可以通过三种方式来构造所需要的InputSpec:直接构造、由Tensor构造以及由numpy.ndarray构造,但是并没有指出这三种方式构造的InputSpec的优缺点。在动态图转静态图--使用样例--2.2.2基本用法的方式四:指定非Tensor参数类型中代码有问题,to_static函数中没有输入net参数,修改代码如下: |
| 7 | + |
| 8 | +```python |
| 9 | +class SimpleNet(Layer): |
| 10 | + def __init__(self, ): |
| 11 | + super(SimpleNet, self).__init__() |
| 12 | + self.linear = paddle.nn.Linear(10, 3) |
| 13 | + self.relu = paddle.nn.ReLU() |
| 14 | + |
| 15 | + def forward(self, x, use_act=False): |
| 16 | + out = self.linear(x) |
| 17 | + if use_act: |
| 18 | + out = self.relu(out) |
| 19 | + return out |
| 20 | + |
| 21 | +net = SimpleNet() |
| 22 | +# 方式一:save inference model with use_act=False |
| 23 | +# 修改 |
| 24 | +net = to_static(net, input_spec=[InputSpec(shape=[None, 10], name='x')]) |
| 25 | +paddle.jit.save(net, path='./simple_net') |
| 26 | + |
| 27 | + |
| 28 | +# 方式二:save inference model with use_act=True |
| 29 | +# 修改 |
| 30 | +net = to_static(net, input_spec=[InputSpec(shape=[None, 10], name='x'), True]) |
| 31 | +paddle.jit.save(net, path='./simple_net') |
| 32 | +``` |
| 33 | +- 语法层面: |
| 34 | + |
| 35 | +支持语法相对来说是比较全面的,介绍的也比较细致。控制流语法等用起来也比较流畅。但是在第三方相关库numpy中只是简单的说了部分支持,并没有具体的例子解释numpy操作中哪部分是支持的,哪部分是不支持的。并且在案例解析--三、内嵌Numpy操作中直接写到动态图模型代码中numpy相关的操作不能转换为静态图,虽然提供了一个好的方法来解决这个问题(转换为tensor),虽然能理解下来但是感觉这两部分写的不具体且有点矛盾。 |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | + |
| 40 | +另外,在案例解析6.1默认参数的部分,给出了forward函数一个不错的建议,但是当我在分析它的原因的时候,我测试了一下下面的代码: |
| 41 | + |
| 42 | + |
| 43 | +```python |
| 44 | +import paddle |
| 45 | +from paddle.nn import Layer |
| 46 | +from paddle.jit import to_static |
| 47 | +from paddle.static import InputSpec |
| 48 | + |
| 49 | + |
| 50 | +class SimpleNet(Layer): |
| 51 | + def __init__(self, ): |
| 52 | + super(SimpleNet, self).__init__() |
| 53 | + self.linear = paddle.nn.Linear(10, 3) |
| 54 | + self.relu = paddle.nn.ReLU() |
| 55 | + |
| 56 | + def forward(self, x, use_act=False): |
| 57 | + out = self.linear(x) |
| 58 | + if use_act: |
| 59 | + out = self.relu(out) |
| 60 | + return out |
| 61 | + |
| 62 | +net = SimpleNet() |
| 63 | +# 方式一:save inference model with use_act=False |
| 64 | +# paddle.jit.save(net, path='./simple_net', input_spec=[InputSpec(shape=[None, 10], name='x')]) |
| 65 | + |
| 66 | + |
| 67 | +# 方式二:save inference model with use_act=True |
| 68 | +paddle.jit.save(net, path='./simple_net', input_spec=[InputSpec(shape=[None, 10], name='x'), True]) |
| 69 | + |
| 70 | +``` |
| 71 | +它他并没有报错,但是paddle.jit.save时在input_spec时我指定了非tensor的数据,而且程序运行并没有报错,这会不会与原因有点冲突?文档原因截图如下: |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | + |
| 76 | +- 报错层面 |
| 77 | + |
| 78 | +文档总体来说写的比较全面。 |
| 79 | +文档中1.1错误日志怎么看,报错调试的文档代码如下: |
| 80 | +```python |
| 81 | +import paddle |
| 82 | +import numpy as np |
| 83 | + |
| 84 | +@paddle.jit.to_static |
| 85 | +def func(x): |
| 86 | + two = paddle.full(shape=[1], fill_value=2, dtype="int32") |
| 87 | + x = paddle.reshape(x, shape=[1, two]) |
| 88 | + return x |
| 89 | + |
| 90 | +def train(): |
| 91 | + x = paddle.to_tensor(np.ones([3]).astype("int32")) |
| 92 | + func(x) |
| 93 | + |
| 94 | +if __name__ == '__main__': |
| 95 | + train() |
| 96 | + |
| 97 | +``` |
| 98 | +报错日志如下图,在paddle内置的方法中有点难以快速定位到问题所在。该报错问题应该是第7行paddle.reshape的维度设置不对。但是在使用排错日志的时候,没有报错信息直接定位到第7行。个人觉得对错误代码位置的直接定位才是最重要的。而且报错的内容提示太多,对新手来说不会很友好。建议直接在报错的时候,报错的最后位置,重复一遍,最重要的报错信息,并提示报错代码所在位置。这样对新手比较友好。对于这种简单问题的报错提示更加明确一点会让使用者觉得更加方便。 |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | +- 文档层面 |
| 105 | + |
| 106 | +文档整体比较完善,但是在使用指南->动态图转静态图->案例解析 中全部都是动静转化机制的各种API的分章节介绍,建议在案例解析最后增加一个完整的实例代码,比如cifar10图像分类的动态图转静态图案例,或者把应用实践中的案例链接附在最后,方便读者找寻。有些读者可能想找一个案例,然后找了使用指南的案例解析,发现没有一个完整的案例,正巧这个读者对整个文档不熟悉,没看过应用实践,然后就找不到案例。 |
| 107 | + |
| 108 | + |
| 109 | +- 意见建议(问题汇总) |
| 110 | + |
| 111 | +1、接口层面,使用指南->动态图转静态图->使用样例 2.2.1 构造inputSpec 并没有指出这三种方式构造的InputSpec的优缺点。 |
| 112 | +2、语法层面,对numpy的支持性存在一些问题。 |
| 113 | +3、报错调试,在使用排错日志的时候,没有报错信息直接定位到错误代码的位置,且报错内容提示太多,对新手不友好。建议直接在报错的时候,报错的最后位置,重复一遍,最重要的报错信息,并提示报错代码所在位置。 |
| 114 | +4、文档层面,在使用指南->动态图转静态图->案例解析 中全部都是动静转化机制的各种API的分章节介绍,建议在案例解析最后增加一个完整的实例代码。 |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + |
0 commit comments