-
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
Changes from 3 commits
9f84043
82db069
ea1481d
bee2f29
a056217
b4bd1a4
fec7243
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# ------------------------------------------------------------- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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 os | ||
|
||
from systemds.context import SystemDSContext | ||
from systemds.operator import Matrix, Source, MultiReturn | ||
from systemds.utils.helpers import get_path_to_script_layers | ||
|
||
|
||
class Affine: | ||
_sds_context: SystemDSContext | ||
_source: Source | ||
_X: Matrix | ||
weight: Matrix | ||
bias: Matrix | ||
|
||
def __init__(self, d, m, seed=-1): | ||
""" | ||
d: number of features | ||
m: number of neuron | ||
""" | ||
self._sds_context = SystemDSContext() | ||
path = get_path_to_script_layers() | ||
path = os.path.join(path, "affine.dml") | ||
self._source = self._sds_context.source(path, "affine") | ||
self.weight = Matrix(self._sds_context, '') | ||
self.bias = Matrix(self._sds_context, '') | ||
|
||
params_dict = {'D': d, 'M': m, 'seed': seed} | ||
out = [self.weight, self.bias] | ||
op = MultiReturn(self._sds_context, "affine::init", output_nodes=out, named_input_nodes=params_dict) | ||
self.weight._unnamed_input_nodes = [op] | ||
self.bias._unnamed_input_nodes = [op] | ||
op._source_node = self._source | ||
|
||
|
||
def forward(self, X): | ||
""" | ||
X: input matrix | ||
return out: output matrix | ||
""" | ||
self._X = X | ||
out = self._source.forward(X, self.weight, self.bias) | ||
return out | ||
|
||
def backward(self, dout): | ||
""" | ||
dout: gradient of output, passed from the upstream | ||
return dX, dW,db: gradient of input, weights and bias, respectively | ||
""" | ||
params_dict = {'dout': dout, 'X': self._X, 'W': self.weight, 'b': self.bias} | ||
dX = Matrix(self._sds_context, '') | ||
dW = Matrix(self._sds_context, '') | ||
db = Matrix(self._sds_context, '') | ||
out = [dX, dW, db] | ||
op = MultiReturn(self._sds_context, "affine::backward", output_nodes=out, named_input_nodes=params_dict) | ||
dX._unnamed_input_nodes = [op] | ||
dW._unnamed_input_nodes = [op] | ||
db._unnamed_input_nodes = [op] | ||
op._source_node = self._source | ||
return dX, dW, db |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# ------------------------------------------------------------- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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 os.path | ||
|
||
from systemds.context import SystemDSContext | ||
from systemds.operator import Matrix, Source | ||
from systemds.utils.helpers import get_path_to_script_layers | ||
|
||
|
||
class ReLU: | ||
_sds_context: SystemDSContext | ||
_source: Source | ||
_X: Matrix | ||
|
||
def __init__(self): | ||
self._sds_context = SystemDSContext() | ||
path = get_path_to_script_layers() | ||
path = os.path.join(path, "relu.dml") | ||
self._source = self._sds_context.source(path, "relu") | ||
|
||
def forward(self, X): | ||
""" | ||
X: input matrix | ||
return out: output matrix | ||
""" | ||
self._X = X | ||
out = self._source.forward(X) | ||
return out | ||
|
||
def backward(self, dout): | ||
""" | ||
dout: gradient of output, passed from the upstream | ||
return dX: gradient of input | ||
""" | ||
dX = self._source.backward(dout, self._X) | ||
return dX |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# ------------------------------------------------------------- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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. | ||
# | ||
# ------------------------------------------------------------- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add line in end of file |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# ------------------------------------------------------------- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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 unittest | ||
|
||
import numpy as np | ||
|
||
from systemds.context import SystemDSContext | ||
|
||
from systemds.operator.nn_nodes.affine import Affine | ||
|
||
dim = 6 | ||
n = 10 | ||
m = 5 | ||
np.random.seed(11) | ||
X = np.random.rand(n, dim) | ||
|
||
np.random.seed(10) | ||
W = np.random.rand(dim, m) | ||
b = np.random.rand(m) | ||
thaivd1309 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
class TestAffine(unittest.TestCase): | ||
sds: SystemDSContext = None | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
cls.sds = SystemDSContext() | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
cls.sds.close() | ||
|
||
def test_affine(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add dedicated tests for forward for backward. |
||
Xm = self.sds.from_numpy(X) | ||
Wm = self.sds.from_numpy(W) | ||
bm = self.sds.from_numpy(b) | ||
|
||
affine = Affine(dim, m, 10) | ||
out = affine.forward(Xm) | ||
print(out.compute()) | ||
print(out.script_str) | ||
dout = self.sds.from_numpy(np.random.rand(n, m)) | ||
dX, dW, db = affine.backward(dout) | ||
assert True | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# ------------------------------------------------------------- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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 unittest | ||
|
||
import numpy as np | ||
|
||
from systemds.context import SystemDSContext | ||
|
||
from systemds.operator.nn_nodes.relu import ReLU | ||
|
||
X = np.array([0, -1, -2, 2, 3, -5]) | ||
dout = np.array([0, 1, 2, 3, 4, 5]) | ||
|
||
|
||
class TestRelu(unittest.TestCase): | ||
sds: SystemDSContext = None | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
cls.sds = SystemDSContext() | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
cls.sds.close() | ||
|
||
def test_forward(self): | ||
relu = ReLU() | ||
#forward | ||
Xm = self.sds.from_numpy(X) | ||
out = relu.forward(Xm).compute().flatten() | ||
expected = np.array([0, 0, 0, 2, 3, 0]) | ||
self.assertTrue(np.allclose(out, expected)) | ||
|
||
def test_backward(self): | ||
relu = ReLU() | ||
# forward | ||
Xm = self.sds.from_numpy(X) | ||
out = relu.forward(Xm) | ||
# backward | ||
doutm = self.sds.from_numpy(dout) | ||
dx = relu.backward(doutm).compute().flatten() | ||
expected = np.array([0, 0, 0, 3, 4, 0], dtype=np.double) | ||
self.assertTrue(np.allclose(dx, expected)) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |
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.