Skip to content

Commit b1c2473

Browse files
weisy11AnnaTrainingG
authored andcommitted
Add grad grad for AvgPool2D (PaddlePaddle#35388)
* add pool2d grad grad * dbg * add unittest * update format * add more unittests * dbg
1 parent e7642ac commit b1c2473

File tree

5 files changed

+159
-1
lines changed

5 files changed

+159
-1
lines changed

paddle/fluid/operators/pool_cudnn_op.cu.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,20 @@ class PoolCUDNNGradOpKernel : public framework::OpKernel<T> {
505505
}
506506
};
507507

508+
template <typename T>
509+
class PoolCUDNNGradGradOpKernel : public PoolCUDNNOpKernel<T> {
510+
public:
511+
void Compute(const framework::ExecutionContext &ctx) const override {
512+
std::string pooling_type = ctx.Attr<std::string>("pooling_type");
513+
if (pooling_type == "max") {
514+
PADDLE_THROW(platform::errors::InvalidArgument(
515+
"Pool op grad grad only supports avgpool."));
516+
} else {
517+
PoolCUDNNOpKernel<T>::Compute(ctx);
518+
}
519+
}
520+
};
521+
508522
} // namespace operators
509523
} // namespace paddle
510524

@@ -534,6 +548,10 @@ REGISTER_OP_KERNEL(pool2d_grad, CUDNN, plat::CUDAPlace,
534548
ops::PoolCUDNNGradOpKernel<float>,
535549
ops::PoolCUDNNGradOpKernel<double>,
536550
ops::PoolCUDNNGradOpKernel<plat::float16>);
551+
REGISTER_OP_KERNEL(pool2d_grad_grad, CUDNN, plat::CUDAPlace,
552+
ops::PoolCUDNNGradGradOpKernel<float>,
553+
ops::PoolCUDNNGradGradOpKernel<double>,
554+
ops::PoolCUDNNGradGradOpKernel<plat::float16>);
537555

538556
REGISTER_OP_KERNEL(pool3d, CUDNN, plat::CUDAPlace,
539557
ops::PoolCUDNNOpKernel<float>,

paddle/fluid/operators/pool_op.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,20 @@ The input(X) size and output(Out) size may be different.
469469
)DOC");
470470
}
471471

472+
template <typename T>
473+
class Pool2dOpGradGradMaker : public framework::SingleGradOpMaker<T> {
474+
public:
475+
using framework::SingleGradOpMaker<T>::SingleGradOpMaker;
476+
477+
protected:
478+
void Apply(GradOpPtr<T> grad_op) const override {
479+
grad_op->SetType("pool2d_grad_grad");
480+
grad_op->SetInput("X", this->OutputGrad(framework::GradVarName("X")));
481+
grad_op->SetOutput("Out", this->InputGrad(framework::GradVarName("Out")));
482+
grad_op->SetAttrMap(this->Attrs());
483+
}
484+
};
485+
472486
class PoolOpInferVarType : public framework::PassInDtypeAndVarTypeToOutput {
473487
protected:
474488
std::unordered_map<std::string, std::string>& GetInputOutputWithSameType()
@@ -687,14 +701,21 @@ REGISTER_OPERATOR(
687701
pool2d, ops::PoolOp, ops::Pool2dOpMaker, ops::PoolOpInferVarType,
688702
paddle::framework::DefaultGradOpMaker<paddle::framework::OpDesc, true>,
689703
paddle::framework::DefaultGradOpMaker<paddle::imperative::OpBase, true>);
690-
REGISTER_OPERATOR(pool2d_grad, ops::PoolOpGrad);
704+
REGISTER_OPERATOR(pool2d_grad, ops::PoolOpGrad,
705+
ops::Pool2dOpGradGradMaker<paddle::framework::OpDesc>,
706+
ops::Pool2dOpGradGradMaker<paddle::imperative::OpBase>);
707+
REGISTER_OPERATOR(pool2d_grad_grad, ops::PoolOp);
691708

692709
REGISTER_OP_CPU_KERNEL(
693710
pool2d, ops::PoolKernel<paddle::platform::CPUDeviceContext, float>,
694711
ops::PoolKernel<paddle::platform::CPUDeviceContext, double>);
695712
REGISTER_OP_CPU_KERNEL(
696713
pool2d_grad, ops::PoolGradKernel<paddle::platform::CPUDeviceContext, float>,
697714
ops::PoolGradKernel<paddle::platform::CPUDeviceContext, double>);
715+
REGISTER_OP_CPU_KERNEL(
716+
pool2d_grad_grad,
717+
ops::PoolGradGradKernel<paddle::platform::CPUDeviceContext, float>,
718+
ops::PoolGradGradKernel<paddle::platform::CPUDeviceContext, double>);
698719

699720
REGISTER_OPERATOR(
700721
pool3d, ops::PoolOp, ops::Pool3dOpMaker, ops::PoolOpInferVarType,

paddle/fluid/operators/pool_op.cu

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ REGISTER_OP_CUDA_KERNEL(
2828
ops::PoolGradKernel<paddle::platform::CUDADeviceContext,
2929
paddle::platform::float16>);
3030

31+
REGISTER_OP_CUDA_KERNEL(
32+
pool2d_grad_grad,
33+
ops::PoolGradGradKernel<paddle::platform::CUDADeviceContext, float>,
34+
ops::PoolGradGradKernel<paddle::platform::CUDADeviceContext, double>,
35+
ops::PoolGradGradKernel<paddle::platform::CUDADeviceContext,
36+
paddle::platform::float16>);
37+
3138
REGISTER_OP_CUDA_KERNEL(
3239
pool3d, ops::PoolKernel<paddle::platform::CUDADeviceContext, float>,
3340
ops::PoolKernel<paddle::platform::CUDADeviceContext, double>,

paddle/fluid/operators/pool_op.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,5 +357,19 @@ class PoolGradKernel : public framework::OpKernel<T> {
357357
}
358358
};
359359

360+
template <typename DeviceContext, typename T>
361+
class PoolGradGradKernel : public PoolKernel<DeviceContext, T> {
362+
public:
363+
void Compute(const framework::ExecutionContext& context) const override {
364+
std::string pooling_type = context.Attr<std::string>("pooling_type");
365+
if (pooling_type == "max") {
366+
PADDLE_THROW(platform::errors::InvalidArgument(
367+
"Pool op grad grad only supports avgpool."));
368+
} else {
369+
PoolKernel<DeviceContext, T>::Compute(context);
370+
}
371+
}
372+
};
373+
360374
} // namespace operators
361375
} // namespace paddle

