diff --git a/lite/kernels/x86/CMakeLists.txt b/lite/kernels/x86/CMakeLists.txt index 75a95d1c91c7e8914a9051c93e8b3c6ed77e1bb2..3d79dc3dfee80613c39f51323e7ba61adcf7cd8a 100644 --- a/lite/kernels/x86/CMakeLists.txt +++ b/lite/kernels/x86/CMakeLists.txt @@ -100,3 +100,4 @@ lite_cc_test(test_sequence_concat_compute_x86 SRCS sequence_concat_compute_test. lite_cc_test(test_var_conv_2d_compute_x86 SRCS var_conv_2d_compute_test.cc DEPS var_conv_2d_compute_x86) #lite_cc_test(test_attention_padding_mask_compute_x86 SRCS attention_padding_mask_compute_test.cc DEPS attention_padding_mask_compute_x86) lite_cc_test(test_sequence_arithmetic_compute_x86 SRCS sequence_arithmetic_compute_test.cc DEPS sequence_arithmetic_compute_x86) +lite_cc_test(test_leaky_relu_compute_x86 SRCS leaky_relu_compute_test.cc DEPS activation_compute_x86) diff --git a/lite/kernels/x86/activation_compute.cc b/lite/kernels/x86/activation_compute.cc index f2f911dd7d037a3f4e0f28592cff07383c8a49b6..2910364f37b74d94977e2397e31eb97fd367825e 100644 --- a/lite/kernels/x86/activation_compute.cc +++ b/lite/kernels/x86/activation_compute.cc @@ -36,6 +36,17 @@ REGISTER_LITE_KERNEL(relu, .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) .Finalize(); +// float +REGISTER_LITE_KERNEL(leaky_relu, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::LeakyReluCompute, + def) + .BindInput("X", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); + // float REGISTER_LITE_KERNEL(tanh, kX86, diff --git a/lite/kernels/x86/activation_compute.h b/lite/kernels/x86/activation_compute.h index 14d0ffe000311c87dac513a65f731e9654042db2..34a932ed1726b5b99337847b22e0a168e0290c84 100644 --- a/lite/kernels/x86/activation_compute.h +++ b/lite/kernels/x86/activation_compute.h @@ -117,6 +117,40 @@ class ReluCompute : public KernelLite { virtual ~ReluCompute() = default; }; +template +struct LeakyReluFunctor { + float alpha; + explicit LeakyReluFunctor(float alpha_) : alpha(alpha_) {} + + template + void operator()(Device d, X x, Out out) const { + out.device(d) = x.cwiseMax(static_cast(alpha) * x); + } +}; + +template +class LeakyReluCompute : public KernelLite { + public: + using param_t = operators::ActivationParam; + + void Run() override { + auto& param = *param_.get_mutable(); + + param.Out->template mutable_data(); + auto X = param.X; + auto Out = param.Out; + auto place = lite::fluid::EigenDeviceType(); + CHECK(X); + CHECK(Out); + auto x = lite::fluid::EigenVector::Flatten(*X); + auto out = lite::fluid::EigenVector::Flatten(*Out); + LeakyReluFunctor functor(param.Leaky_relu_alpha); + functor(place, x, out); + } + + virtual ~LeakyReluCompute() = default; +}; + // tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) template struct TanhFunctor : public BaseActivationFunctor { diff --git a/lite/kernels/x86/layer_norm_compute_test.cc b/lite/kernels/x86/layer_norm_compute_test.cc index fbac39505204b3799f6c5274f80690196e83a725..a5244bcc6f2c561b5eac2fc74b1cc8c5f12417d6 100644 --- a/lite/kernels/x86/layer_norm_compute_test.cc +++ b/lite/kernels/x86/layer_norm_compute_test.cc @@ -155,7 +155,6 @@ TEST(layer_norm_x86, run_test) { ref(&x, &Scale, &Bias, &out, &Mean, &Var, begin_norm_axis, epsilon); for (int j = 0; j < out.dims().production(); ++j) { EXPECT_NEAR(out_data[j], ref_data[j], 1e-5); - // LOG(INFO) << out_data[j]; } LOG(INFO) << *mean_data; LOG(INFO) << *var_data; diff --git a/lite/kernels/x86/leaky_relu_compute_test.cc b/lite/kernels/x86/leaky_relu_compute_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..0885fb00e3bf4f1c0383e06f5e4da7c919f21e30 --- /dev/null +++ b/lite/kernels/x86/leaky_relu_compute_test.cc @@ -0,0 +1,86 @@ +// Copyright (c) 2019 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. + +#include +#include +#include +#include "lite/core/op_registry.h" +#include "lite/kernels/x86/activation_compute.h" + +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +TEST(leaky_relu_x86, retrive_op) { + auto leaky_relu = + KernelRegistry::Global().Create( + "leaky_relu"); + ASSERT_FALSE(leaky_relu.empty()); + ASSERT_TRUE(leaky_relu.front()); +} + +TEST(leaky_relu_x86, init) { + LeakyReluCompute leaky_relu; + ASSERT_EQ(leaky_relu.precision(), PRECISION(kFloat)); + ASSERT_EQ(leaky_relu.target(), TARGET(kX86)); +} + +TEST(leaky_relu_x86, run_test) { + lite::Tensor x, out; + constexpr int batch_size = 1; + std::vector x_shape{batch_size, 3, 2, 2}; + x.Resize(lite::DDim(x_shape)); + std::vector out_shape{batch_size, 3, 2, 2}; + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); i++) { + x_data[i] = static_cast(i) / 12.0 - 0.5; + } + LeakyReluCompute leaky_relu; + operators::ActivationParam param; + + param.X = &x; + param.Out = &out; + param.Leaky_relu_alpha = 0.05; + + leaky_relu.SetParam(param); + leaky_relu.Run(); + + std::vector ref_data({-0.025, + -0.02083333, + -0.01666667, + -0.0125, + -0.00833333, + -0.00416667, + 0., + 0.08333334, + 0.16666667, + 0.25, + 0.33333334, + 0.41666666}); + for (int i = 0; i < out.dims().production(); i++) { + EXPECT_NEAR(out_data[i], ref_data[i], 1e-05); + } +} + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle + +USE_LITE_KERNEL(leaky_relu, kX86, kFloat, kNCHW, def);