Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions paddle/phi/kernels/funcs/activation_functor.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ struct CosDoubleGradFunctor : public BaseActivationFunctor<T> {
const DenseTensor* ddX,
DenseTensor* dX,
DenseTensor* ddOut) const {
auto* d = dev.eigen_device();
auto* device = dev.eigen_device();
auto d2d1x = EigenVector<T>::Flatten(
GET_DATA_SAFELY(ddX, "Input", "d2d1x", "CosDoubleGrad"));
auto x = EigenVector<T>::Flatten(
Expand All @@ -407,21 +407,17 @@ struct CosDoubleGradFunctor : public BaseActivationFunctor<T> {
// calculate d2x first, so d2d1y can inplace d2d1x
auto d2x = EigenVector<T>::Flatten(
GET_DATA_SAFELY(dX, "Output", "d2x", "CosDoubleGrad"));
if (ddOut) {
if (dOut) {
auto d1y = EigenVector<T>::Flatten(
GET_DATA_SAFELY(dOut, "Output", "d1y", "CosDoubleGrad"));
d2x.device(*d) = -d2d1x * x.unaryExpr(Cosine<T>()) * d1y;
} else {
d2x.device(*d) = x * static_cast<T>(0);
}
if (dX) {
auto d1y = EigenVector<T>::Flatten(
GET_DATA_SAFELY(dOut, "Output", "d1y", "CosDoubleGrad"));
d2x.device(*device) = -d2d1x * x.unaryExpr(Cosine<T>()) * d1y;
}

if (dX) {
if (ddOut) {
// calculate d2d1y
auto d2d1y = EigenVector<T>::Flatten(
GET_DATA_SAFELY(ddOut, "Output", "d2d1y", "CosDoubleGrad"));
d2d1y.device(*d) = -d2d1x * x.unaryExpr(Sine<T>());
d2d1y.device(*device) = -d2d1x * x.unaryExpr(Sine<T>());
}
}
static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; }
Expand Down
47 changes: 47 additions & 0 deletions test/legacy_test/test_activation_nn_grad.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import gradient_checker
import numpy as np
from decorator_helper import prog_scope
from utils import dygraph_guard, static_guard

import paddle
import paddle.nn.functional as F
Expand Down Expand Up @@ -544,6 +545,52 @@ def test_grad(self):
self.func(p)


class TestCosDoubleGradCheck2(unittest.TestCase):
@test_with_pir_api
def _check_cos_double_dynamic(self, place):
with dygraph_guard():
x = paddle.randn([64, 64])
x = paddle.to_tensor(x, place=place, stop_gradient=False)
y = paddle.cos(x)
dx = paddle.grad(y, x, create_graph=True)
dxx_result = paddle.grad(dx, x)[0]
dxx_expected = -paddle.cos(x)
np.testing.assert_allclose(
dxx_result.numpy(),
dxx_expected.numpy(),
1e-6,
1e-6,
)

@test_with_pir_api
def _check_cos_double_static(self, place):
x_data = np.random.randn(64, 64).astype("float32")
with static_guard():
main_prog = paddle.static.Program()
starup_prog = paddle.static.Program()
with paddle.static.program_guard(main_prog, starup_prog):
x = paddle.assign(x_data)
x.stop_gradient = False
y = paddle.cos(x)
dx = paddle.static.gradients(y, x)
dxx = paddle.static.gradients(dx, x)[0]

exe = paddle.static.Executor(place)
exe.run(starup_prog)
(dxx_result,) = exe.run(main_prog, fetch_list=[dxx])
dxx_expected = -np.cos(x_data)
np.testing.assert_allclose(dxx_result, dxx_expected, 1e-6, 1e-6)

def test_cos_double_grad(self):
places = [base.CPUPlace()]
if core.is_compiled_with_cuda():
places.append(base.CUDAPlace(0))

for place in places:
self._check_cos_double_dynamic(place)
self._check_cos_double_static(place)


class TestPowDoubleGradCheck1(unittest.TestCase):
def pow_wrapper(self, x):
return paddle.pow(x[0], 2)
Expand Down