python/paddle/fluid/tests/unittests/test_nn_grad.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,5 +381,103 @@ def test_grad(self):
381381
self.func(p)
382382

383383

384+
class TestAvgPool2DDoubleGradCheckCase1(unittest.TestCase):
385+
@prog_scope()
386+
def func(self, place):
387+
input_NCHW = fluid.layers.data(
388+
name="input_NCHW",
389+
shape=[2, 3, 5, 5],
390+
append_batch_size=False,
391+
dtype="float32")
392+
393+
input_NCHW.persistable = True
394+
y = layers.pool2d(input_NCHW, pool_size=2, pool_type="avg")
395+
x_arr = np.random.uniform(-1, 1, [2, 3, 5, 5]).astype(np.float32)
396+
397+
gradient_checker.double_grad_check(
398+
[input_NCHW], y, x_init=x_arr, place=place, eps=0.05)
399+
400+
def test_grad(self):
401+
places = [fluid.CPUPlace()]
402+
if core.is_compiled_with_cuda():
403+
places.append(fluid.CUDAPlace(0))
404+
for p in places:
405+
self.func(p)
406+
407+
408+
class TestAvgPool2DDoubleGradCheckCase2(unittest.TestCase):
409+
@prog_scope()
410+
def func(self, place):
411+
input_NHWC = fluid.layers.data(
412+
name="input_NHWC",
413+
shape=[2, 5, 5, 3],
414+
append_batch_size=False,
415+
dtype="float32")
416+
417+
input_NHWC.persistable = True
418+
y = layers.pool2d(
419+
input_NHWC, pool_size=2, pool_type="avg", data_format="NHWC")
420+
x_arr = np.random.uniform(-1, 1, [2, 5, 5, 3]).astype(np.float32)
421+
422+
gradient_checker.double_grad_check(
423+
[input_NHWC], y, x_init=x_arr, place=place, eps=0.05)
424+
425+
def test_grad(self):
426+
places = [fluid.CPUPlace()]
427+
if core.is_compiled_with_cuda():
428+
places.append(fluid.CUDAPlace(0))
429+
for p in places:
430+
self.func(p)
431+
432+
433+
class TestAvgPool2DDoubleGradCheckCase3(unittest.TestCase):
434+
@prog_scope()
435+
def func(self, place):
436+
input_NCHW = fluid.layers.data(
437+
name="input_NCHW",
438+
shape=[2, 3, 5, 5],
439+
append_batch_size=False,
440+
dtype="float32")
441+
442+
input_NCHW.persistable = True
443+
y = layers.pool2d(
444+
input_NCHW, pool_size=2, pool_type="avg", pool_padding=[1, 1])
445+
x_arr = np.random.uniform(-1, 1, [2, 3, 5, 5]).astype(np.float32)
446+
447+
gradient_checker.double_grad_check(
448+
[input_NCHW], y, x_init=x_arr, place=place, eps=0.05)
449+
450+
def test_grad(self):
451+
places = [fluid.CPUPlace()]
452+
if core.is_compiled_with_cuda():
453+
places.append(fluid.CUDAPlace(0))
454+
for p in places:
455+
self.func(p)
456+
457+
458+
class TestAvgPool2DDoubleGradCheckCase4(unittest.TestCase):
459+
@prog_scope()
460+
def func(self, place):
461+
input_NCHW = fluid.layers.data(
462+
name="input_NCHW",
463+
shape=[2, 3, 5, 5],
464+
append_batch_size=False,
465+
dtype="float32")
466+
467+
input_NCHW.persistable = True
468+
y = layers.pool2d(input_NCHW, pool_size=[4, 4], pool_type="avg")
469+
x_arr = np.random.uniform(-1, 1, [2, 3, 5, 5]).astype(np.float32)
470+
471+
gradient_checker.double_grad_check(
472+
[input_NCHW], y, x_init=x_arr, place=place, eps=0.05)
473+
474+
def test_grad(self):
475+
places = [fluid.CPUPlace()]
476+
if core.is_compiled_with_cuda():
477+
places.append(fluid.CUDAPlace(0))
478+
for p in places:
479+
self.func(p)
480+
481+
384482
if __name__ == "__main__":
385483
unittest.main()

0 commit comments

Comments
 (0)