From: Patryk Elszkowski Date: Mon, 26 Oct 2020 10:34:50 +0000 (+0100) Subject: enable reference implementation in CTCGreedyDecoder single layer test (#2680) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5036b12544dc0ccf57f7f9a7be18a71f4fad1892;p=platform%2Fupstream%2Fdldt.git enable reference implementation in CTCGreedyDecoder single layer test (#2680) * enable reference implementation for CTCGreedyDecoder single layer tests * update unit test to have blnak_index * remove merge_repeated disable flag for CPU test because CPU impl always merge * add CTCGreedyDecoder single layer tests for CPU * changes to match xPU implementations * apply reviewers suggestions Co-authored-by: Patryk Elszkowski --- diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp new file mode 100644 index 0000000..e128cf3 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "single_layer_tests/ctc_greedy_decoder.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace ngraph::helpers; + +namespace { +// Common params +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const auto basicCases = ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({ 10, 1, 16 }), + std::vector({ 20, 2, 8 })), + ::testing::Values(true/*, false - current implementation of CPU greedy decoder always merge_repeated */), + ::testing::Values(CommonTestUtils::DEVICE_CPU)); + +INSTANTIATE_TEST_CASE_P(smoke_CTC_Greedy_decoder_Basic, CTCGreedyDecoderLayerTest, + basicCases, + CTCGreedyDecoderLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/ctc_greedy_decoder.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/ctc_greedy_decoder.hpp index 7372446..d564f55 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/ctc_greedy_decoder.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/ctc_greedy_decoder.hpp @@ -50,7 +50,6 @@ protected: InferenceEngine::SizeVector sequenceLengths; bool mergeRepeated; - std::vector> CalculateRefs() override; void SetUp() override; }; diff --git a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/ctc_greedy_decoder.cpp b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/ctc_greedy_decoder.cpp index 4c6f91c..c759aeb 100644 --- a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/ctc_greedy_decoder.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/ctc_greedy_decoder.cpp @@ -51,83 +51,6 @@ std::string CTCGreedyDecoderLayerTest::getTestCaseName( return result.str(); } -std::vector> CTCGreedyDecoderLayerTest::CalculateRefs() { - std::vector inRawData; - std::vector castedBlobs; - for (size_t i = 0; i < inputs.size(); i++) { - const auto precision = inputs[i]->getTensorDesc().getPrecision(); - const auto layout = inputs[i]->getTensorDesc().getLayout(); - const auto defLayout = InferenceEngine::TensorDesc::getLayoutByDims(inputs[i]->getTensorDesc().getDims()); - - if (precision == InferenceEngine::Precision::FP32 && layout == defLayout) { - inRawData.push_back(inputs[i]->cbuffer().template as()); - } else { - auto castedBlob = FuncTestUtils::copyBlobWithCast(inputs[i]); - castedBlob = FuncTestUtils::convertBlobLayout(castedBlob, defLayout); - inRawData.push_back(castedBlob->cbuffer().template as()); - castedBlobs.push_back(castedBlob); - } - } - - size_t T_ = inputShapes.at(0); - size_t N_ = inputShapes.at(1); - size_t C_ = inputShapes.at(2); - auto outSize = T_ * N_; - float a = 43; - const float* probabilities = inRawData[0]; - const float* sequence_indicators = inRawData[1]; - auto outBuf = std::vector(outSize); - float* output_sequences = outBuf.data(); - - for (auto i = 0; i < outSize; i++) - output_sequences[i] = -1.0f; - - for (size_t n = 0; n < N_; ++n) { - int prev_class_idx = -1; - size_t output_index = n * T_; - - for (size_t t = 0; /* check at end */; ++t) { - // get maximum probability and its index - int max_class_idx = 0; - - const float* probs = probabilities + t * C_ * N_ + n * C_; - float max_prob = probs[0]; - ++probs; - - for (size_t c = 1; c < C_; ++c, ++probs) { - if (*probs > max_prob) { - max_class_idx = static_cast(c); - max_prob = *probs; - } - } - - if (max_class_idx < static_cast(C_) - 1 && - max_class_idx != prev_class_idx) { - output_sequences[output_index] = static_cast(max_class_idx); - output_index++; - } - - prev_class_idx = max_class_idx; - - if (t + 1 == T_ || sequence_indicators[(t + 1) * N_ + n] == 0) { - break; - } - } - } - - // Be aligned with test utils ref calulcation method, which returns std::vector>... - std::vector> ret(1); - for (auto& val : outBuf) { - uint8_t* u8_val = reinterpret_cast(&val); - ret[0].push_back(u8_val[0]); - ret[0].push_back(u8_val[1]); - ret[0].push_back(u8_val[2]); - ret[0].push_back(u8_val[3]); - } - - return ret; -} - void CTCGreedyDecoderLayerTest::SetUp() { auto netPrecision = InferenceEngine::Precision::UNSPECIFIED; std::tie(netPrecision, inPrc, outPrc, inLayout, outLayout, inputShapes, mergeRepeated, targetDevice) = GetParam(); @@ -146,7 +69,6 @@ void CTCGreedyDecoderLayerTest::SetUp() { } TEST_P(CTCGreedyDecoderLayerTest, CompareWithRefs) { - //std::vector> CalculateRefs(); Run(); }; } // namespace LayerTestsDefinitions diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/ctc_greedy_decoder.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/ctc_greedy_decoder.hpp index 40a9e3d..21eb99f 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/ctc_greedy_decoder.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/ctc_greedy_decoder.hpp @@ -35,9 +35,10 @@ namespace ngraph const Shape& out_shape, const bool ctc_merge_repeated) { - auto max_seq_len = data_shape[0]; - auto batch_size = data_shape[1]; - auto class_count = data_shape[2]; + const auto max_seq_len = data_shape[0]; + const auto batch_size = data_shape[1]; + const auto class_count = data_shape[2]; + const auto blank_index = class_count - 1; CoordinateTransform out_transform = CoordinateTransform(out_shape); CoordinateTransform data_transform = CoordinateTransform(data_shape); @@ -59,18 +60,17 @@ namespace ngraph auto mask_index = seq_masks_transform.index({seq_ind, batch_ind}); // first 0 marks the end of a sequence - if (std::abs(static_cast(sequence_masks[mask_index] - - static_cast(1))) > - std::numeric_limits::epsilon()) + if (seq_ind && sequence_masks[mask_index] == T{0}) { - continue; + break; } auto class_index = data + data_index; auto class_max_element = std::max_element(class_index, class_index + class_count); unsigned int max_class_ind = std::distance(class_index, class_max_element); - if (!(previous_class_index == max_class_ind && ctc_merge_repeated)) + if (!(previous_class_index == max_class_ind && ctc_merge_repeated) && + max_class_ind < blank_index) { tmp_out[out_index++] = max_class_ind; } diff --git a/ngraph/test/backend/ctc_greedy_decoder.in.cpp b/ngraph/test/backend/ctc_greedy_decoder.in.cpp index db52946..ae516d7 100644 --- a/ngraph/test/backend/ctc_greedy_decoder.in.cpp +++ b/ngraph/test/backend/ctc_greedy_decoder.in.cpp @@ -49,7 +49,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder) { const int T = 3; const int N = 1; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -59,7 +59,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.4f, 0.3f, 0.5f, 0.6f}); + test_case.add_input({0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 0.0f, 1.0f}); @@ -70,7 +70,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_f16) { const int T = 3; const int N = 1; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -80,7 +80,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_f16) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.4f, 0.3f, 0.5f, 0.6f}); + test_case.add_input({0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 0.0f, 1.0f}); @@ -91,7 +91,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_multiple_batches) { const int T = 3; const int N = 2; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -101,8 +101,24 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_multiple_batches) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input( - {0.1f, 0.2f, 0.15f, 0.25f, 0.4f, 0.3f, 0.45f, 0.35f, 0.5f, 0.6f, 0.55f, 0.65f}); + test_case.add_input({0.1f, + 0.2f, + 0.f, + 0.15f, + 0.25f, + 0.f, + 0.4f, + 0.3f, + 0.f, + 0.45f, + 0.35f, + 0.f, + 0.5f, + 0.6f, + 0.f, + 0.55f, + 0.65f, + 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}); @@ -116,7 +132,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_single_batch_short_sequence) { const int T = 3; const int N = 1; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -126,7 +142,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_single_batch_short_sequence) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.4f, 0.3f, 0.5f, 0.6f}); + test_case.add_input({0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}); test_case.add_input({1.0f, 1.0f, 0.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 0.0f, -1.0f}); @@ -137,7 +153,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_merge) { const int T = 3; const int N = 1; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -147,7 +163,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_merge) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.3f, 0.4f, 0.6f, 0.5f}); + test_case.add_input({0.1f, 0.2f, 0.f, 0.3f, 0.4f, 0.f, 0.6f, 0.5f, 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 0.0f, -1.0f}); @@ -158,7 +174,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_single_no_merge) { const int T = 3; const int N = 1; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -168,7 +184,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_single_no_merge) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.3f, 0.4f, 0.6f, 0.5f}); + test_case.add_input({0.1f, 0.2f, 0.f, 0.3f, 0.4f, 0.f, 0.6f, 0.5f, 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 1.0f, 0.0f}); @@ -179,7 +195,7 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_multiple_sequences) { const int T = 2; const int N = 2; - const int C = 2; + const int C = 3; const auto data_shape = Shape{T, N, C}; const auto masks_shape = Shape{T, N}; @@ -189,7 +205,8 @@ NGRAPH_TEST(${BACKEND_NAME}, ctc_greedy_decoder_multiple_sequences) auto function = make_shared(decoder, ParameterVector{data, masks}); auto test_case = test::TestCase(function); - test_case.add_input({0.1f, 0.2f, 0.4f, 0.3f, 0.5f, 0.6f, 0.7f, 0.8f}); + test_case.add_input( + {0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f, 0.7f, 0.8f, 0.f}); test_case.add_input({1.0f, 1.0f, 1.0f, 0.0f}); test_case.add_expected_output(Shape{N, T, 1, 1}, vector{1.0f, 1.0f, 0.0f, -1.0f});