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

Add Skeleton of Python API design #4052

Merged
merged 17 commits into from
Sep 30, 2017

Conversation

reyoung
Copy link
Collaborator

@reyoung reyoung commented Sep 13, 2017

No description provided.

@@ -0,0 +1,156 @@
# Design Doc: Python API

The top level user API in Python should be as same as API in `paddle.v2` after refactoring Paddle from a layer based framework to an operator based framework. There are many new classes in C++ in [compile time] for describing neural networks, such as `Variable`, `Operator`, `Block`. The issue about current design is how to give a proper way to wrap the C++ API to `paddle.v2` API and writing layers in Python.
Copy link
Contributor

Choose a reason for hiding this comment

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

writing -> write


## Python Class and compile-time protobuf

Since we design our Python API concepts based on `compile-time`, we try to map our Python classes to every compile-time result, i.e., the protobuf messages. They are:
Copy link
Contributor

Choose a reason for hiding this comment

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

every compile-time result -> each compile-time concepts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is the result I want to say, not concepts. The result of compile-time is protobuf.

self.ops.prepend(...)
```

Users are able to create a global variable inside any block since they many create parameters inside a RNN or IfElseOp. All parameters should be stored in the global block, not the step block in RNN.
Copy link
Member

@jacquesqiao jacquesqiao Sep 20, 2017

Choose a reason for hiding this comment

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

inside a RNN -> inside a RNNOp

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.


Users are able to create a global variable inside any block since they many create parameters inside a RNN or IfElseOp. All parameters should be stored in the global block, not the step block in RNN.

Users can create local variables for outputs of operators. Users can also append and prepend an operator in current block. Prepending `random initialize` operator or `load` operator is very useful to initialize parameters before training.
Copy link
Member

@jacquesqiao jacquesqiao Sep 20, 2017

Choose a reason for hiding this comment

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

Users can create local variables for outputs of operators.

what about the inputs of operators?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Inputs of operators are the other operators' output.


### Operator

Operator class will take inputs, outputs and attributes of the operator into `protobuf` OpDesc and create a C++ `OpDesc` instance. The `infer_shape` perform on C++ objects.
Copy link
Member

Choose a reason for hiding this comment

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

take ... into OpDesc is a little strange

block = g_block
w = block.create_parameter(...)
b = block.create_parameter(...)
out = stack.create_var()
Copy link
Member

Choose a reason for hiding this comment

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

what is stack for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually, this is a topy, should be block

return self.create_var(...)

def create_parameter(self, ...):
return self.create_global_var(...)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does create_parameter mean create_global_var?

I guess yes, because:

All parameters should be stored in the global block

What happens if the one block's create_parameter call creates a parameter that has the same name from another block? Intuitively block A and block B creating the parameter with the same name will not interfere with each other.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually, no.

  1. All parameters must be created in the global block.
  2. All parameters are marked as Parameter. The Parameter is a subclass of Variable.

Copy link
Contributor

Choose a reason for hiding this comment

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

So the user can not create parameter inside a if-else block? (e.g., create a FC layer with parameter W and B).


### Variable

Operators' inputs, outputs, and parameters are all variables. In our design, a variable has four key attributes: its name(`name`), the block it belongs to(`block`), a pointer pointed to its C++ Protobuf object(`cpp_var_desc_ptr`), and the operator it is created by(`op`). All of these attributes are initialized in the constructor, except the `op`. The `op` will keep being `None` till the variable is taken as an operator's output.
Copy link
Contributor

Choose a reason for hiding this comment

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

The op will keep being None till the variable is taken as an operator's output.

Do you mean: "The value of op is None unless the variable is an operator's output."?


Users are able to create a global variable inside any block since they many create parameters inside a RNN or IfElse. All parameters should be stored in the global block, not the step block in RNN.

Users can create local variables for outputs of operators. Users can also append and prepend an operator in current block. Prepending `random initialize` operator or `load` operator is very useful to initialize parameters before training.
Copy link
Contributor

Choose a reason for hiding this comment

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

"current block" is mentioned 3 times in this document, what exactly does it mean. Is it a global variable?

Yi Wang and others added 2 commits September 29, 2017 20:19
@wangkuiyi wangkuiyi merged commit f600ad1 into PaddlePaddle:develop Sep 30, 2017
@reyoung reyoung deleted the feature/python_api_design branch October 2, 2017 18:19
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.

6 participants