OpSet 11 Operator Update: Supporting Neg Axis (#1835)

* OpSet 11 Update: Neg Axis handling for 5 ops:
ArgMax, ArgMin, HardMax, LogSoftmax, Softmax.

* Add unit test for ArgMax, ArgMin and HardMax

* Add lp_norm and exclude nGraph from hardmax test.

* Exclude nGraph from Neg Axis test.

* Exclude nGraph from NegAxis test

* fix excluded ep.

* Fix nGraph test failure

* add test.run
This commit is contained in:
ybrnathan 2019-09-16 21:36:15 -07:00 committed by GitHub
parent 2f7f83c655
commit d646dc73e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 191 additions and 38 deletions

View file

@ -102,15 +102,15 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Asi
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Acos);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Atan);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, Gemm);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Hardmax);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, LogSoftmax);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, Hardmax);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, LogSoftmax);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, float, MatMul);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, double, MatMul);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int32_t, MatMul);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint32_t, MatMul);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int64_t, MatMul);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint64_t, MatMul);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Softmax);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, Softmax);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, TopK);
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, BatchNormalization);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Conv);
@ -153,10 +153,10 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain,
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ReduceSumSquare);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, double, ReduceSumSquare);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ReduceSumSquare);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ArgMax);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ArgMax);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ArgMin);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ArgMin);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMax);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, int32_t, ArgMax);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMin);
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, int32_t, ArgMin);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, GRU);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, LSTM);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, RNN);
@ -307,6 +307,13 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, Re
// opset 11
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Clip);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, uint8_t, DynamicQuantizeLinear);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMax);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMax);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMin);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMin);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Hardmax);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, LogSoftmax);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Softmax);
void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
static const BuildKernelCreateInfoFn function_table[] = {
@ -394,15 +401,15 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Acos)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Atan)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, Gemm)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Hardmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, LogSoftmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, Hardmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, LogSoftmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, float, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, double, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int32_t, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint32_t, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int64_t, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint64_t, MatMul)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Softmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, Softmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, TopK)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, BatchNormalization)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Conv)>,
@ -445,10 +452,10 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ReduceSumSquare)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ReduceSumSquare)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, double, ReduceSumSquare)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, int32_t, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, float, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, int32_t, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, GRU)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, LSTM)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, RNN)>,
@ -599,6 +606,13 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
//opset 11
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Clip)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, uint8_t, DynamicQuantizeLinear)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMin)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Hardmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, LogSoftmax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Softmax)>,
};
for (auto& function_table_entry : function_table) {

View file

@ -2,6 +2,7 @@
// Licensed under the MIT License.
#include "core/providers/cpu/math/hardmax.h"
#include "core/providers/common.h"
#include "core/util/math_cpuonly.h"
#include "core/util/math.h"
@ -13,8 +14,9 @@ Status Hardmax<float>::Compute(OpKernelContext* ctx) const {
const TensorShape& input_shape = X->Shape();
const auto* Xdata = X->template Data<float>();
size_t tmpN = input_shape.SizeToDimension(axis_);
size_t tmpD = input_shape.SizeFromDimension(axis_);
auto axis = HandleNegativeAxis(axis_, input_shape.NumDimensions()); // handle negative and enforce axis is valid
size_t tmpN = input_shape.SizeToDimension(axis);
size_t tmpD = input_shape.SizeFromDimension(axis);
// Math::RowwiseMax expects int N and D.
if (tmpN * tmpD > INT32_MAX || tmpN > INT32_MAX || tmpD > INT32_MAX) {
@ -48,9 +50,17 @@ Status Hardmax<float>::Compute(OpKernelContext* ctx) const {
return Status::OK();
}
ONNX_CPU_OPERATOR_KERNEL(
ONNX_CPU_OPERATOR_VERSIONED_KERNEL(
Hardmax,
1,
10,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
Hardmax<float>);
// Opset 11 starts to support Neg Axis.
ONNX_CPU_OPERATOR_KERNEL(
Hardmax,
11,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
Hardmax<float>);

View file

@ -19,9 +19,6 @@ class Hardmax final : public OpKernel {
if (status.IsOK()) {
axis_ = gsl::narrow_cast<int>(axis);
}
// if value was provided, make sure it was valid
ORT_ENFORCE(axis_ >= 0, "Invalid axis provided.");
}
Status Compute(OpKernelContext* context) const override;

View file

@ -42,10 +42,17 @@ Status LogSoftmax<float>::Compute(OpKernelContext* ctx) const {
return status;
}
ONNX_CPU_OPERATOR_KERNEL(
ONNX_CPU_OPERATOR_VERSIONED_KERNEL(
LogSoftmax,
1,
10,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
LogSoftmax<float>);
// Opset 11 starts to support Neg Axis.
ONNX_CPU_OPERATOR_KERNEL(
LogSoftmax,
11,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
LogSoftmax<float>);
} // namespace onnxruntime

View file

@ -43,9 +43,17 @@ Status Softmax<float>::Compute(OpKernelContext* ctx) const {
return status;
}
ONNX_CPU_OPERATOR_KERNEL(
ONNX_CPU_OPERATOR_VERSIONED_KERNEL(
Softmax,
1,
10,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
Softmax<float>);
// Opset 11 starts to support Neg Axis.
ONNX_CPU_OPERATOR_KERNEL(
Softmax,
11,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
Softmax<float>);

View file

@ -3,6 +3,7 @@
#include "core/providers/cpu/nn/lp_norm.h"
#include "core/util/math_cpuonly.h"
#include "core/providers/common.h"
namespace onnxruntime {
ONNX_CPU_OPERATOR_KERNEL(
@ -55,7 +56,7 @@ Status LpNorm<float>::Compute(OpKernelContext* p_op_kernel_context) const {
const TensorShape& input_shape = input->Shape();
Tensor* output = p_op_kernel_context->Output(0, input_shape);
const auto canonical_axis = axis_ != -1 ? axis_ : (input_shape.NumDimensions() - 1);
const auto canonical_axis = HandleNegativeAxis(axis_, static_cast<int64_t>(input_shape.NumDimensions()));
const int64_t m = input_shape.GetDims()[canonical_axis];
const int64_t n = input_shape.Size() / m;
const int64_t sf = input_shape.SizeFromDimension(canonical_axis + 1);

View file

@ -22,6 +22,23 @@ namespace onnxruntime {
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<int32_t>()), \
x<int32_t>);
#define REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(x, startVer, endVer) \
ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( \
x, \
startVer, \
endVer, \
float, \
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()), \
x<float>); \
\
ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( \
x, \
startVer, \
endVer, \
int32_t, \
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<int32_t>()), \
x<int32_t>);
#define REGISTER_UNARY_ELEMENTWISE_KERNEL_DOUBLE_ONLY(x, sinceVersion) \
ONNX_CPU_OPERATOR_TYPED_KERNEL( \
x, \
@ -53,8 +70,10 @@ REGISTER_UNARY_ELEMENTWISE_KERNEL_INT64_ONLY(ReduceSum, 1);
REGISTER_UNARY_ELEMENTWISE_KERNEL_DOUBLE_ONLY(ReduceSum, 1);
REGISTER_UNARY_ELEMENTWISE_KERNEL(ReduceSumSquare, 1);
REGISTER_UNARY_ELEMENTWISE_KERNEL_DOUBLE_ONLY(ReduceSumSquare, 1);
REGISTER_UNARY_ELEMENTWISE_KERNEL(ArgMax, 1);
REGISTER_UNARY_ELEMENTWISE_KERNEL(ArgMin, 1);
REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ArgMax, 1, 10);
REGISTER_UNARY_ELEMENTWISE_KERNEL(ArgMax, 11);
REGISTER_UNARY_ELEMENTWISE_VERSIONED_KERNEL(ArgMin, 1, 10);
REGISTER_UNARY_ELEMENTWISE_KERNEL(ArgMin, 11);
// When all reduce axises located at the tail of the dims, quite general cases, transpose and extra
// copy could be skiped to improve performance, if required by check_no_transpose = true;

View file

@ -23,7 +23,13 @@ static void RunTest(const std::vector<float>& x_vals,
test.AddInput<float>("X", dimensions, x_vals);
test.AddOutput<float>("Y", dimensions, expected_vals);
test.Run(expect_result, expected_err_str);
std::unordered_set<std::string> excluded_eps;
if (axis < 0) {
excluded_eps.insert(kNGraphExecutionProvider); // NGraph EP cannot handle negative axis values
}
test.Run(expect_result, expected_err_str, excluded_eps);
}
TEST(HardmaxOperator, Simple) {
@ -135,17 +141,27 @@ TEST(HardmaxOperator, ThreeDimsAxis2) {
RunTest(x_vals_3dims, expected_vals, three_dimensions, /*axis*/ 2);
}
TEST(HardmaxOperator, InvalidAxis) {
std::vector<float> x_vals = {-1.0f, 0.0f, 1.0f};
std::vector<float> expected_vals = {0.0f, 0.0f, 0.0f};
std::vector<int64_t> dimensions = {1, 3};
TEST(HardmaxOperator, ThreeDimsNegAxis2) {
// x = <see x_vals_3dims>
// import cntk as C
// expected = C.hardmax(x.reshape(12,5)).eval().reshape(3, 4, 5)
std::vector<float> expected_vals = {
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
RunTest(x_vals,
expected_vals,
dimensions,
/* invalid axis */ -1,
OpTester::ExpectResult::kExpectFailure,
"Invalid axis provided.");
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
RunTest(x_vals_3dims, expected_vals, three_dimensions, /*axis*/ -1);
}
} // namespace test

View file

@ -80,5 +80,32 @@ TEST(LpNormalizationTest, LpNormalizationDefaultAxisAndP) {
test.AddOutput<float>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L1NormalizationWithValidNegativeAxis) {
OpTester test("LpNormalization");
test.AddAttribute("axis", static_cast<int64_t>(-2));
test.AddAttribute("p", static_cast<int64_t>(1));
vector<float> input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F,
4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F,
9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F,
6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F,
1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F,
9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F};
vector<int64_t> input_dims = {2, 3, 4};
test.AddInput<float>("input", input_dims, input);
vector<float> expected_output = {0.2907843F, 0.3976693F, 0.3296719F, 0.28535331F,
0.23563529F, 0.36431994F, 0.25339247F, 0.43624816F,
0.47358041F, 0.23801075F, 0.41693563F, 0.27839852F,
0.35740998F, 0.3586345F, 0.11079474F, 0.09572189F,
0.06911299F, 0.32647048F, 0.54091538F, 0.47374282F,
0.57347703F, 0.31489502F, 0.34828988F, 0.43053529F};
test.AddOutput<float>("Y", input_dims, expected_output);
test.Run();
}
} // namespace test
} // namespace onnxruntime

View file

@ -22,16 +22,27 @@ void TestReduceOp(const std::string& op,
{
OpTester test(op.c_str());
bool has_neg_axis = false;
if (!axes.empty()) {
if (op.compare("ArgMax") == 0 || op.compare("ArgMin") == 0)
if (op.compare("ArgMax") == 0 || op.compare("ArgMin") == 0) {
test.AddAttribute("axis", axes[0]);
if (axes[0] < 0)
has_neg_axis = true;
}
else
test.AddAttribute("axes", axes);
}
test.AddAttribute("keepdims", keepdims);
test.AddInput<float>("data", input_dims, data);
test.AddOutput<OutT>("reduced", expected_dims, expected_data);
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kCudaExecutionProvider, kTensorrtExecutionProvider}); //TensorRT: result differs
std::unordered_set<std::string> excluded_eps = {kCudaExecutionProvider, kTensorrtExecutionProvider}; //TensorRT: result differs
if (has_neg_axis) {
excluded_eps.insert(kNGraphExecutionProvider); // NGraph EP cannot handle negative axis values
}
test.Run(OpTester::ExpectResult::kExpectSuccess, "", excluded_eps);
}
TEST(ReductionOpTest, ReductionVariationTest) {
@ -1106,6 +1117,28 @@ TEST(ReductionOpTest, ArgMax_int32) {
test.Run();
}
TEST(ReductionOpTest, ArgMax_int32_neg_axis) {
OpTester test("ArgMax");
test.AddAttribute("axis", (int64_t)(-2));
test.AddAttribute("keepdims", (int64_t)1);
test.AddInput<int32_t>("data", {3, 2, 2},
{1, 2,
3, 4,
5, 6,
7, 8,
9, 10,
11, 12});
test.AddOutput<int64_t>("reduced", {3, 1, 2},
{1, 1,
1, 1,
1, 1});
std::unordered_set<std::string> excluded_eps = {kNGraphExecutionProvider}; // NGraph EP cannot handle negative axis values
test.Run(OpTester::ExpectResult::kExpectSuccess, "", excluded_eps);
}
TEST(ReductionOpTest, ArgMax2D) {
OpTester test("ArgMax");
test.AddAttribute("axis", (int64_t)1);
@ -1186,5 +1219,26 @@ TEST(ReductionOpTest, ArgMin_int32) {
test.Run();
}
TEST(ReductionOpTest, ArgMin_int32_neg_axis) {
OpTester test("ArgMin");
test.AddAttribute("axis", (int64_t)(-3));
test.AddAttribute("keepdims", (int64_t)0);
test.AddInput<int32_t>("data", {3, 2, 2},
{1, 2,
3, 4,
5, 6,
7, 8,
9, 10,
11, 12});
test.AddOutput<int64_t>("reduced", {2, 2},
{0, 0,
0, 0});
std::unordered_set<std::string> excluded_eps = {kNGraphExecutionProvider}; // NGraph EP cannot handle negative axis values
test.Run(OpTester::ExpectResult::kExpectSuccess, "", excluded_eps);
}
} // namespace test
} // namespace onnxruntime