From e81dafc760a6d38dbbde8b4f11deba59bc287bab Mon Sep 17 00:00:00 2001 From: tangnana925 <85614052+tangnana925@users.noreply.github.com> Date: Sat, 31 Jul 2021 05:24:37 +0800 Subject: [PATCH] Dev eye (#5583) * add autotest tan tanh floor arctanh * add autotest tan floor tan * Add autotest for log1p * Code format * delete no use import * add eye op alignment * amend pytorch test * delete merge error branch * Delete log1p.py delete merge error branch * amend code because the list of master change * amend eye test code * amend eye docsting * amend eye docsting * amend eye docstring * autotest test_eye * auto format by CI * amend param of eye Co-authored-by: Zhenhua <huangzhenhua@zhejianglab.com> Co-authored-by: oneflow-ci-bot <ci-bot@oneflow.org> Co-authored-by: oneflow-ci-bot <69100618+oneflow-ci-bot@users.noreply.github.com> --- docs/source/oneflow.rst | 3 +- python/oneflow/__init__.py | 1 + python/oneflow/nn/modules/eye.py | 99 +++++++++++++++++++++++++ python/oneflow/test/modules/test_eye.py | 66 +++++++++++++++++ 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 python/oneflow/nn/modules/eye.py create mode 100644 python/oneflow/test/modules/test_eye.py diff --git a/docs/source/oneflow.rst b/docs/source/oneflow.rst index 63702bb8e..521bdd018 100644 --- a/docs/source/oneflow.rst +++ b/docs/source/oneflow.rst @@ -12,7 +12,8 @@ oneflow clip, diag, enable_eager_execution, - expand, + expand, + eye, flatten, function_config, gather, diff --git a/python/oneflow/__init__.py b/python/oneflow/__init__.py index 70e3eb198..7131a9a84 100644 --- a/python/oneflow/__init__.py +++ b/python/oneflow/__init__.py @@ -319,6 +319,7 @@ from oneflow.nn.modules.sort import sort_op as sort from oneflow.nn.modules.squeeze import squeeze_op as squeeze from oneflow.nn.modules.stack import stack from oneflow.nn.modules.tan import tan_op as tan +from oneflow.nn.modules.eye import eye_op as eye from oneflow.nn.modules.tensor_buffer import gen_tensor_buffer from oneflow.nn.modules.tensor_buffer import ( tensor_buffer_to_tensor_op as tensor_buffer_to_tensor, diff --git a/python/oneflow/nn/modules/eye.py b/python/oneflow/nn/modules/eye.py new file mode 100644 index 000000000..916394da7 --- /dev/null +++ b/python/oneflow/nn/modules/eye.py @@ -0,0 +1,99 @@ +""" +Copyright 2020 The OneFlow Authors. All rights reserved. + +Licensed 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. +""" +from typing import Union + +import oneflow as flow +from oneflow.nn.module import Module +from oneflow.framework.tensor import register_tensor_op + + +class Eye(Module): + def __init__( + self, + n: int, + m: int = None, + device: Union[str, flow.device] = "cpu", + requires_grad: bool = False, + ) -> None: + super().__init__() + self.n = n + self.m = m + self.device = device + self.requires_grad = requires_grad + + def forward(self): + n = self.n + m = self.m + if m is None: + m = n + + if m == n: + res = flow.diag(flow.ones(n)) + elif m < n: + tmp = flow.ones(m) + input1 = flow.zeros((n - m, m)) + input2 = flow.diag(tmp) + res = flow.cat([input2, input1], dim=0) + else: + tmp = flow.ones(n) + input1 = flow.zeros((n, m - n)) + input2 = flow.diag(tmp) + res = flow.cat([input2, input1], dim=1) + + res.requires_grad = self.requires_grad + if isinstance(self.device, str): + device = flow.device(self.device) + else: + device = self.device + re = res.to(device) + return re + + +def eye_op( + n, m=None, device: Union[str, flow.device] = "cpu", requires_grad: bool = False, +): + """This operator creates a 2-D Tensor with ones on the diagonal and zeros elsewhere. + + Args: + n (int): the number of rows. + m (Optional[int], optional): the number of colums with default being n. Defaults to None. + + Keyword args: + device(flow.device, optional): the desired device of returned tensor. Default: if None, uses the current device for the default tensor. + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: `False`. + + Returns: + oneflow.Tensor: The result Blob with ones on the diagonal and zeros elsewhere. + + For example: + + .. code-block:: python + + >>> import oneflow as flow + >>> out = flow.eye(3, 3) + >>> out + tensor([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]], dtype=oneflow.float32) + + """ + return Eye(n, m, device, requires_grad)() + + +if __name__ == "__main__": + import doctest + + doctest.testmod(raise_on_error=True) diff --git a/python/oneflow/test/modules/test_eye.py b/python/oneflow/test/modules/test_eye.py new file mode 100644 index 000000000..c76b85705 --- /dev/null +++ b/python/oneflow/test/modules/test_eye.py @@ -0,0 +1,66 @@ +""" +Copyright 2020 The OneFlow Authors. All rights reserved. + +Licensed 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 +from collections import OrderedDict + +import numpy as np +from automated_test_util import * +from test_util import GenArgList + +import oneflow as flow + + +def _test_eye_forward(test_case, device, n, m): + output = flow.eye(n, m, device=device) + np_out = np.eye(n, m) + test_case.assertTrue(np.array_equal(output.numpy(), np_out)) + + +def _test_eye_backward(test_case, device, n, m): + x = flow.eye(n, m, device=device) + x.requires_grad = True + y = x.sum() + y.backward() + test_case.assertTrue(np.array_equal(x.grad.numpy(), np.ones([n, m]))) + + +@flow.unittest.skip_unless_1n1d() +class TestEye(flow.unittest.TestCase): + def test_eye(test_case): + arg_dict = OrderedDict() + arg_dict["test_fun"] = [ + _test_eye_forward, + _test_eye_backward, + ] + arg_dict["device"] = ["cpu", "cuda"] + arg_dict["n"] = [4, 3, 2] + arg_dict["m"] = [4, 3, 2] + for arg in GenArgList(arg_dict): + arg[0](test_case, *arg[1:]) + + @autotest() + def test_eye_with_random_data(test_case): + n = random().to(int) + m = random().to(int) + x = torch.eye(n=n, m=m) + device = random_device() + x.to(device) + x = random_pytorch_tensor().to(device) + return x + + +if __name__ == "__main__": + unittest.main() -- GitLab