303 lines
8.4 KiB
Python
303 lines
8.4 KiB
Python
# Copyright (c) 2021 PaddlePaddle 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
|
|
|
|
import numpy as np
|
|
from op_test import OpTest, get_device_place, is_custom_device
|
|
|
|
import paddle
|
|
from paddle import static
|
|
from paddle.base import core, dygraph
|
|
|
|
paddle.enable_static()
|
|
|
|
|
|
def ref_complex(x, y):
|
|
return x + 1j * y
|
|
|
|
|
|
class TestComplexOp(OpTest):
|
|
def init_spec(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [10, 10]
|
|
self.dtype = "float64"
|
|
|
|
def setUp(self):
|
|
self.op_type = "complex"
|
|
self.python_api = paddle.complex
|
|
self.init_spec()
|
|
x = np.random.randn(*self.x_shape).astype(self.dtype)
|
|
y = np.random.randn(*self.y_shape).astype(self.dtype)
|
|
out_ref = ref_complex(x, y)
|
|
self.inputs = {'X': x, 'Y': y}
|
|
self.outputs = {'Out': out_ref}
|
|
|
|
def test_check_output(self):
|
|
self.check_output(check_pir=True, check_symbol_infer=False)
|
|
|
|
def test_check_grad(self):
|
|
self.check_grad(
|
|
['X', 'Y'],
|
|
'Out',
|
|
check_pir=True,
|
|
)
|
|
|
|
def test_check_grad_ignore_x(self):
|
|
self.check_grad(
|
|
['Y'],
|
|
'Out',
|
|
no_grad_set=set('X'),
|
|
check_pir=True,
|
|
)
|
|
|
|
def test_check_grad_ignore_y(self):
|
|
self.check_grad(
|
|
['X'],
|
|
'Out',
|
|
no_grad_set=set('Y'),
|
|
check_pir=True,
|
|
)
|
|
|
|
|
|
class TestComplexOpBroadcast1(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [10, 3, 1, 4]
|
|
self.y_shape = [100, 1]
|
|
self.dtype = "float64"
|
|
|
|
|
|
class TestComplexOpBroadcast2(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [100, 1]
|
|
self.y_shape = [10, 3, 1, 4]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexOpBroadcast3(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [1, 100]
|
|
self.y_shape = [100]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexOpZeroSize1(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [1, 0]
|
|
self.y_shape = [0]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexOpZeroSize2(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [100, 1]
|
|
self.y_shape = [10, 0, 1, 4]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexOpZeroSize3(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [10, 3, 1, 0]
|
|
self.y_shape = [100, 1]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexOpZeroSize4(TestComplexOp):
|
|
def init_spec(self):
|
|
self.x_shape = [10, 3, 1, 0]
|
|
self.y_shape = [0, 1]
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestComplexAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
self.x = np.random.randn(10, 10)
|
|
self.y = np.random.randn(10, 10)
|
|
self.out = ref_complex(self.x, self.y)
|
|
|
|
def test_dygraph(self):
|
|
with dygraph.guard():
|
|
x = paddle.to_tensor(self.x)
|
|
y = paddle.to_tensor(self.y)
|
|
out_np = paddle.complex(x, y).numpy()
|
|
np.testing.assert_allclose(self.out, out_np, rtol=1e-05)
|
|
|
|
def test_static(self):
|
|
paddle.enable_static()
|
|
mp, sp = static.Program(), static.Program()
|
|
with static.program_guard(mp, sp):
|
|
x = static.data("x", shape=[10, 10], dtype="float64")
|
|
y = static.data("y", shape=[10, 10], dtype="float64")
|
|
out = paddle.complex(x, y)
|
|
|
|
exe = static.Executor()
|
|
exe.run(sp)
|
|
[out_np] = exe.run(
|
|
mp, feed={"x": self.x, "y": self.y}, fetch_list=[out]
|
|
)
|
|
np.testing.assert_allclose(self.out, out_np, rtol=1e-05)
|
|
|
|
|
|
class OutTest(unittest.TestCase):
|
|
def setUp(self):
|
|
paddle.disable_static()
|
|
if core.is_compiled_with_cuda() or is_custom_device():
|
|
self.place = get_device_place()
|
|
else:
|
|
self.place = core.CPUPlace()
|
|
|
|
def test_complex_api(self):
|
|
def run_complex(test_type):
|
|
x = paddle.arange(2, dtype=paddle.float32).unsqueeze(-1)
|
|
y = paddle.arange(3, dtype=paddle.float32)
|
|
x.stop_gradient = False
|
|
y.stop_gradient = False
|
|
z = paddle.ones([100])
|
|
z.stop_gradient = False
|
|
|
|
a = x + x
|
|
b = y + y
|
|
c = z + z
|
|
|
|
if test_type == "return":
|
|
c = paddle.complex(a, b)
|
|
elif test_type == "input_out":
|
|
paddle.complex(a, b, out=c)
|
|
elif test_type == "both_return":
|
|
c = paddle.complex(a, b, out=c)
|
|
elif test_type == "both_input_out":
|
|
tmp = paddle.complex(a, b, out=c)
|
|
|
|
out = paddle._C_ops.complex(a, b)
|
|
np.testing.assert_allclose(
|
|
out.numpy(),
|
|
c.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
|
|
d = c + c
|
|
|
|
d.mean().backward()
|
|
|
|
return c, x.grad, y.grad, z.grad
|
|
|
|
paddle.disable_static()
|
|
out1, x1, y1, z1 = run_complex("return")
|
|
out2, x2, y2, z2 = run_complex("input_out")
|
|
out3, x3, y3, z3 = run_complex("both_return")
|
|
out4, x4, y4, z4 = run_complex("both_input_out")
|
|
|
|
np.testing.assert_allclose(
|
|
out1.numpy(),
|
|
out2.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
out1.numpy(),
|
|
out3.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
out1.numpy(),
|
|
out4.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
|
|
np.testing.assert_allclose(
|
|
x1.numpy(),
|
|
x2.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
x1.numpy(),
|
|
x3.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
x1.numpy(),
|
|
x3.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
y1.numpy(),
|
|
y2.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
y1.numpy(),
|
|
y3.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_allclose(
|
|
y1.numpy(),
|
|
y4.numpy(),
|
|
1e-20,
|
|
1e-20,
|
|
)
|
|
np.testing.assert_equal(z1, None)
|
|
np.testing.assert_equal(z2, None)
|
|
np.testing.assert_equal(z3, None)
|
|
np.testing.assert_equal(z4, None)
|
|
|
|
|
|
class TestComplexOut(unittest.TestCase):
|
|
def setUp(self):
|
|
paddle.disable_static()
|
|
self.shape = [3, 4]
|
|
self.real_np = np.random.rand(*self.shape).astype(np.float32)
|
|
self.imag_np = np.random.rand(*self.shape).astype(np.float32)
|
|
self.test_types = ["out"]
|
|
|
|
def do_test(self, test_type):
|
|
real = paddle.to_tensor(self.real_np, stop_gradient=False)
|
|
imag = paddle.to_tensor(self.imag_np, stop_gradient=False)
|
|
|
|
if test_type == 'raw':
|
|
result = paddle.complex(real, imag)
|
|
result.real().mean().backward()
|
|
return result, real.grad, imag.grad
|
|
elif test_type == 'out':
|
|
out = paddle.empty(self.shape, dtype='complex64')
|
|
out.stop_gradient = False
|
|
paddle.complex(real, imag, out=out)
|
|
out.real().mean().backward()
|
|
return out, real.grad, imag.grad
|
|
else:
|
|
raise ValueError(f"Unknown test type: {test_type}")
|
|
|
|
def test_out(self):
|
|
out_std, real_grad_std, imag_grad_std = self.do_test('raw')
|
|
for test_type in self.test_types:
|
|
out, real_grad, imag_grad = self.do_test(test_type)
|
|
np.testing.assert_allclose(out.numpy(), out_std.numpy(), rtol=1e-20)
|
|
np.testing.assert_allclose(
|
|
real_grad.numpy(), real_grad_std.numpy(), rtol=1e-20
|
|
)
|
|
np.testing.assert_allclose(
|
|
imag_grad.numpy(), imag_grad_std.numpy(), rtol=1e-20
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|