Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dy2stat]support Python3 type annotation #36544

Merged
merged 11 commits into from
Nov 3, 2021

Conversation

0x45f
Copy link
Contributor

@0x45f 0x45f commented Oct 19, 2021

PR types

Others

PR changes

Others

Describe

Dy2stat type annotation

背景
python3支持type hint语法,动转静模块中可以借助type hint语法进行变量类型分析。

功能描述
python3中的type hint语法,比如赋值语句a: float = 1.0和函数参数func(a: int, b: float = 1)。对于下面的代码forward函数虽然将texts标示为paddle.Tensor类型,但是由于动转静模块并未支持python3的type hint语法,无法将texts识别为一个tensor,for语句动转静处理list时会出错。在此PR之后可以将函数参数texts识别为一个tensor。

import paddle 
from paddle.jit import to_static
from paddle import nn
import paddle.nn.functional as F

paddle.set_device('cpu')

class SDMGRHead(nn.Layer):
    def __init__(self,):
        super(SDMGRHead, self).__init__()
        self.name = "name"

        #self.edge_ = nn.Linear(5, 256)
        num_chars = 92
        node_input = 32
        self.edge_embed = nn.Embedding(num_chars, node_input, 0)
    
    def forward(self, texts: paddle.Tensor):
        node_nums, char_nums = [], []
        # import pdb; pdb.set_trace()
        for text in texts:
            # node_nums.append(text.shape[0])
            char_nums.append(paddle.sum((text > -1).astype('int32'), axis=-1))

        max_num = max([char_num.max() for char_num in char_nums])
        #max_num = paddle.max(paddle.concat(char_nums)).numpy()[0]
        all_nodes = paddle.concat([
            paddle.concat(
                [text, paddle.zeros(
                    (text.shape[0], max_num - text.shape[1]))], -1)
            for text in texts
        ])
        temp = paddle.clip(all_nodes, min=0).astype(int)
        embed_nodes = self.edge_embed(temp)
        return embed_nodes

texts = paddle.randn((1, 300, 300)).astype('float32') + 3
model = SDMGRHead()
res = model(texts)
print(res.shape)
infer_shape = [paddle.static.InputSpec(shape=[1, 300, 300], dtype="float32")]
model = to_static(model, input_spec=infer_shape)
paddle.jit.save(model, "./debug/inference")
print("debug: save_inference success!")

测试
下面是两个测试样例,以及StaticAnalysisVisitor模块所识别出的变量类型。

def func_to_test3():
    a = 1
    b = 3.0
    c = a * b
    d = True + c
    e = a < b
    f = 9 * (a * 4)
    g = "dddy"
    h = None
    i = False
    j = None + 1
    k: float = 1.0
    l: paddle.Tensor = paddle.to_tensor([1, 2])
result_var_type3 = {
    'a': {NodeVarType.INT},
    'b': {NodeVarType.FLOAT},
    'c': {NodeVarType.FLOAT},
    'd': {NodeVarType.FLOAT},
    'e': {NodeVarType.BOOLEAN},
    'f': {NodeVarType.INT},
    'g': {NodeVarType.STRING},
    'h': {NodeVarType.NONE},
    'i': {NodeVarType.BOOLEAN},
    'j': {NodeVarType.UNKNOWN},
    'k': {NodeVarType.FLOAT},
    'l': {NodeVarType.PADDLE_RETURN_TYPES}
}

def func_to_test7(a: int, b: float, c: paddle.Tensor, d: float='diff'):
    a = True
result_var_type7 = {
    'a': {NodeVarType.BOOLEAN},
    'b': {NodeVarType.FLOAT},
    'c': {NodeVarType.TENSOR},
    'd': {NodeVarType.STRING}
}

@paddle-bot-old
Copy link

Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

Copy link
Contributor

@Aurelius84 Aurelius84 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work~

# if annotation and value(Constant) are diffent type, we use value type
if node.value:
ret_type = self.node_to_wrapper_map[node.value].node_var_type
if isinstance(node.target, gast.Name):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里只会对类似 x: float = 2.1 作处理,对于类似self.x: float = 2.1 是不会处理? 因为self.x是一个gast.Attribute,而不是一个gast.Name.

此PR 若是不支持的,这里记一个TODO,需要确认下是否有类似非gats.Name的场景和需求

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在之前代码中的Assign node也没有支持类似self.x= 2.1赋值语句,所以在AnnAssign node也暂时不支持self.x: float = 2.1类似语句。后续可以确认是否需要支持此类赋值语句。

@@ -57,6 +57,9 @@ def func_to_test3():
h = None
i = False
j = None + 1
k: float = 1.0
l: paddle.Tensor = fluid.dygraph.to_variable(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_variable 接口已经被弃用了,应该避免使用旧的接口

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改使用to_tensor接口

@0x45f 0x45f changed the title Dy2stat type annotation [Dy2stat]support Python3 type annotation Nov 1, 2021
@Aurelius84 Aurelius84 merged commit db8425e into PaddlePaddle:develop Nov 3, 2021
@0x45f 0x45f deleted the dy2stat_type_annotation branch November 3, 2021 07:16
ghost pushed a commit to piotrekobi/Paddle that referenced this pull request Nov 3, 2021
* Support Py3 type annotations in @to_static

* support type hint for args in func

* support type hint assign

* if annotation and value(Constant) are diffent type, we use value type

* polish type_from_annotation()

* code format

* code format

* remove useless commentary

* fix review

Co-authored-by: Aurelius84 <zhangliujie@baidu.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants