From b84fedfc35508f26c5b6757d791633a191e489e0 Mon Sep 17 00:00:00 2001 From: jinyuKING <2943829328@qq.com> Date: Mon, 25 May 2020 10:33:57 +0800 Subject: [PATCH] =?UTF-8?q?API/OP=EF=BC=88sequence=5Ffirst=5Fstep=EF=BC=8C?= =?UTF-8?q?sequence=5Flast=5Fstep=EF=BC=8Csequence=5Fmask=EF=BC=8Cbeam=5Fs?= =?UTF-8?q?earch=EF=BC=8Cbeam=5Fsearch=5Fdecode=EF=BC=89=20error=20message?= =?UTF-8?q?=20enhancement=20,test=3Drelease/1.8=20(#24668)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fluid/operators/beam_search_decode_op.cc | 43 ++++--- .../fluid/operators/beam_search_decode_op.h | 24 +++- .../operators/beam_search_decode_op_test.cc | 13 ++- paddle/fluid/operators/beam_search_op.cc | 6 +- paddle/fluid/operators/beam_search_op.h | 22 +++- .../sequence_ops/sequence_mask_op.cc | 4 +- .../operators/sequence_ops/sequence_mask_op.h | 13 ++- python/paddle/fluid/layers/rnn.py | 24 ++++ python/paddle/fluid/layers/sequence_lod.py | 12 +- .../sequence/test_sequence_first_step.py | 50 +++++++++ .../sequence/test_sequence_last_step.py | 50 +++++++++ .../unittests/sequence/test_sequence_mask.py | 14 ++- .../unittests/test_beam_search_decode_op.py | 43 +++++++ .../tests/unittests/test_beam_search_op.py | 105 ++++++++++++++++++ .../tests/unittests/test_rnn_cell_api.py | 2 +- 15 files changed, 385 insertions(+), 40 deletions(-) create mode 100644 python/paddle/fluid/tests/unittests/sequence/test_sequence_first_step.py create mode 100644 python/paddle/fluid/tests/unittests/sequence/test_sequence_last_step.py diff --git a/paddle/fluid/operators/beam_search_decode_op.cc b/paddle/fluid/operators/beam_search_decode_op.cc index eece632e74..c177dad802 100644 --- a/paddle/fluid/operators/beam_search_decode_op.cc +++ b/paddle/fluid/operators/beam_search_decode_op.cc @@ -128,14 +128,31 @@ class BeamSearchDecodeOp : public framework::OperatorBase { const LoDTensorArray* ids = ctx.Input("Ids"); const LoDTensorArray* scores = ctx.Input("Scores"); const size_t step_num = ids->size(); - PADDLE_ENFORCE_GT(step_num, 0UL, - "beam search steps should be larger than 0"); + PADDLE_ENFORCE_GT( + step_num, 0UL, + platform::errors::InvalidArgument( + "beam search steps, which is the" + "size of Input(Ids) LoDTensorArray. beam search steps should " + "be larger than 0, but received %d. ", + step_num)); const size_t source_num = ids->at(0).lod().at(0).size() - 1; - PADDLE_ENFORCE_GT(source_num, 0UL, "source num should be larger than 0"); + PADDLE_ENFORCE_GT( + source_num, 0UL, + platform::errors::InvalidArgument( + "source_num is the sequence number of the" + "first decoding step, indicating by Input(Ids)[0].lod[0].size. " + "The number of source_num should be larger than" + "0, but received %d. ", + source_num)); for (size_t i = 0; i < step_num; ++i) { - PADDLE_ENFORCE_EQ(ids->at(i).lod().size(), 2UL, - "Level of LodTensor should be 2"); + PADDLE_ENFORCE_EQ( + ids->at(i).lod().size(), 2UL, + platform::errors::InvalidArgument( + "For the i step in beam search steps," + "the size of Input(Ids)[i].lod() should larger than 2," + "but received %d. ", + ids->at(i).lod().size())); } size_t beam_size = ctx.Attr("beam_size"); @@ -190,14 +207,14 @@ hypothesis has. class BeamSearchDecodeInferShape : public framework::InferShapeBase { public: void operator()(framework::InferShapeContext* context) const override { - PADDLE_ENFORCE(context->HasInput("Ids"), - "BeamSearchDecodeOp must have input Ids"); - PADDLE_ENFORCE(context->HasInput("Scores"), - "BeamSearchDecodeOp must have input Scores"); - PADDLE_ENFORCE(context->HasOutput("SentenceIds"), - "BeamSearchDecodeOp must have output SentenceIds"); - PADDLE_ENFORCE(context->HasOutput("SentenceScores"), - "BeamSearchDecodeOp must have output SentenceScores"); + OP_INOUT_CHECK(context->HasInput("Ids"), "Input", "Ids", + "BeamSearchDecode"); + OP_INOUT_CHECK(context->HasInput("Scores"), "Input", "Scores", + "BeamSearchDecode"); + OP_INOUT_CHECK(context->HasOutput("SentenceIds"), "Output", "SentenceIds", + "BeamSearchDecode"); + OP_INOUT_CHECK(context->HasOutput("SentenceScores"), "Output", + "SentenceScores", "BeamSearchDecode"); } }; diff --git a/paddle/fluid/operators/beam_search_decode_op.h b/paddle/fluid/operators/beam_search_decode_op.h index 0b883c3158..de9dab4204 100644 --- a/paddle/fluid/operators/beam_search_decode_op.h +++ b/paddle/fluid/operators/beam_search_decode_op.h @@ -15,6 +15,7 @@ limitations under the License. */ #pragma once #include +#include #include #include "paddle/fluid/framework/lod_tensor_array.h" @@ -82,7 +83,15 @@ void BeamSearchDecoder::ConvertSentenceVectorToLodTensor( LoDTensor* score_tensor, bool reverse, bool sort_by_score) const { size_t src_num = sentence_vector_list.size(); - PADDLE_ENFORCE_NE(src_num, 0, "src_num should not be 0"); + PADDLE_ENFORCE_NE( + src_num, 0, + platform::errors::InvalidArgument( + "src_num is the sequence number of the first decoding step" + ", indicating by Input(Ids)[0].lod[0].size." + "src_num has wrong value." + "src_num should not be 0," + "But received %d.", + src_num)); std::vector source_level_lod = {0}; std::vector sentence_level_lod = {0}; @@ -144,9 +153,16 @@ void BeamSearchDecoder::Backtrace(const LoDTensorArray& step_ids, const LoDTensorArray& step_scores, LoDTensor* id_tensor, LoDTensor* score_tensor) const { - PADDLE_ENFORCE(!step_ids.empty(), "step num should be larger than 0"); - PADDLE_ENFORCE_EQ(step_ids.size(), step_scores.size(), - "step_ids and step_scores should be the same"); + PADDLE_ENFORCE_NE( + step_ids.empty(), true, + platform::errors::InvalidArgument("Input(Ids) should not be empty." + "But the Input(Ids) is empty.")); + PADDLE_ENFORCE_EQ( + step_ids.size(), step_scores.size(), + platform::errors::InvalidArgument( + "The size of Input(Ids) and Input(Scores) should be " + "the same. But the size of Input(Ids) and Input(Scores) " + "are not equal.")); const size_t step_num = step_ids.size(); const size_t src_num = step_ids.at(0).lod().at(kSourceLevel).size() - 1; std::vector> sentence_vector_list( diff --git a/paddle/fluid/operators/beam_search_decode_op_test.cc b/paddle/fluid/operators/beam_search_decode_op_test.cc index 88339e38d8..2a24e21387 100644 --- a/paddle/fluid/operators/beam_search_decode_op_test.cc +++ b/paddle/fluid/operators/beam_search_decode_op_test.cc @@ -35,10 +35,17 @@ void GenerateExample(const std::vector& level_0, const std::vector& data, LoDTensorArray* ids, LoDTensorArray* scores) { PADDLE_ENFORCE_EQ(level_0.back(), level_1.size() - 1, - "source level is used to describe candidate set"); + platform::errors::InvalidArgument( + "source level is used to describe candidate set" + ", so it's element should less than levle_1 length. " + "And the value of source" + "level is %d. ", + level_1.size() - 1)); PADDLE_ENFORCE_EQ(level_1.back(), data.size(), - "the lowest level is used to describe data" - ", so it's last element should be data length"); + platform::errors::InvalidArgument( + "the lowest level is used to describe data" + ", so it's last element should be data length %d. ", + data.size())); CPUPlace place; diff --git a/paddle/fluid/operators/beam_search_op.cc b/paddle/fluid/operators/beam_search_op.cc index c866189c7a..c6715227cf 100644 --- a/paddle/fluid/operators/beam_search_op.cc +++ b/paddle/fluid/operators/beam_search_op.cc @@ -89,13 +89,11 @@ class BeamSearchOp : public framework::OperatorWithKernel { void InferShape(framework::InferShapeContext *ctx) const override { for (const std::string &arg : std::vector({"pre_ids", "scores"})) { - PADDLE_ENFORCE(ctx->HasInput(arg), "BeamSearch need input argument '%s'", - arg); + OP_INOUT_CHECK(ctx->HasInput(arg), "Input", arg, "BeamSeach"); } for (const std::string &arg : std::vector({"selected_ids", "selected_scores"})) { - PADDLE_ENFORCE(ctx->HasOutput(arg), - "BeamSearch need output argument '%s'", arg); + OP_INOUT_CHECK(ctx->HasOutput(arg), "Output", arg, "BeamSeach"); } } diff --git a/paddle/fluid/operators/beam_search_op.h b/paddle/fluid/operators/beam_search_op.h index 3d32ea0cc9..708f3cd808 100644 --- a/paddle/fluid/operators/beam_search_op.h +++ b/paddle/fluid/operators/beam_search_op.h @@ -29,9 +29,15 @@ class BeamSearchOpKernel : public framework::OpKernel { auto* pre_ids = context.Input("pre_ids"); auto* pre_scores = context.Input("pre_scores"); - PADDLE_ENFORCE_NOT_NULL(scores); - PADDLE_ENFORCE_NOT_NULL(pre_ids); - PADDLE_ENFORCE_NOT_NULL(pre_scores); + PADDLE_ENFORCE_NOT_NULL(scores, + platform::errors::NotFound( + "Input(scores) of BeamSearchOp is not found.")); + PADDLE_ENFORCE_NOT_NULL( + pre_ids, platform::errors::NotFound( + "Input(pre_ids) of BeamSearchOp is not found.")); + PADDLE_ENFORCE_NOT_NULL( + pre_scores, platform::errors::NotFound( + "Input(pre_scores) of BeamSearchOp is not found.")); size_t level = context.Attr("level"); size_t beam_size = context.Attr("beam_size"); @@ -42,8 +48,14 @@ class BeamSearchOpKernel : public framework::OpKernel { auto selected_scores = context.Output("selected_scores"); auto* parent_idx = context.Output("parent_idx"); - PADDLE_ENFORCE_NOT_NULL(selected_ids); - PADDLE_ENFORCE_NOT_NULL(selected_scores); + PADDLE_ENFORCE_NOT_NULL( + selected_ids, + platform::errors::NotFound( + "Output(selected_scores) of BeamSearchOp is not found.")); + PADDLE_ENFORCE_NOT_NULL( + selected_scores, + platform::errors::NotFound( + "Output(parent_idx) of BeamSearchOp is not found.")); math::BeamSearchFunctor alg; alg(context.template device_context(), pre_ids, pre_scores, diff --git a/paddle/fluid/operators/sequence_ops/sequence_mask_op.cc b/paddle/fluid/operators/sequence_ops/sequence_mask_op.cc index e9097ee258..b8912dd4c7 100644 --- a/paddle/fluid/operators/sequence_ops/sequence_mask_op.cc +++ b/paddle/fluid/operators/sequence_ops/sequence_mask_op.cc @@ -23,8 +23,8 @@ class SequenceMaskOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) must exist"); - PADDLE_ENFORCE(ctx->HasOutput("Y"), "Output(Y) must exist"); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "SequenceMask"); + OP_INOUT_CHECK(ctx->HasOutput("Y"), "Output", "Y", "SequenceMask"); int maxlen = ctx->Attrs().Get("maxlen"); auto dim = framework::vectorize(ctx->GetInputDim("X")); diff --git a/paddle/fluid/operators/sequence_ops/sequence_mask_op.h b/paddle/fluid/operators/sequence_ops/sequence_mask_op.h index abddc6859f..3abaeccb28 100644 --- a/paddle/fluid/operators/sequence_ops/sequence_mask_op.h +++ b/paddle/fluid/operators/sequence_ops/sequence_mask_op.h @@ -80,7 +80,10 @@ class SequenceMaskKernel : public framework::OpKernel { int maxlen = ctx.Attr("maxlen"); if (ctx.HasInput("MaxLenTensor")) { auto max_len_tensor = ctx.Input("MaxLenTensor"); - PADDLE_ENFORCE(max_len_tensor != NULL, "MaxLenTensor is NULL"); + PADDLE_ENFORCE_NOT_NULL(max_len_tensor, + platform::errors::InvalidArgument( + "Input(MaxLenTensor) should not be NULL." + "But received Input(MaxLenTensor) is NULL")); if (platform::is_gpu_place(max_len_tensor->place())) { framework::Tensor temp; TensorCopySync(*max_len_tensor, platform::CPUPlace(), &temp); @@ -93,8 +96,12 @@ class SequenceMaskKernel : public framework::OpKernel { y_dim.push_back(maxlen); y->Resize(framework::make_ddim(y_dim)); - PADDLE_ENFORCE_GT(maxlen, 0, - "MaxLenTensor value should be greater than 0"); + PADDLE_ENFORCE_GT( + maxlen, 0, + platform::errors::InvalidArgument( + "Input(MaxLenTensor) value should be greater than 0. But " + "received Input(MaxLenTensor) value = %d.", + maxlen)); } auto *x_data = x->data(); diff --git a/python/paddle/fluid/layers/rnn.py b/python/paddle/fluid/layers/rnn.py index 216caa21eb..f3606dae19 100644 --- a/python/paddle/fluid/layers/rnn.py +++ b/python/paddle/fluid/layers/rnn.py @@ -57,6 +57,7 @@ __all__ = [ class RNNCell(object): """ + RNNCell is the base class for abstraction representing the calculations mapping the input and state to the output and new state. It is suitable to and mostly used in RNN. @@ -221,6 +222,7 @@ class RNNCell(object): class GRUCell(RNNCell): """ + Gated Recurrent Unit cell. It is a wrapper for `fluid.contrib.layers.rnn_impl.BasicGRUUnit` to make it adapt to RNNCell. @@ -317,6 +319,7 @@ class GRUCell(RNNCell): class LSTMCell(RNNCell): """ + Long-Short Term Memory cell. It is a wrapper for `fluid.contrib.layers.rnn_impl.BasicLSTMUnit` to make it adapt to RNNCell. @@ -431,6 +434,7 @@ def rnn(cell, is_reverse=False, **kwargs): """ + rnn creates a recurrent neural network specified by RNNCell `cell`, which performs :code:`cell.call()` repeatedly until reaches to the maximum length of `inputs`. @@ -575,6 +579,7 @@ def rnn(cell, class Decoder(object): """ + Decoder is the base class for any decoder instance used in `dynamic_decode`. It provides interface for output generation for one time step, which can be used to generate sequences. @@ -664,6 +669,7 @@ class Decoder(object): class BeamSearchDecoder(Decoder): """ + Decoder with beam search decoding strategy. It wraps a cell to get probabilities, and follows a beam search step to calculate scores and select candidate token ids for each decoding step. @@ -1127,6 +1133,7 @@ def dynamic_decode(decoder, return_length=False, **kwargs): """ + Dynamic decoding performs :code:`decoder.step()` repeatedly until the returned Tensor indicating finished status contains all True values or the number of decoding step reaches to :attr:`max_step_num`. @@ -1941,6 +1948,7 @@ def dynamic_lstm(input, dtype='float32', name=None): """ + **Note**: 1. This OP only supports LoDTensor as inputs. If you need to deal with Tensor, please use :ref:`api_fluid_layers_lstm` . 2. In order to improve efficiency, users must first map the input of dimension [T, hidden_size] to input of [T, 4 * hidden_size], and then pass it to this OP. @@ -2111,6 +2119,7 @@ def lstm(input, default_initializer=None, seed=-1): """ + **Note**: This OP only supports running on GPU devices. @@ -2296,6 +2305,7 @@ def dynamic_lstmp(input, cell_clip=None, proj_clip=None): """ + **Note**: 1. In order to improve efficiency, users must first map the input of dimension [T, hidden_size] to input of [T, 4 * hidden_size], and then pass it to this OP. @@ -2505,6 +2515,7 @@ def dynamic_gru(input, h_0=None, origin_mode=False): """ + **Note: The input type of this must be LoDTensor. If the input type to be processed is Tensor, use** :ref:`api_fluid_layers_StaticRNN` . @@ -2665,6 +2676,7 @@ def gru_unit(input, gate_activation='sigmoid', origin_mode=False): """ + Gated Recurrent Unit (GRU) RNN cell. This operator performs GRU calculations for one time step and it supports these two modes: @@ -2821,6 +2833,7 @@ def beam_search(pre_ids, name=None, return_parent_idx=False): """ + Beam search is a classical algorithm for selecting candidate words in a machine translation task. @@ -2922,6 +2935,12 @@ def beam_search(pre_ids, beam_size=beam_size, end_id=end_id) """ + check_variable_and_dtype(pre_ids, 'pre_ids', ['int64'], 'beam_search') + check_variable_and_dtype(pre_scores, 'pre_scores', ['float32', 'float64'], + 'beam_search') + check_type(ids, 'ids', (Variable, type(None)), 'beam_search') + check_variable_and_dtype(scores, 'scores', ['float32', 'float64'], + 'beam_search') helper = LayerHelper('beam_search', **locals()) score_type = pre_scores.dtype id_type = pre_ids.dtype @@ -2962,6 +2981,7 @@ def beam_search(pre_ids, def beam_search_decode(ids, scores, beam_size, end_id, name=None): """ + This operator is used after beam search has completed. It constructs the full predicted sequences for each sample by walking back along the search paths stored in lod of ``ids`` . The result sequences are stored in a @@ -3015,6 +3035,9 @@ def beam_search_decode(ids, scores, beam_size, end_id, name=None): finished_ids, finished_scores = fluid.layers.beam_search_decode( ids, scores, beam_size=5, end_id=0) """ + check_variable_and_dtype(ids, 'ids', ['int64'], 'beam_search_encode') + check_variable_and_dtype(scores, 'scores', ['float32'], + 'beam_search_encode') helper = LayerHelper('beam_search_decode', **locals()) sentence_ids = helper.create_variable_for_type_inference(dtype=ids.dtype) sentence_scores = helper.create_variable_for_type_inference(dtype=ids.dtype) @@ -3041,6 +3064,7 @@ def lstm_unit(x_t, bias_attr=None, name=None): """ + Long-Short Term Memory (LSTM) RNN cell. This operator performs LSTM calculations for one time step, whose implementation is based on calculations described in `RECURRENT NEURAL NETWORK REGULARIZATION `_ . diff --git a/python/paddle/fluid/layers/sequence_lod.py b/python/paddle/fluid/layers/sequence_lod.py index 15be39d6af..b0dda4ba25 100644 --- a/python/paddle/fluid/layers/sequence_lod.py +++ b/python/paddle/fluid/layers/sequence_lod.py @@ -314,7 +314,7 @@ def sequence_pool(input, pool_type, is_test=False, pad_value=0.0): where 1.=1., 5.=3. + 2., 4.=4., 0.0=pad_value, 12.=6. + 5. + 1. Args: - input (variable): LoDTensor with lod_level no more than 2. The data type should be float32. + input (variable): LoDTensor with lod_level no more than 2. The data type should be float32 or float64. pool_type (str): The pooling type that supports average, sum, sqrt, max, last or first. is_test (bool): Only works when :attr:`pool_type` is max. If set False, a temporary Tenosr maxIndex is created to record the index information corresponding to the maximum value, which is used for backward @@ -322,7 +322,7 @@ def sequence_pool(input, pool_type, is_test=False, pad_value=0.0): pad_value (float): Used to pad the pooling result for empty input sequence. Default: 0.0 Returns: - Variable: LoDTensor after pooling with data type float32. + Variable: LoDTensor after pooling with data type float32 or float64. Examples: @@ -464,10 +464,10 @@ def sequence_first_step(input): where 1.=first(1.), 3.=first(3., 2.), 4.=first(4.), 0.0 = pad_value, 6.=first(6., 5., 1.) Args: - input(Variable): LoDTensor with lod_level no more than 2. The data type should be float32. + input(Variable): LoDTensor with lod_level no more than 2. The data type should be float32 or float64. Returns: - Variable: LoDTensor consist of the sequence's first step vector. The data type is float32. + Variable: LoDTensor consist of the sequence's first step vector. The data type is float32 or float64. Examples: @@ -477,6 +477,8 @@ def sequence_first_step(input): x = fluid.data(name='x', shape=[None, 10], dtype='float32', lod_level=1) x_first_step = fluid.layers.sequence_first_step(input=x) """ + check_variable_and_dtype(input, 'input', ['float32', 'float64'], + 'sequence_first_step') return sequence_pool(input=input, pool_type="first") @@ -530,6 +532,8 @@ def sequence_last_step(input): x = fluid.data(name='x', shape=[None, 10], dtype='float32', lod_level=1) x_last_step = fluid.layers.sequence_last_step(input=x) """ + check_variable_and_dtype(input, 'input', ['float32', 'float64'], + 'sequence_last_step') return sequence_pool(input=input, pool_type="last") diff --git a/python/paddle/fluid/tests/unittests/sequence/test_sequence_first_step.py b/python/paddle/fluid/tests/unittests/sequence/test_sequence_first_step.py new file mode 100644 index 0000000000..0e7f9202fd --- /dev/null +++ b/python/paddle/fluid/tests/unittests/sequence/test_sequence_first_step.py @@ -0,0 +1,50 @@ +# Copyright (c) 2018 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. +import paddle.fluid as fluid +from paddle.fluid.framework import convert_np_dtype_to_dtype_, Program, program_guard +import paddle.fluid.core as core +import numpy as np +import copy +import unittest +import sys +sys.path.append("../") +from op_test import OpTest + + +class TestSequenceFirstStepOpError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + + def test_Variable(): + # the input must be Variable + input_data = np.random.randint(1, 5, [4]).astype("int64") + fluid.layers.sequence_last_step(input_data) + + self.assertRaises(TypeError, test_Variable) + + def test_input_dtype(): + # the dtype of input must be int64 + type_data = fluid.layers.data( + name='type_data', + shape=[7, 1], + append_batch_size=False, + dtype='int64', + lod_level=1) + fluid.layers.sequence_last_step(type_data) + + self.assertRaises(TypeError, test_input_dtype) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/sequence/test_sequence_last_step.py b/python/paddle/fluid/tests/unittests/sequence/test_sequence_last_step.py new file mode 100644 index 0000000000..ea3a29a832 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/sequence/test_sequence_last_step.py @@ -0,0 +1,50 @@ +# Copyright (c) 2018 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. +import paddle.fluid as fluid +from paddle.fluid.framework import convert_np_dtype_to_dtype_, Program, program_guard +import paddle.fluid.core as core +import numpy as np +import copy +import unittest +import sys +sys.path.append("../") +from op_test import OpTest + + +class TestSequenceLastStepOpError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + + def test_Variable(): + # the input must be Variable + input_data = np.random.randint(1, 5, [4]).astype("int64") + fluid.layers.sequence_last_step(input_data) + + self.assertRaises(TypeError, test_Variable) + + def test_input_dtype(): + # the dtype of input must be int64 + type_data = fluid.layers.data( + name='type_data', + shape=[7, 1], + append_batch_size=False, + dtype='int64', + lod_level=1) + fluid.layers.sequence_last_step(type_data) + + self.assertRaises(TypeError, test_input_dtype) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/sequence/test_sequence_mask.py b/python/paddle/fluid/tests/unittests/sequence/test_sequence_mask.py index f1efb78d78..de41235fd3 100644 --- a/python/paddle/fluid/tests/unittests/sequence/test_sequence_mask.py +++ b/python/paddle/fluid/tests/unittests/sequence/test_sequence_mask.py @@ -13,7 +13,7 @@ # limitations under the License. import paddle.fluid as fluid -from paddle.fluid.framework import convert_np_dtype_to_dtype_ +from paddle.fluid.framework import convert_np_dtype_to_dtype_, Program, program_guard import paddle.fluid.core as core import numpy as np import copy @@ -154,5 +154,17 @@ class SequenceMaskTest5_tensor_attr(SequenceMaskTestBase_tensor_attr): self.mask_dtype = 'float64' +class TestSequenceMaskOpError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + input_data = np.random.uniform(1, 5, [4]).astype("float32") + + def test_Variable(): + # the input must be Variable + fluid.layers.sequence_mask(input_data, maxlen=4) + + self.assertRaises(TypeError, test_Variable) + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_beam_search_decode_op.py b/python/paddle/fluid/tests/unittests/test_beam_search_decode_op.py index 51eee41ab2..cc3fab9056 100644 --- a/python/paddle/fluid/tests/unittests/test_beam_search_decode_op.py +++ b/python/paddle/fluid/tests/unittests/test_beam_search_decode_op.py @@ -19,6 +19,8 @@ import unittest import numpy as np import paddle.fluid.core as core from paddle.fluid.op import Operator +import paddle.fluid as fluid +from paddle.fluid.framework import Program, program_guard class TestBeamSearchDecodeOp(unittest.TestCase): @@ -110,5 +112,46 @@ class TestBeamSearchDecodeOpGPU(TestBeamSearchDecodeOp): self.place = core.CUDAPlace(0) +class TestBeamSearchDecodeOpError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + + def test_id_Variable(): + # the input pre_ids must be Variable + test_ids = np.random.randint(1, 5, [5, 1]).astype("int64") + scores = fluid.layers.create_array(dtype='float32') + fluid.layers.beam_search_decode( + test_ids, scores, beam_size=5, end_id=0) + + self.assertRaises(TypeError, test_id_Variable) + + def test_score_Variable(): + # the input pre_scores must be Variable + ids = fluid.layers.create_array(dtype='int64') + test_scores = np.random.uniform(1, 5, [5, 1]).astype("float32") + fluid.layers.beam_search_decode( + ids, test_scores, beam_size=5, end_id=0) + + self.assertRaises(TypeError, test_score_Variable) + + def test_id_dtype(): + # the dtype of input pre_ids must be int64 + type_ids = fluid.layers.create_array(dtype='float32') + scores = fluid.layers.create_array(dtype='float32') + fluid.layers.beam_search_decode( + type_ids, scores, beam_size=5, end_id=0) + + self.assertRaises(TypeError, test_id_dtype) + + def test_score_dtype(): + # the dtype of input pre_scores must be float32 + ids = fluid.layers.create_array(dtype='int64') + type_scores = fluid.layers.create_array(dtype='int64') + fluid.layers.beam_search_decode( + ids, type_scores, beam_size=5, end_id=0) + + self.assertRaises(TypeError, test_score_dtype) + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_beam_search_op.py b/python/paddle/fluid/tests/unittests/test_beam_search_op.py index 1d9f4b78f3..faf085eb6c 100644 --- a/python/paddle/fluid/tests/unittests/test_beam_search_op.py +++ b/python/paddle/fluid/tests/unittests/test_beam_search_op.py @@ -19,6 +19,8 @@ from paddle.fluid.op import Operator, DynamicRecurrentOp import paddle.fluid.core as core import unittest import numpy as np +import paddle.fluid as fluid +from paddle.fluid.framework import Program, program_guard def create_tensor(scope, name, np_data): @@ -96,5 +98,108 @@ class BeamSearchOpTester(unittest.TestCase): tensor.set_lod(self.lod) +class TestBeamSearchOpError(unittest.TestCase): + def test_errors(self): + with program_guard(Program(), Program()): + pre_ids = fluid.data( + name='pre_id', shape=[1], lod_level=2, dtype='int64') + pre_scores = fluid.data( + name='pre_scores', shape=[1], lod_level=2, dtype='float32') + probs = fluid.data(name='probs', shape=[10000], dtype='float32') + topk_scores, topk_indices = fluid.layers.topk(probs, k=4) + accu_scores = fluid.layers.elementwise_add( + x=fluid.layers.log(x=topk_scores), + y=fluid.layers.reshape( + pre_scores, shape=[-1]), + axis=0) + + def test_preids_Variable(): + # the input pre_ids must be Variable + preids_data = np.random.randint(1, 5, [5, 1]).astype("int64") + fluid.layers.beam_search( + pre_ids=preids_data, + pre_scores=pre_scores, + ids=topk_indices, + scores=accu_scores, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_preids_Variable) + + def test_prescores_Variable(): + # the input pre_scores must be Variable + prescores_data = np.random.uniform(1, 5, + [5, 1]).astype("float32") + fluid.layers.beam_search( + pre_ids=pre_ids, + pre_scores=prescores_data, + ids=topk_indices, + scores=accu_scores, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_prescores_Variable) + + def test_ids_Variable(): + # the input ids must be Variable or None + ids_data = np.random.randint(1, 5, [5, 1]).astype("int64") + fluid.layers.beam_search( + pre_ids=pre_ids, + pre_scores=pre_scores, + ids=ids_data, + scores=accu_scores, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_ids_Variable) + + def test_scores_Variable(): + # the input scores must be Variable + scores_data = np.random.uniform(1, 5, [5, 1]).astype("float32") + fluid.layers.beam_search( + pre_ids=pre_ids, + pre_scores=pre_scores, + ids=topk_indices, + scores=scores_data, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_scores_Variable) + + def test_preids_dtype(): + # the dtype of input pre_ids must be int64 + preids_type_data = fluid.data( + name='preids_type_data', + shape=[1], + lod_level=2, + dtype='float32') + fluid.layers.beam_search( + pre_ids=preids_type_data, + pre_scores=pre_scores, + ids=topk_indices, + scores=accu_scores, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_preids_dtype) + + def test_prescores_dtype(): + # the dtype of input pre_scores must be float32 + prescores_type_data = fluid.data( + name='prescores_type_data', + shape=[1], + lod_level=2, + dtype='int64') + fluid.layers.beam_search( + pre_ids=pre_ids, + pre_scores=prescores_type_data, + ids=topk_indices, + scores=accu_scores, + beam_size=4, + end_id=1) + + self.assertRaises(TypeError, test_prescores_dtype) + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_rnn_cell_api.py b/python/paddle/fluid/tests/unittests/test_rnn_cell_api.py index 721bb92d11..6b9438eece 100644 --- a/python/paddle/fluid/tests/unittests/test_rnn_cell_api.py +++ b/python/paddle/fluid/tests/unittests/test_rnn_cell_api.py @@ -541,7 +541,7 @@ def def_seq2seq_model(num_layers, hidden_size, dropout_prob, src_vocab_size, loss = layers.unsqueeze(loss, axes=[2]) max_tar_seq_len = layers.shape(target)[1] tar_mask = layers.sequence_mask( - target_length, maxlen=max_tar_seq_len, dtype="float") + target_length, maxlen=max_tar_seq_len, dtype="float32") loss = loss * tar_mask loss = layers.reduce_mean(loss, dim=[0]) loss = layers.reduce_sum(loss) -- GitLab