diff --git a/paddle/operators/dropout_op.cc b/paddle/operators/dropout_op.cc index 74e72cf1168c4712fbcc54c7c2a495346db1e8b3..b111b9fccb2310bd5fb92bda878a497c51f62ce0 100644 --- a/paddle/operators/dropout_op.cc +++ b/paddle/operators/dropout_op.cc @@ -26,7 +26,6 @@ class DropoutOp : public framework::OperatorWithKernel { protected: void InferShape(const framework::InferShapeContext &ctx) const override { - // validity check PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("X"), "Input(X) must not be null."); PADDLE_ENFORCE_GE(ctx.Attr("dropout_prob"), 0); PADDLE_ENFORCE_LE(ctx.Attr("dropout_prob"), 1); @@ -34,10 +33,11 @@ class DropoutOp : public framework::OperatorWithKernel { PADDLE_ENFORCE(ctx.Attr("is_training") == 0 || ctx.Attr("is_training") == 1); - // resize auto dims = ctx.Input("X")->dims(); ctx.Output("Out")->Resize(dims); - ctx.Output("Mask")->Resize(dims); + if (ctx.Attr("is_training") == 1) { + ctx.Output("Mask")->Resize(dims); + } } }; @@ -75,24 +75,27 @@ class DropoutOpGrad : public framework::OperatorWithKernel { protected: void InferShape(const framework::InferShapeContext &ctx) const override { - // validity check + PADDLE_ENFORCE_EQ(ctx.Attr("is_training"), 1, + "GradOp is only callable when is_training is true"); + PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("X"), "Input(X) must not be null."); PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("Mask"), "Mask must not be null."); PADDLE_ENFORCE_NOT_NULL(ctx.InputVar(framework::GradVarName("Out")), "Input(Out@GRAD) must not be null."); + PADDLE_ENFORCE_GE(ctx.Attr("dropout_prob"), 0); PADDLE_ENFORCE_LE(ctx.Attr("dropout_prob"), 1); // TODO(xinghai-sun): remove this check after swtiching to bool PADDLE_ENFORCE(ctx.Attr("is_training") == 0 || ctx.Attr("is_training") == 1); auto x_dims = ctx.Input("X")->dims(); - auto mask_dims = ctx.Input("Mask")->dims(); auto out_dims = ctx.Input(framework::GradVarName("Out"))->dims(); PADDLE_ENFORCE_EQ(x_dims, out_dims, "Dimensions of Input(X) and Out@Grad must be the same."); + auto mask_dims = ctx.Input("Mask")->dims(); PADDLE_ENFORCE_EQ(x_dims, mask_dims, "Dimensions of Input(X) and Mask must be the same."); - // resize + auto *x_grad = ctx.Output(framework::GradVarName("X")); x_grad->Resize(x_dims); } diff --git a/paddle/operators/dropout_op.cu b/paddle/operators/dropout_op.cu index f5fbad5ca0af6d265dc218e08d6552018c5319bd..186237fb238add37f32403309a0f7e8a9846d335 100644 --- a/paddle/operators/dropout_op.cu +++ b/paddle/operators/dropout_op.cu @@ -53,26 +53,24 @@ class GPUDropoutKernel : public framework::OpKernel { auto* x = context.Input("X"); auto* y = context.Output("Out"); y->mutable_data(context.GetPlace()); - auto* mask = context.Output("Mask"); - auto* mask_data = mask->mutable_data(context.GetPlace()); - AttrType dropout_prob = context.Attr("dropout_prob"); auto X = EigenMatrix::Reshape(*x, 1); auto Y = EigenMatrix::Reshape(*y, 1); - auto M = EigenMatrix::Reshape(*mask, 1); auto place = context.GetEigenDevice(); - int size = framework::product(mask->dims()); if (context.Attr("is_training") == 1) { + auto* mask = context.Output("Mask"); + auto* mask_data = mask->mutable_data(context.GetPlace()); + int size = framework::product(mask->dims()); int seed = context.Attr("seed"); thrust::counting_iterator index_sequence_begin(0); thrust::transform(index_sequence_begin, index_sequence_begin + size, thrust::device_ptr(mask_data), MaskGenerator(dropout_prob, seed)); + auto M = EigenMatrix::Reshape(*mask, 1); Y.device(place) = X * M; } else { - cudaMemset(mask_data, 0, sizeof(T) * size); Y.device(place) = X * dropout_prob; } } diff --git a/paddle/operators/dropout_op.h b/paddle/operators/dropout_op.h index 00fdfb4c5f13d6abcceec682b09ddb2f211f5f41..82eafee0e0e7db7b4b4ae5405f37146d061aefd5 100644 --- a/paddle/operators/dropout_op.h +++ b/paddle/operators/dropout_op.h @@ -31,14 +31,13 @@ class CPUDropoutKernel : public framework::OpKernel { void Compute(const framework::ExecutionContext& context) const override { auto* x = context.Input("X"); auto* y = context.Output("Out"); - auto* mask = context.Output("Mask"); - auto* mask_data = mask->mutable_data(context.GetPlace()); - auto* y_data = y->mutable_data(context.GetPlace()); const auto* x_data = x->data(); - + auto* y_data = y->mutable_data(context.GetPlace()); AttrType dropout_prob = context.Attr("dropout_prob"); if (context.Attr("is_training") == 1) { + auto* mask = context.Output("Mask"); + auto* mask_data = mask->mutable_data(context.GetPlace()); int seed = context.Attr("seed"); std::minstd_rand engine; engine.seed(seed); @@ -54,8 +53,6 @@ class CPUDropoutKernel : public framework::OpKernel { } } } else { - size_t size = framework::product(mask->dims()); - memset(mask_data, 0, sizeof(T) * size); auto X = EigenMatrix::Reshape(*x, 1); auto Y = EigenMatrix::Reshape(*y, 1); auto place = context.GetEigenDevice(); @@ -69,7 +66,8 @@ class DropoutGradKernel : public framework::OpKernel { public: void Compute(const framework::ExecutionContext& context) const override { PADDLE_ENFORCE_EQ(context.Attr("is_training"), 1, - "Only callable when is_training is true"); + "GradOp is only callable when is_training is true"); + auto* grad_x = context.Output(framework::GradVarName("X")); auto* grad_y = context.Input(framework::GradVarName("Out")); auto* mask = context.Input("Mask"); diff --git a/python/paddle/v2/framework/tests/test_dropout_op.py b/python/paddle/v2/framework/tests/test_dropout_op.py index d49952492947f53cd5a416f6999640023cbdf44e..3638fee1a1c26195791bc1f5a46dd749da0aee95 100644 --- a/python/paddle/v2/framework/tests/test_dropout_op.py +++ b/python/paddle/v2/framework/tests/test_dropout_op.py @@ -38,10 +38,7 @@ class TestDropoutOp4(OpTest): self.op_type = "dropout" self.inputs = {'X': np.random.random((32, 64)).astype("float32")} self.attrs = {'dropout_prob': 0.35, 'is_training': 0} - self.outputs = { - 'Out': self.inputs['X'] * self.attrs['dropout_prob'], - 'Mask': np.zeros((32, 64)) - } + self.outputs = {'Out': self.inputs['X'] * self.attrs['dropout_prob']} def test_check_output(self): self.check_output() @@ -52,10 +49,7 @@ class TestDropoutOp5(OpTest): self.op_type = "dropout" self.inputs = {'X': np.random.random((32, 64, 3)).astype("float32")} self.attrs = {'dropout_prob': 0.75, 'is_training': 0} - self.outputs = { - 'Out': self.inputs['X'] * self.attrs['dropout_prob'], - 'Mask': np.zeros((32, 64, 3)) - } + self.outputs = {'Out': self.inputs['X'] * self.attrs['dropout_prob']} def test_check_output(self): self.check_output()