未验证 提交 db4bd24b 编写于 作者: F furnace 提交者: GitHub

[NPU] add sigmoid and sigmoid_cross_entropy_with_logits (#34074)

* [NPU] add sigmoid and sigmoid_cross_entropy_with_logits

* [NPU] add debug logs

* [NPU] delete debug logs

* [NPU] reset to paddle.NPUPlace(0)

* [NPU] add more unittests for sigmoid_cross_entropy_with_logits

* delete useless c++ code, and delete check_dygraph=False

* [NPU] delete repeated codes of unittests

* [NPU] fix licence code style

* [NPU] add attrs (now do not support) check for sigmoid_cross_entropy_with_logits
上级 044a82d8
...@@ -303,6 +303,50 @@ class SquareNPUKernel : public framework::OpKernel<T> { ...@@ -303,6 +303,50 @@ class SquareNPUKernel : public framework::OpKernel<T> {
} }
}; };
template <typename DeviceContext, typename T>
class SigmoidNPUKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& ctx) const override {
auto* x = ctx.Input<Tensor>("X");
auto* out = ctx.Output<Tensor>("Out");
auto place = ctx.GetPlace();
out->mutable_data<T>(place);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
const auto& runner = NpuOpRunner("Sigmoid", {*x}, {*out}, {});
runner.Run(stream);
}
};
template <typename DeviceContext, typename T>
class SigmoidGradNPUKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& ctx) const override {
auto* dout = ctx.Input<Tensor>(framework::GradVarName("Out"));
auto* out = ctx.Input<Tensor>("Out");
auto* dx = ctx.Output<Tensor>(framework::GradVarName("X"));
auto place = ctx.GetPlace();
dx->mutable_data<T>(place);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
const auto& runner_dx =
NpuOpRunner("SigmoidGrad", {*out, *dout}, {*dx}, {});
runner_dx.Run(stream);
}
};
} // namespace operators } // namespace operators
} // namespace paddle } // namespace paddle
...@@ -366,3 +410,14 @@ REGISTER_OP_NPU_KERNEL( ...@@ -366,3 +410,14 @@ REGISTER_OP_NPU_KERNEL(
ops::SquareNPUKernel<paddle::platform::NPUDeviceContext, ops::SquareNPUKernel<paddle::platform::NPUDeviceContext,
paddle::platform::float16>, paddle::platform::float16>,
ops::SquareNPUKernel<paddle::platform::NPUDeviceContext, int>); ops::SquareNPUKernel<paddle::platform::NPUDeviceContext, int>);
REGISTER_OP_NPU_KERNEL(
sigmoid, ops::SigmoidNPUKernel<paddle::platform::NPUDeviceContext, float>,
ops::SigmoidNPUKernel<paddle::platform::NPUDeviceContext,
paddle::platform::float16>);
REGISTER_OP_NPU_KERNEL(
sigmoid_grad,
ops::SigmoidGradNPUKernel<paddle::platform::NPUDeviceContext, float>,
ops::SigmoidGradNPUKernel<paddle::platform::NPUDeviceContext,
paddle::platform::float16>);
...@@ -21,7 +21,6 @@ namespace paddle { ...@@ -21,7 +21,6 @@ namespace paddle {
namespace operators { namespace operators {
using framework::Tensor; using framework::Tensor;
const int kIgnoreIndex = -100;
class SigmoidCrossEntropyWithLogitsOp : public framework::OperatorWithKernel { class SigmoidCrossEntropyWithLogitsOp : public framework::OperatorWithKernel {
public: public:
......
...@@ -21,6 +21,7 @@ namespace paddle { ...@@ -21,6 +21,7 @@ namespace paddle {
namespace operators { namespace operators {
using Tensor = framework::Tensor; using Tensor = framework::Tensor;
const int kIgnoreIndex = -100;
// Out = max(X, 0) - X * Labels + log(1 + exp(-abs(X))) // Out = max(X, 0) - X * Labels + log(1 + exp(-abs(X)))
template <typename DeviceContext, typename T> template <typename DeviceContext, typename T>
......
/* Copyright (c) 2021 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 Licnse. */
#include "paddle/fluid/operators/sigmoid_cross_entropy_with_logits_op.h"
#include "paddle/fluid/operators/npu_op_runner.h"
namespace paddle {
namespace operators {
using Tensor = framework::Tensor;
void CheckAttrs(const framework::ExecutionContext& ctx) {
// Add this check is is due to Ascend SigmoidCrossEntropyWithLogits
// and SigmoidCrossEntropyWithLogitsGrad does't supoort
// attr normalize and ignore_index
bool normalize = ctx.Attr<bool>("normalize");
int ignore_index = ctx.Attr<int>("ignore_index");
PADDLE_ENFORCE_EQ(normalize, false,
platform::errors::InvalidArgument(
"attr normalize must be false, but got true"));
PADDLE_ENFORCE_EQ(ignore_index, kIgnoreIndex,
platform::errors::InvalidArgument(
"attr ignore_index must be default %d, but got %d",
kIgnoreIndex, ignore_index));
}
template <typename DeviceContext, typename T>
class SigmoidCrossEntropyWithLogitsNPUKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& ctx) const override {
CheckAttrs(ctx);
auto* x = ctx.Input<Tensor>("X");
auto* label = ctx.Input<Tensor>("Label");
auto* out = ctx.Output<Tensor>("Out");
auto place = ctx.GetPlace();
out->mutable_data<T>(place);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
const auto& runner =
NpuOpRunner("SigmoidCrossEntropyWithLogits", {*x, *label}, {*out}, {});
runner.Run(stream);
}
};
template <typename DeviceContext, typename T>
class SigmoidCrossEntropyWithLogitsNPUGradKernel
: public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& ctx) const override {
CheckAttrs(ctx);
auto* x = ctx.Input<Tensor>("X");
auto* label = ctx.Input<Tensor>("Label");
auto* dout = ctx.Input<Tensor>(framework::GradVarName("Out"));
auto* dx = ctx.Output<Tensor>(framework::GradVarName("X"));
auto place = ctx.GetPlace();
dx->mutable_data<T>(place);
auto stream =
ctx.template device_context<paddle::platform::NPUDeviceContext>()
.stream();
const auto& runner_dx = NpuOpRunner("SigmoidCrossEntropyWithLogitsGrad",
{*x, *label, *dout}, {*dx}, {});
runner_dx.Run(stream);
}
};
} // namespace operators
} // namespace paddle
namespace ops = paddle::operators;
namespace plat = paddle::platform;
REGISTER_OP_NPU_KERNEL(
sigmoid_cross_entropy_with_logits,
ops::SigmoidCrossEntropyWithLogitsNPUKernel<plat::NPUDeviceContext, float>,
ops::SigmoidCrossEntropyWithLogitsNPUKernel<plat::NPUDeviceContext,
plat::float16>);
REGISTER_OP_NPU_KERNEL(
sigmoid_cross_entropy_with_logits_grad,
ops::SigmoidCrossEntropyWithLogitsNPUGradKernel<plat::NPUDeviceContext,
float>,
ops::SigmoidCrossEntropyWithLogitsNPUGradKernel<plat::NPUDeviceContext,
plat::float16>);
# Copyright (c) 2021 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.
from __future__ import print_function
import numpy as np
from paddle.fluid.tests.unittests.op_test import OpTest
from scipy.special import logit
from scipy.special import expit
import paddle.fluid.core as core
import unittest
from paddle.fluid import compiler, Program, program_guard
import paddle.fluid as fluid
import paddle
paddle.enable_static()
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestSigmoidCrossEntropyWithLogitsOp1(OpTest):
"""Test sigmoid_cross_entropy_with_logit_op with binary label
"""
def setUp(self):
self.op_type = "sigmoid_cross_entropy_with_logits"
self.set_npu()
self.init_dtype()
batch_size = 64
num_classes = 20
self.inputs = {
'X': logit(
np.random.uniform(0, 1, (batch_size, num_classes))
.astype(self.dtype)),
'Label': np.random.randint(0, 2, (batch_size, num_classes))
.astype(self.dtype)
}
# Fw Pass is implemented as elementwise sigmoid followed by
# elementwise logistic loss
# Label * -log(sigmoid(X)) + (1 - label) * -log(1 - sigmoid(X))
sigmoid_X = expit(self.inputs['X'])
term1 = self.inputs['Label'] * np.log(sigmoid_X)
term2 = (1 - self.inputs['Label']) * np.log(1 - sigmoid_X)
self.outputs = {'Out': -term1 - term2}
def test_check_output(self):
self.check_output_with_place(self.place, atol=1e-5)
def test_check_grad(self):
self.check_grad_with_place(self.place, ['X'], 'Out')
def set_npu(self):
self.__class__.use_npu = True
self.place = paddle.NPUPlace(0)
def init_dtype(self):
self.dtype = np.float32
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestSigmoidCrossEntropyWithLogitsOp3(
TestSigmoidCrossEntropyWithLogitsOp1):
"""Test sigmoid_cross_entropy_with_logit_op with probabalistic label
"""
def setUp(self):
self.op_type = "sigmoid_cross_entropy_with_logits"
self.set_npu()
self.init_dtype()
batch_size = 64
num_classes = 20
self.inputs = {
'X': logit(
np.random.uniform(0, 1, (batch_size, num_classes))
.astype(self.dtype)),
'Label': np.random.uniform(0, 1, (batch_size, num_classes))
.astype(self.dtype)
}
# Fw Pass is implemented as elementwise sigmoid followed by
# elementwise logistic loss
# Label * -log(sigmoid(X)) + (1 - label) * -log(1 - sigmoid(X))
sigmoid_X = expit(self.inputs['X'])
term1 = self.inputs['Label'] * np.log(sigmoid_X)
term2 = (1 - self.inputs['Label']) * np.log(1 - sigmoid_X)
self.outputs = {'Out': -term1 - term2}
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestSigmoidCrossEntropyWithLogitsOp5(
TestSigmoidCrossEntropyWithLogitsOp1):
"""Test sigmoid_cross_entropy_with_logit_op with probabalistic label
"""
def setUp(self):
self.op_type = "sigmoid_cross_entropy_with_logits"
self.set_npu()
self.init_dtype()
batch_size = [10, 10]
num_classes = 20
self.inputs = {
'X': logit(
np.random.uniform(0, 1, tuple(batch_size + [num_classes]))
.astype(self.dtype)),
'Label': np.random.uniform(0, 1, tuple(batch_size + [num_classes]))
.astype(self.dtype)
}
# Fw Pass is implemented as elementwise sigmoid followed by
# elementwise logistic loss
# Label * -log(sigmoid(X)) + (1 - label) * -log(1 - sigmoid(X))
sigmoid_X = expit(self.inputs['X'])
term1 = self.inputs['Label'] * np.log(sigmoid_X)
term2 = (1 - self.inputs['Label']) * np.log(1 - sigmoid_X)
self.outputs = {'Out': -term1 - term2}
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestSigmoidCrossEntropyWithLogitsOp6(
TestSigmoidCrossEntropyWithLogitsOp1):
"""Test sigmoid_cross_entropy_with_logit_op with binary label
"""
def setUp(self):
self.op_type = "sigmoid_cross_entropy_with_logits"
self.set_npu()
self.init_dtype()
batch_size = [10, 10]
num_classes = 20
self.inputs = {
'X': logit(
np.random.uniform(0, 1, tuple(batch_size + [num_classes]))
.astype(self.dtype)),
'Label': np.random.randint(0, 2, tuple(batch_size + [num_classes]))
.astype(self.dtype)
}
# Fw Pass is implemented as elementwise sigmoid followed by
# elementwise logistic loss
# Label * -log(sigmoid(X)) + (1 - label) * -log(1 - sigmoid(X))
sigmoid_X = expit(self.inputs['X'])
term1 = self.inputs['Label'] * np.log(sigmoid_X)
term2 = (1 - self.inputs['Label']) * np.log(1 - sigmoid_X)
self.outputs = {'Out': -term1 - term2}
if __name__ == '__main__':
unittest.main()
# Copyright (c) 2021 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.
from __future__ import print_function
import numpy as np
import unittest
import sys
from paddle.fluid.tests.unittests.op_test import OpTest
import paddle
import paddle.fluid as fluid
paddle.enable_static()
SEED = 2021
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestNPUSigmoid(OpTest):
def setUp(self):
self.op_type = "sigmoid"
self.set_npu()
self.init_dtype()
np.random.seed(SEED)
x = np.random.uniform(-1, 1, [11, 17]).astype(self.dtype)
out = 1 / (1 + np.exp(-x))
self.inputs = {'X': OpTest.np_dtype_to_fluid_dtype(x)}
self.outputs = {'Out': out}
def test_check_output(self):
self.check_output_with_place(self.place)
def test_check_grad(self):
if self.dtype == np.float16:
return
self.check_grad_with_place(
self.place, ['X'], 'Out', max_relative_error=0.01)
def set_npu(self):
self.__class__.use_npu = True
self.place = paddle.NPUPlace(0)
def init_dtype(self):
self.dtype = np.float32
@unittest.skipIf(not paddle.is_compiled_with_npu(),
"core is not compiled with NPU")
class TestNPUSigmoidFp16(TestNPUSigmoid):
def test_check_output(self):
self.check_output_with_place(self.place, atol=1e-3)
def init_dtype(self):
self.dtype = np.float16
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册