Files
paddlepaddle--paddle/test/legacy_test/test_imperative_double_grad.py
T
2026-07-13 12:40:42 +08:00

1212 lines
41 KiB
Python

# Copyright (c) 2022 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
from unittest import TestCase
import numpy as np
from op_test import get_device, is_custom_device
import paddle
import paddle.nn.functional as F
from paddle import base
from paddle.base.wrapped_decorator import wrap_decorator
from paddle.vision.models import resnet50, resnet101
def _dygraph_guard_(func):
def __impl__(*args, **kwargs):
if base.in_dygraph_mode():
return func(*args, **kwargs)
else:
with base.dygraph.guard():
return func(*args, **kwargs)
return __impl__
dygraph_guard = wrap_decorator(_dygraph_guard_)
def random_var(size, low=-1, high=1, dtype='float32'):
x_np = np.random.uniform(low=low, high=high, size=size).astype(dtype)
return paddle.to_tensor(x_np)
class TestEagerGrad(TestCase):
def test_simple_example_eager_grad(self):
np.random.seed(2021)
paddle.set_device('cpu')
np_x = np.random.random((3, 3))
np_y = np.random.random((3, 1))
x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
out = paddle.matmul(x, y)
dx = base.dygraph.grad(out, x)
dout = np.ones_like(np_y)
expected_dx = np.matmul(dout, np.transpose(np_y))
# stop_gradient = !create_graph, create_graph default false
self.assertEqual(dx[0].stop_gradient, True)
np.testing.assert_allclose(dx[0].numpy(), expected_dx, rtol=1e-05)
def test_simple_example_eager_grad_allow_unused(self):
np.random.seed(2021)
paddle.set_device('cpu')
np_x = np.random.random((3, 3))
np_y = np.random.random((3, 1))
np_z = np.random.random((3, 1))
x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
out_z = paddle.nn.functional.sigmoid(z)
out = paddle.matmul(x, y)
dx = base.dygraph.grad(out, [x, z], allow_unused=True)
dout = np.ones_like(np_y)
expected_dx = np.matmul(dout, np.transpose(np_y))
np.testing.assert_allclose(dx[0].numpy(), expected_dx, rtol=1e-05)
# stop_gradient = !create_graph, create_graph default false
self.assertEqual(dx[0].stop_gradient, True)
# x is unused input in the graph
self.assertIsNone(dx[1])
def test_simple_example_eager_grad_not_allow_unused(self):
np.random.seed(2021)
paddle.set_device('cpu')
np_x = np.random.random((3, 3))
np_y = np.random.random((3, 1))
np_z = np.random.random((3, 1))
x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
out_z = paddle.nn.functional.sigmoid(z)
out = paddle.matmul(x, y)
try:
# allow_unused is false in default
dx = base.dygraph.grad(out, [x, z])
except ValueError as e:
error_msg = str(e)
assert error_msg.find("allow_unused") > 0
def test_simple_example_eager_grad_duplicate_input(self):
np.random.seed(2021)
paddle.set_device('cpu')
np_x = np.random.random((3, 3))
np_y = np.random.random((3, 1))
np_z = np.random.random((3, 1))
x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
out_z = paddle.nn.functional.sigmoid(z)
out = paddle.matmul(x, y)
try:
# duplicate input will arise RuntimeError errors
dx = base.dygraph.grad(out, [x, x])
except RuntimeError as e:
error_msg = str(e)
assert error_msg.find("duplicate") > 0
def test_simple_example_eager_grad_duplicate_output(self):
np.random.seed(2021)
paddle.set_device('cpu')
np_x = np.random.random((3, 3))
np_y = np.random.random((3, 1))
np_z = np.random.random((3, 1))
x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
out_z = paddle.nn.functional.sigmoid(z)
out = paddle.matmul(x, y)
try:
# duplicate output will arise RuntimeError errors
dx = base.dygraph.grad([out, out], [x])
except RuntimeError as e:
error_msg = str(e)
assert error_msg.find("duplicate") > 0
def test_simple_example_eager_two_grad_output(self):
x1 = paddle.to_tensor([1.0, 2.0])
x1.stop_gradient = False
x2 = paddle.to_tensor([1.0, 2.0])
x2.stop_gradient = False
out1 = x1 * 2
out2 = x2 * 2
dout2_record_by_hook = []
def record_hook(grad):
dout2_record_by_hook.append(grad)
out2.register_hook(record_hook)
out3 = paddle.multiply(out1, out2)
out4 = paddle.mean(out3)
egr_dout2, egr_dout3 = paddle.grad([out4], [out2, out3])
np.testing.assert_array_equal(
dout2_record_by_hook[0].numpy(), np.array([1.0, 2.0])
)
x1 = paddle.to_tensor([1.0, 2.0])
x1.stop_gradient = False
x2 = paddle.to_tensor([1.0, 2.0])
x2.stop_gradient = False
out1 = x1 * 2
out2 = x2 * 2
out3 = paddle.multiply(out1, out2)
out4 = paddle.mean(out3)
dout2, dout3 = paddle.grad([out4], [out2, out3])
self.assertEqual(dout2.stop_gradient, egr_dout2.stop_gradient)
self.assertEqual(dout3.stop_gradient, egr_dout3.stop_gradient)
np.testing.assert_array_equal(dout2.numpy(), egr_dout2.numpy())
np.testing.assert_array_equal(dout3.numpy(), egr_dout3.numpy())
class TestDygraphDoubleGrad(TestCase):
def setUp(self):
self.sort_sum_gradient = False
self.shape = [5, 10]
def grad(
self,
outputs,
inputs,
grad_outputs=None,
no_grad_vars=None,
retain_graph=None,
create_graph=False,
allow_unused=False,
):
base.set_flags({'FLAGS_sort_sum_gradient': self.sort_sum_gradient})
return base.dygraph.grad(
outputs=outputs,
inputs=inputs,
grad_outputs=grad_outputs,
no_grad_vars=no_grad_vars,
retain_graph=retain_graph,
create_graph=create_graph,
allow_unused=allow_unused,
)
@dygraph_guard
def test_exception(self):
with self.assertRaises(AssertionError):
self.grad(None, None)
shape = self.shape
with self.assertRaises(AssertionError):
self.grad(1, random_var(shape))
with self.assertRaises(AssertionError):
self.grad(random_var(shape), 1)
with self.assertRaises(AssertionError):
self.grad([1], [random_var(shape)])
with self.assertRaises(AssertionError):
self.grad([random_var(shape)], [1])
with self.assertRaises(AssertionError):
self.grad(
[random_var(shape), random_var(shape)],
[random_var(shape)],
[random_var(shape)],
)
with self.assertRaises(AssertionError):
self.grad(
[random_var(shape)], [random_var(shape)], no_grad_vars=[1]
)
with self.assertRaises(AssertionError):
self.grad([random_var(shape)], [random_var(shape)], no_grad_vars=1)
@dygraph_guard
def test_simple_example(self):
x = random_var(self.shape)
x.stop_gradient = False
y = x + 1
for create_graph in [False, True]:
(dx,) = self.grad(
[x], [x], create_graph=create_graph, retain_graph=True
)
self.assertEqual(dx.shape, x.shape)
self.assertTrue(np.all(dx.numpy() == 1))
self.assertNotEqual(dx.stop_gradient, create_graph)
(dx_mul_2,) = self.grad(
[y, x], [x], create_graph=create_graph, retain_graph=True
)
self.assertEqual(dx_mul_2.shape, x.shape)
self.assertTrue(np.all(dx_mul_2.numpy() == 2))
self.assertNotEqual(dx_mul_2.stop_gradient, create_graph)
(none_grad,) = self.grad(
[x], [y], create_graph=create_graph, allow_unused=True
)
self.assertIsNone(none_grad)
(grad_with_none_and_not_none,) = self.grad(
[x, y], [y], create_graph=create_graph
)
self.assertTrue(grad_with_none_and_not_none.shape, x.shape)
self.assertTrue(np.all(grad_with_none_and_not_none.numpy() == 1))
self.assertNotEqual(
grad_with_none_and_not_none.stop_gradient, create_graph
)
@dygraph_guard
def test_example_no_grad_vars(self):
x = random_var(self.shape)
x_np = x.numpy()
numel = x_np.size
x.stop_gradient = False
y1 = F.relu(x)
y2 = F.relu(x)
z = y1 + y2
w = z * z
w_mean = paddle.mean(w)
del y1, z, w
(dx_actual,) = self.grad(
[w_mean], [x], create_graph=True, no_grad_vars=[y2]
)
self.assertFalse(y2.stop_gradient)
self.assertFalse(dx_actual.stop_gradient)
dx_expected = (
1.0
/ float(numel)
* (np.maximum(x_np, 0) + y2.numpy())
* (x_np > 0)
* 2
).astype('float32')
np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
@dygraph_guard
def test_none_one_initial_gradient(self):
numel = 1
for s in self.shape:
numel *= s
half_numel = int(numel / 2)
half_x_positive = np.random.uniform(low=1, high=2, size=[half_numel])
half_x_negative = np.random.uniform(
low=-2, high=-1, size=[numel - half_numel]
)
x_np = np.array(list(half_x_positive) + list(half_x_negative)).astype(
'float32'
)
np.random.shuffle(x_np)
x = paddle.to_tensor(x_np)
x.stop_gradient = False
alpha = 0.2
y = paddle.nn.functional.leaky_relu(x, alpha)
y = y * y
z = y * y
x_np = x.numpy()
relu_x_np = np.maximum(x_np, alpha * x_np).astype('float32')
relu_x_grad_np = ((x_np > 0) + (x_np < 0) * alpha).astype('float32')
dy_expected = (relu_x_np * relu_x_grad_np * 2).astype('float32')
dz_expected = (np.power(relu_x_np, 3) * relu_x_grad_np * 4).astype(
'float32'
)
random_grad_y = random_var(y.shape, low=1, high=2)
random_grad_z = random_var(z.shape, low=1, high=2)
ones_grad_y = np.ones(y.shape).astype('float32')
ones_grad_z = np.ones(z.shape).astype('float32')
original_random_grad_y = random_grad_y.numpy()
original_random_grad_z = random_grad_z.numpy()
for grad_y in [random_grad_y]:
for grad_z in [random_grad_z]:
for create_graph in [False, True]:
(dx_actual,) = self.grad(
outputs=[y, z],
inputs=[x],
grad_outputs=[grad_y, grad_z],
create_graph=create_graph,
retain_graph=True,
)
grad_y_np = (
ones_grad_y if grad_y is None else grad_y.numpy()
)
grad_z_np = (
ones_grad_z if grad_z is None else grad_z.numpy()
)
dx_expected = (
dy_expected * grad_y_np + dz_expected * grad_z_np
)
np.testing.assert_allclose(
dx_actual.numpy(), dx_expected, rtol=1e-05
)
if grad_y is not None:
self.assertTrue(grad_y.stop_gradient)
np.testing.assert_array_equal(
grad_y.numpy(), original_random_grad_y
)
if grad_z is not None:
self.assertTrue(grad_z.stop_gradient)
np.testing.assert_array_equal(
grad_z.numpy(), original_random_grad_z
)
@dygraph_guard
def test_example_with_gradient_accumulation_and_create_graph(self):
x = random_var(self.shape)
x_np = x.numpy()
numel = x_np.size
x.stop_gradient = False
y = F.relu(x)
z = y + 1
w = z * z
w_mean = paddle.mean(w)
del y, z, w
(dx_actual,) = self.grad([w_mean], [x], create_graph=True)
del w_mean
self.assertFalse(dx_actual.stop_gradient)
# Theoretical result based on math calculation
dx_expected = (
1.0 / float(numel) * (np.maximum(x_np, 0) + 1) * (x_np > 0) * 2
).astype('float32')
np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
loss = paddle.mean(dx_actual * dx_actual + x * x)
loss.backward(retain_graph=True)
x_grad_actual = x.gradient()
x_grad_expected = (
2.0
/ float(numel)
* (x_np + dx_expected * (x_np > 0) * 2 / float(numel))
).astype('float32')
np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
for i in range(5):
loss.backward(retain_graph=True)
x_grad_actual = x.gradient()
x_grad_expected = (i + 2) * (
2.0
/ float(numel)
* (x_np + dx_expected * (x_np > 0) * 2 / float(numel))
).astype('float32')
np.testing.assert_allclose(
x_grad_actual, x_grad_expected, rtol=1e-05
)
@dygraph_guard
def test_example_with_gradient_accumulation_and_no_grad_vars(self):
x = random_var(self.shape)
x_np = x.numpy()
numel = x_np.size
x.stop_gradient = False
y1 = F.relu(x)
y2 = F.relu(x)
z = y1 + y2
w = z * z
w_mean = paddle.mean(w)
del y1, z, w
(dx_actual,) = self.grad(
[w_mean],
[x],
retain_graph=True,
create_graph=True,
no_grad_vars=[y2],
)
self.assertFalse(y2.stop_gradient)
self.assertFalse(dx_actual.stop_gradient)
dx_expected = (
1.0
/ float(numel)
* (np.maximum(x_np, 0) + y2.numpy())
* (x_np > 0)
* 2
).astype('float32')
np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
loss = paddle.mean(dx_actual * dx_actual + x * x)
loss.backward()
x_grad_actual = x.gradient()
x_grad_expected = (
2.0
/ float(numel)
* (x_np + dx_expected * (x_np > 0) * 4 / float(numel))
).astype('float32')
np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
@dygraph_guard
def test_example_with_gradient_accumulation_and_not_create_graph(self):
x = random_var(self.shape)
x_np = x.numpy()
numel = x_np.size
x.stop_gradient = False
y = F.relu(x)
z = y + 1
w = z * z
w_mean = paddle.mean(w)
del y, z, w
(dx_actual,) = self.grad([w_mean], [x], create_graph=False)
del w_mean
self.assertTrue(dx_actual.stop_gradient)
dx_expected = (
1.0 / float(numel) * (np.maximum(x_np, 0) + 1) * (x_np > 0) * 2
).astype('float32')
np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
loss = paddle.mean(dx_actual * dx_actual + x * x)
loss.backward()
x_grad_actual = x.gradient()
x_grad_expected = (2.0 * x_np / float(numel)).astype('float32')
np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
class TestDygraphDoubleGradSortGradient(TestDygraphDoubleGrad):
def setUp(self):
self.sort_sum_gradient = True
self.shape = [5, 10]
class TestDygraphDoubleGradVisitedUniq(TestCase):
def test_compare(self):
value = (
np.random.uniform(-0.5, 0.5, 100)
.reshape(10, 2, 5)
.astype("float32")
)
def model_f(input):
linear = paddle.nn.Linear(5, 3)
for i in range(10):
if i == 0:
out = linear(input)
else:
out = out + linear(input)
return out
base.set_flags({'FLAGS_sort_sum_gradient': True})
with base.dygraph.guard():
paddle.seed(123)
if paddle.framework.use_pir_api():
with paddle.pir_utils.OldIrGuard():
# Note: dygraph use self.main_program.global_block().create_parameter(), it's need manual seed to old Program
paddle.framework.random._manual_program_seed(123)
paddle.framework.random._manual_program_seed(123)
else:
paddle.framework.random._manual_program_seed(123)
a = paddle.to_tensor(value)
a.stop_gradient = False
out = model_f(a)
dx = base.dygraph.grad(
outputs=[out],
inputs=[a],
create_graph=False,
only_inputs=True,
allow_unused=False,
)
grad_1 = dx[0].numpy()
with base.dygraph.guard():
paddle.seed(123)
if paddle.framework.use_pir_api():
with paddle.pir_utils.OldIrGuard():
# Note: dygraph use self.main_program.global_block().create_parameter(), it's need manual seed to old Program
paddle.framework.random._manual_program_seed(123)
paddle.framework.random._manual_program_seed(123)
else:
paddle.framework.random._manual_program_seed(123)
a = paddle.to_tensor(value)
a.stop_gradient = False
out = model_f(a)
out.backward()
grad_2 = a.gradient()
np.testing.assert_array_equal(grad_1, grad_2)
class TestDoubleGradResNet(TestCase):
def setUp(self):
paddle.seed(123)
if paddle.framework.use_pir_api():
with paddle.pir_utils.OldIrGuard():
# Note: dygraph use self.main_program.global_block().create_parameter(), it's need manual seed to old Program
paddle.framework.random._manual_program_seed(123)
paddle.framework.random._manual_program_seed(123)
else:
paddle.framework.random._manual_program_seed(123)
self.data = np.random.rand(1, 3, 224, 224).astype(np.float32)
@dygraph_guard
def test_resnet_resnet50(self):
model = resnet50(pretrained=False)
egr_data = paddle.to_tensor(self.data)
egr_data.stop_gradient = False
egr_out = model(egr_data)
egr_preds = paddle.argmax(egr_out, axis=1)
egr_label_onehot = paddle.nn.functional.one_hot(
paddle.to_tensor(egr_preds), num_classes=egr_out.shape[1]
)
egr_target = paddle.sum(egr_out * egr_label_onehot, axis=1)
egr_g = paddle.grad(outputs=egr_target, inputs=egr_out)[0]
egr_g_numpy = egr_g.numpy()
self.assertEqual(list(egr_g_numpy.shape), list(egr_out.shape))
model = resnet50(pretrained=False)
data = paddle.to_tensor(self.data)
data.stop_gradient = False
out = model(data)
preds = paddle.argmax(out, axis=1)
label_onehot = paddle.nn.functional.one_hot(
paddle.to_tensor(preds), num_classes=out.shape[1]
)
target = paddle.sum(out * label_onehot, axis=1)
g = paddle.grad(outputs=target, inputs=out)[0]
g_numpy = g.numpy()
self.assertEqual(list(g_numpy.shape), list(out.shape))
np.testing.assert_array_equal(egr_out, out)
np.testing.assert_array_equal(egr_g_numpy, g_numpy)
@dygraph_guard
def test_resnet_resnet101(self):
model = resnet101(pretrained=False)
egr_data = paddle.to_tensor(self.data)
egr_data.stop_gradient = False
egr_out = model(egr_data)
egr_preds = paddle.argmax(egr_out, axis=1)
egr_label_onehot = paddle.nn.functional.one_hot(
paddle.to_tensor(egr_preds), num_classes=egr_out.shape[1]
)
egr_target = paddle.sum(egr_out * egr_label_onehot, axis=1)
egr_g = paddle.grad(outputs=egr_target, inputs=egr_out)[0]
egr_g_numpy = egr_g.numpy()
self.assertEqual(list(egr_g_numpy.shape), list(egr_out.shape))
model = resnet101(pretrained=False)
data = paddle.to_tensor(self.data)
data.stop_gradient = False
out = model(data)
preds = paddle.argmax(out, axis=1)
label_onehot = paddle.nn.functional.one_hot(
paddle.to_tensor(preds), num_classes=out.shape[1]
)
target = paddle.sum(out * label_onehot, axis=1)
g = paddle.grad(outputs=target, inputs=out)[0]
g_numpy = g.numpy()
self.assertEqual(list(g_numpy.shape), list(out.shape))
np.testing.assert_array_equal(egr_out, out)
np.testing.assert_array_equal(egr_g_numpy, g_numpy)
class TestDoubleGradBasics(TestCase):
def test_matmul(self):
input_numpy = np.ones([3, 3]) * 2
x = paddle.to_tensor(input_numpy, stop_gradient=False, dtype='float32')
y = paddle.to_tensor(input_numpy, stop_gradient=False, dtype='float32')
grad_out = paddle.to_tensor(
np.ones([3, 3]), stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
new_x_g, new_y_g = paddle.grad(
[out], [x, y], [grad_out], retain_graph=True, create_graph=True
)
new_x_g.backward()
out_ref = np.ones([3, 3]) * 12.0
np.testing.assert_array_equal(out.numpy(), out_ref)
new_x_g_ref = np.ones([3, 3]) * 6.0
new_y_g_ref = np.ones([3, 3]) * 6.0
np.testing.assert_array_equal(new_x_g.numpy(), new_x_g_ref)
np.testing.assert_array_equal(new_y_g.numpy(), new_y_g_ref)
x_grad_ref = np.ones([3, 3]) * 0.0
np.testing.assert_array_equal(x.grad.numpy(), x_grad_ref)
y_grad_ref = np.ones([3, 3]) * 3.0
np.testing.assert_array_equal(y.grad.numpy(), y_grad_ref)
grad_out_grad_ref = np.ones([3, 3]) * 6.0
np.testing.assert_array_equal(grad_out.grad.numpy(), grad_out_grad_ref)
class TestDygraphDoubleGradMatmul(TestCase):
# case1: ddy is none, no broadcast,dims != 1
def test_matmul_double_grad_case1(self):
input_numpy_x = np.random.random([3, 3]).astype('float32')
input_numpy_y = np.random.random([3, 3]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([3, 3]), stop_gradient=False, dtype='float32'
)
(dx, dy) = paddle.grad(
[out], [x, y], [dout], retain_graph=True, create_graph=True
)
ddx = paddle.to_tensor(
np.ones([3, 3]), stop_gradient=False, dtype='float32'
)
ddy = ddx
dx_double_grad, dy_double_grad, ddout = paddle.grad(
[dx, dy],
[x, y, dout],
[ddx, ddy],
retain_graph=True,
create_graph=True,
)
return dx_double_grad, dy_double_grad, ddout
def expected():
dx_double_grad_expected = np.matmul(
np.ones([3, 3], dtype="float32"),
np.ones([3, 3], dtype="float32"),
)
dy_double_grad_expected = np.matmul(
np.ones([3, 3], dtype="float32"),
np.ones([3, 3], dtype="float32"),
)
ddout_expected1 = np.matmul(
np.ones([3, 3], dtype="float32"), input_numpy_y
)
ddout_expected2 = np.matmul(
input_numpy_x, np.ones([3, 3], dtype="float32")
)
ddout_expected = ddout_expected1 + ddout_expected2
return (
dx_double_grad_expected,
dy_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case2: ddx is none,no broadcast, dims != 1
def test_matmul_double_grad_case2(self):
input_numpy_x = np.random.random([3, 3]).astype('float32')
input_numpy_y = np.random.random([3, 3]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([3, 3]), stop_gradient=False, dtype='float32'
)
(dy,) = paddle.grad(
[out], [y], [dout], retain_graph=True, create_graph=True
)
ddy = paddle.to_tensor(
np.ones([3, 3]), stop_gradient=False, dtype='float32'
)
# when x isnot be differentiate in first grad dy in second grad could be None in composite op
dx_double_grad, ddout = paddle.grad(
[dy],
[x, dout],
[ddy],
retain_graph=True,
create_graph=True,
)
return dx_double_grad, ddout
def expected():
dx_double_grad_expected = np.matmul(
np.ones([3, 3], dtype="float32"),
np.ones([3, 3], dtype="float32"),
)
ddout_expected = np.matmul(
input_numpy_x, np.ones([3, 3], dtype="float32")
)
return (
dx_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case3: ddx is none, dims = 1
def test_matmul_double_grad_case3(self):
input_numpy_x = np.random.random([3]).astype('float32')
input_numpy_y = np.random.random([3]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([1]), stop_gradient=False, dtype='float32'
)
(dy,) = paddle.grad(
[out], [y], [dout], retain_graph=True, create_graph=True
)
ddy = paddle.to_tensor(
np.ones([3]), stop_gradient=False, dtype='float32'
)
# when x is not be differentiate in first grad, dy from second grad could be None in composite api.
dx_double_grad, ddout = paddle.grad(
[dy],
[x, dout],
[ddy],
retain_graph=True,
create_graph=True,
)
return dx_double_grad, ddout
def expected():
dx_double_grad_expected = np.ones([3], dtype="float32")
ddout_expected = np.matmul(
input_numpy_x, np.ones([3], dtype="float32")
)
return (
dx_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case4: ddy is none, dims = 1
def test_matmul_double_grad_case4(self):
input_numpy_x = np.random.random([3]).astype('float32')
input_numpy_y = np.random.random([3]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([1]), stop_gradient=False, dtype='float32'
)
(dx,) = paddle.grad(
[out], [x], [dout], retain_graph=True, create_graph=True
)
ddx = paddle.to_tensor(
np.ones([3]), stop_gradient=False, dtype='float32'
)
# when y is not be differentiate in first grad, dx from second grad could be None in composite api.
dy_double_grad, ddout = paddle.grad(
[dx],
[y, dout],
[ddx],
retain_graph=True,
create_graph=True,
)
return dy_double_grad, ddout
def expected():
dy_double_grad_expected = np.ones([3], dtype="float32")
ddout_expected = np.matmul(
input_numpy_y, np.ones([3], dtype="float32")
)
return (
dy_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case5: ddx is none, broadcast, dims != 1
def test_matmul_double_grad_case5(self):
input_numpy_x = np.random.random([2, 1]).astype('float32')
input_numpy_y = np.random.random([1]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([2]), stop_gradient=False, dtype='float32'
)
(dy,) = paddle.grad(
[out], [y], [dout], retain_graph=True, create_graph=True
)
ddy = paddle.to_tensor(
np.ones([1]), stop_gradient=False, dtype='float32'
)
dx_double_grad, ddout = paddle.grad(
[dy],
[x, dout],
[ddy],
retain_graph=True,
create_graph=True,
)
return dx_double_grad, ddout
def expected():
dx_double_grad_expected = np.ones([2, 1], dtype="float32")
ddout_expected = np.matmul(
input_numpy_x, np.ones([1], dtype="float32")
)
return (
dx_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case6: ddy is none, broadcast, dims != 1
def test_matmul_double_grad_case6(self):
input_numpy_x = np.random.random([2, 1]).astype('float32')
input_numpy_y = np.random.random([1]).astype('float32')
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='float32'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='float32'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([2]), stop_gradient=False, dtype='float32'
)
(dx,) = paddle.grad(
[out], [x], [dout], retain_graph=True, create_graph=True
)
ddx = paddle.to_tensor(
np.ones([2, 1]), stop_gradient=False, dtype='float32'
)
dy_double_grad, ddout = paddle.grad(
[dx],
[y, dout],
[ddx],
retain_graph=True,
create_graph=True,
)
return dy_double_grad, ddout
def expected():
dy_double_grad_expected = np.ones([1], dtype="float32") * 2
ddout_expected = np.ones([2], dtype="float32") * input_numpy_y[0]
return (
dy_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if paddle.is_compiled_with_cuda() or is_custom_device():
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# TODO(Ruting) test complex dtype when composite api support
'''
# case7: ddx is none, dims = 1, complex dtype
def test_matmul_double_grad_case7(self):
input_numpy_x = np.random.random([3]).astype(
'float32'
) + 1j * np.random.random([3]).astype('float32')
input_numpy_y = np.random.random([3]).astype(
'float32'
) + 1j * np.random.random([3]).astype('float32')
input_numpy_y_conj = np.conjugate(input_numpy_y)
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='complex64'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='complex64'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([1]), stop_gradient=False, dtype='complex64'
)
(dx,) = paddle.grad(
[out], [x], [dout], retain_graph=True, create_graph=True
)
ddx = paddle.to_tensor(
np.ones([3]), stop_gradient=False, dtype='complex64'
)
# when y is not be differentiate in first grad, dx from second grad could be None in composite api.
dy_double_grad, ddout = paddle.grad(
[dx],
[y, dout],
[ddx],
retain_graph=True,
create_graph=True,
)
return dy_double_grad, ddout
def expected():
dy_double_grad_expected = np.ones(
[3], dtype="float32"
) + 0j * np.ones([3], dtype="float32")
ddout_expected = np.matmul(
input_numpy_y_conj, np.ones([3], dtype="float32")
)
return (
dy_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if (paddle.is_compiled_with_cuda() or is_custom_device()):
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
# case8: ddy is none, dims = 1, complex dtype
def test_matmul_double_grad_case8(self):
input_numpy_x = np.random.random([3]).astype(
'float32'
) + 1j * np.random.random([3]).astype('float32')
input_numpy_y = np.random.random([3]).astype(
'float32'
) + 1j * np.random.random([3]).astype('float32')
input_numpy_x_conj = np.conjugate(input_numpy_x)
def actual():
x = paddle.to_tensor(
input_numpy_x, stop_gradient=False, dtype='complex64'
)
y = paddle.to_tensor(
input_numpy_y, stop_gradient=False, dtype='complex64'
)
out = paddle.matmul(x, y, False, False)
dout = paddle.to_tensor(
np.ones([1]), stop_gradient=False, dtype='complex64'
)
(dy,) = paddle.grad(
[out], [y], [dout], retain_graph=True, create_graph=True
)
ddy = paddle.to_tensor(
np.ones([3]), stop_gradient=False, dtype='complex64'
)
dx_double_grad, ddout = paddle.grad(
[dy],
[x, dout],
[ddy],
retain_graph=True,
create_graph=True,
)
return dx_double_grad, ddout
def expected():
dx_double_grad_expected = np.ones([3], dtype="float32")
ddout_expected = np.matmul(
input_numpy_x_conj, np.ones([3], dtype="float32")
)
return (
dx_double_grad_expected,
ddout_expected,
)
expected_results = expected()
places = ["cpu"]
if (paddle.is_compiled_with_cuda() or is_custom_device()):
places.append(get_device())
for place in places:
paddle.device.set_device(place)
actual_results = actual()
for expected_result, actual_result in zip(
expected_results, actual_results
):
np.testing.assert_allclose(
expected_result, actual_result, rtol=1e-6
)
'''
def test_value_error(self):
def test():
import paddle
from paddle import nn
model = nn.Sequential(nn.Linear(3, 4))
x = paddle.randn([4, 1])
y = paddle.randn([4, 1])
z = paddle.randn([4, 1])
x.stop_gradient = False
y.stop_gradient = False
z.stop_gradient = False
out = model(paddle.concat((x, y, z), axis=1))
data = {
"x": x,
"y": y,
"z": z,
"u": out[:, 0:1],
"v": out[:, 1:2],
"w": out[:, 2:3],
"p": out[:, 3:4],
}
v = out[:, 1:2]
z = paddle.grad(v, x, create_graph=True)[0]
zz = paddle.grad(z, x, create_graph=True)[0]
np.testing.assert_equal(zz.numpy(), paddle.zeros_like(zz).numpy())
if __name__ == '__main__':
unittest.main()