-
Notifications
You must be signed in to change notification settings - Fork 466
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
[SYSTEMDS-3426] Python NN Builtin components #1848
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, most of the things are on the right track.
I would like to change the API a bit, to enable static calling:
This means you need to change the API in 2 ways
as an example Relu should be able to be called:
from systemds.operator.nn_nodes.relu as Relu
Relu.forward(X)
Relu.backward(X)
But we should also still be able to call the other way:
Relu().forward(X)
Relu().backward(X)
For the Affine since it have internal state i like how it is, but i still want the forward and backward static call. and internally in the class for Affine i still want the option to have the state.
Second lets change the liberary name to:
systemds.operator.nn.??
As a follow up task look at the complied plans, and figure out if the NN builtin are sourced multiple times. If they are fix this. Also add a test that verifies the compiled plans does not contain multiple sources of the same file. aka if you use affine twice or more.
To look at the compiled plans simply set the verbose flag when calling compute()
# specific language governing permissions and limitations | ||
# under the License. | ||
# | ||
# ------------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add line in end of file
_X: Matrix | ||
|
||
def __init__(self): | ||
self._sds_context = SystemDSContext() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not allowed since it starts up a new JVM.
just remove it and the variable for SDS.
we can on first call extract the context from the variable X on a forward or on a Backward pass.
def tearDownClass(cls): | ||
cls.sds.close() | ||
|
||
def test_affine(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add dedicated tests for forward for backward.
Ideally you add multiple such tests.
Then write in what you expect to get out from the operation based on a explicit input.
I added static methods call for Affine and ReLU. Since static call of forward and backward does not have internal states, the user needs to provide extra parameter, e.g. affine.forward(X) and Affine.forward(X, W, b). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall i like it, there are 3 missing pieces for me to say that it is a pass:
- Test if it does not source multiple times when called multiple times in a single script, you verify this via calling compute with verbose.
- Verify it works across two different instance of SystemDSContext, to do this you need to start two
SystemDSContext()
and call into these with two different affine transforms. Note here you need to materialize an X for each of them and remember to call close on each. - Make a test that verify combined behavior of multiple instructions. i suggest a simple test for a network of affine(128) relu affine(64) relu affine (32) relu affine(2). here verify again, that we do not souce multiple times, even if we call multiple different layers.
These things should be enough for both of you to pass the coding, but i would like to have seen more instructions introduced.
@Baunsgaard Added the new tests that we discussed. Could you please review it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, this concludes your Programming assignment.
There are some minor things to improve in tests, where you move the variables to individual test cases, and please add at least one more test case with other inputs.
And I am still missing an experiment to verify behavior with multiple SDS contexts.
Before merging we need to Ensure that this API is what we want in general (more people have to indicate their opinion), i can imagine one comment that could be brought up is that the standard functions should be non static and the instance based should be renamed or moved slightly, for instance outside the class definition inside the same file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add license (i know it is stupid, but these do need it as well.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like that this is part of the nn package. This should be moved to the tests.
|
||
class ReLU: | ||
_source: Source = None | ||
_X: Matrix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like that X (the input) is stored inside
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that the input X would be used in the backward pass anyways so I stored it. But I can remove it if you wish
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you know what. You are right, lets keep it, since it is needed in backward passes
|
||
class Affine: | ||
_source: Source = None | ||
_X: Matrix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, i do not like the input is stored inside.
Xm = self.sds.from_numpy(X) | ||
Wm = self.sds.from_numpy(W) | ||
bm = self.sds.full((1, 6), 0) | ||
doutm = self.sds.from_numpy(dout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like doutm is materialized here, can we not calculate it based on a forward to backward pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since an error-evaluating function hasn't been implemented yet, I couldn't calculate the gradient for the backward pass. So I have to materialize the output gradient like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we should leave a TODO specifying to use an loss function.
But i think it should be possible to naively use the outputs of the forward call.
scripts = DMLScript(self.sds) | ||
scripts.build_code(network_out) | ||
|
||
self.assertEqual(1,self.count_sourcing(scripts.dml_script, layer_name="affine")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
format, add a space after ","
@classmethod | ||
def setUpClass(cls): | ||
cls.sds = SystemDSContext() | ||
cls.X = np.array([0, -1, -2, 2, 3, -5]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this to the individual tests.
return dX | ||
|
||
# forward = staticmethod(forward) | ||
# backward = staticmethod(backward) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove commented code.
""" | ||
Affine._create_source(X.sds_context) | ||
out = Affine._source.forward(X, W, b) | ||
return out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collapse these to lines to not make out on the line above.
X: input matrix | ||
return out: output matrix | ||
""" | ||
self._X = X |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this.
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]> Closes apache#1848
Thanks for the PR @thaivd1309 and @rahuljo I will take it from here, and moved the code to another PR #1929 , |
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]> Closes apache#1848
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]> Closes apache#1848
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Closes apache#1848 Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]> ...
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Closes apache#1848 Closes apache#1929 Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]>
This commit adds the new interface for easy usage of our neural network in python. The design take inspiration from other neural network frameworks. This specific commit contains the building blocks of Affine and Relu. Closes #1848 Closes #1929 Co-authored-by: Duc Thai Vu <[email protected]> Co-authored-by: Rahul Joshi <[email protected]>
I added the class Affine which represents a layer in a neural network.
Also, the class Source couldn't parse the file ''affine.dml'' because it it contains the comment block " /* */ " so I fixed it