diff --git a/paddle/fluid/eager/eager_tensor.h b/paddle/fluid/eager/eager_tensor.h index b11acae566d741da5eb8f2604d3ec4f4ec88cef3..dd9881fcd5f0f41c71cf31b05df9f4c11bd60fe1 100644 --- a/paddle/fluid/eager/eager_tensor.h +++ b/paddle/fluid/eager/eager_tensor.h @@ -21,24 +21,176 @@ #include "paddle/phi/api/include/tensor.h" #include "paddle/phi/api/lib/utils/tensor_utils.h" #include "paddle/phi/core/compat/convert_utils.h" + +namespace egr { + +/** + * VariableCompatTensor class is used by Eager mode for now. It's painful to + * do this in Eager Mode, the better choice is to design the special Tensor + * directly in phi and use it in paddle::experimental::Tensor. + * However, we have some special operators, and they use special input variable + * type, such as vector, unordered_map, these type cannot + * cover by DenseTensor or SparseTensor. So, we have to provide a compatible + * Tensor type like variable to support these special input type. We should + * remove this as soon as we finish the ResourceTensor in phi. + * + * Note: Keep this class as clean as possible. + * This class should only support method declared in framework::Variable and + * necessary overridden methods. + * + * Note: This class is only used to support types that cannot be supported by + * the phi Tensor system temporarily. You CANNOT use this class to handle types + * such as DenseTensor, SelectedRows, etc. + **/ +class VariableCompatTensor + : public phi::TensorBase, + public phi::TypeInfoTraits { + public: + template + const T& Get() const { + static_assert( + paddle::framework::IsRegisteredVarType(), + "Not registered type. Please register T inside var_type_traits.h"); + PADDLE_ENFORCE_NOT_NULL(holder_, paddle::platform::errors::NotFound( + "Variable is not initialized.")); + PADDLE_ENFORCE_EQ( + holder_->Type(), paddle::framework::VarTypeTrait::kId, + paddle::platform::errors::InvalidArgument( + "The Variable type must be %s, but the type it holds is %s.", + paddle::framework::ToTypeName( + paddle::framework::VarTypeTrait::kId), + paddle::framework::ToTypeName(holder_->Type()))); + return *static_cast(holder_->Ptr()); + } + + bool IsInitialized() const { return holder_ != nullptr; } + + template + T* GetMutable() { + if (!holder_) { + holder_.reset(new PlaceholderImpl()); + } else { + PADDLE_ENFORCE_EQ( + holder_->Type(), paddle::framework::VarTypeTrait::kId, + paddle::platform::errors::InvalidArgument( + "The Variable type must be %s, but the type it holds is %s.", + paddle::framework::ToTypeName( + paddle::framework::VarTypeTrait::kId), + paddle::framework::ToTypeName(holder_->Type()))); + } + return static_cast(holder_->Ptr()); + } + + template + bool IsType() const { + return holder_ && + holder_->Type() == paddle::framework::VarTypeTrait::kId; + } + + void Clear() { holder_.reset(); } + + int Type() const { + PADDLE_ENFORCE_NOT_NULL(holder_, paddle::platform::errors::NotFound( + "Variable is not initialized.")); + return holder_->Type(); + } + + // necessary overridden methods + + static const char* name() { return "VariableCompatTensor"; } + + ~VariableCompatTensor() override = default; + + int64_t numel() const override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `numel` method.")); + } + + const phi::DDim& dims() const override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `dims` method.")); + } + + phi::DataType dtype() const override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `dtype` method.")); + } + + phi::DataLayout layout() const override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `layout` method.")); + } + + const phi::Place& place() const override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `place` method.")); + } + + bool valid() const override { return IsInitialized(); } + + bool initialized() const override { return IsInitialized(); } + + void* AllocateFrom(phi::Allocator* allocator, phi::DataType dtype, + size_t requested_size = 0) override { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor does not support `AllocateFrom` method.")); + } + + private: + struct Placeholder { + virtual ~Placeholder() PADDLE_MAY_THROW {} + + inline int Type() const { return type_; } + inline const void* Ptr() const { return ptr_; } + inline void* Ptr() { return ptr_; } + + protected: + inline void Init(void* p, int type) { + ptr_ = p; + type_ = type; + } + + void* ptr_; + int type_; + }; + + // Placeholder hides type T, so it doesn't appear as a template + // parameter of Variable. + template + struct PlaceholderImpl : public Placeholder { + static_assert( + paddle::framework::IsRegisteredVarType(), + "Not registered type. Please register T inside var_type_traits.h"); + PlaceholderImpl() { + this->Init(&obj_, paddle::framework::VarTypeTrait::kId); + } + + private: + T obj_; + }; + + // pointers to a PlaceholderImpl object indeed. + std::shared_ptr holder_; +}; + +inline bool IsVariableCompatTensor(const paddle::experimental::Tensor& tensor) { + return VariableCompatTensor::classof(tensor.impl().get()); +} + /** * This class is used by Eager mode for now. It's painful to do this in Eager - * Mode, the better - * choice is to use paddle::experimental::Tensor directly. However, we have a - * punch of nested kernel code, and - * they use paddle::framework::Variable in inner logic code. So, we have to - * provide variable in - * paddle::framework::ExecutionContext to support it. We should remove this as - * soon as we finish our latest - * Phi Lib, and use paddle::experimental::Tensor instead. + * Mode, the better choice is to use paddle::experimental::Tensor directly. + * However, we have a punch of nested kernel code, and they use + * paddle::framework::Variable in inner logic code. So, we have to provide + * variable in paddle::framework::ExecutionContext to support it. We should + * remove this as soon as we finish our latest Phi Lib, and use + * paddle::experimental::Tensor instead. * * Note: Keep this class as clean as possible. * This class should only support method declared in * paddle::experimental::Tensor with access method of * paddle::framework::Variable no more members are acceptable. * **/ - -namespace egr { class EagerVariable final { public: /* Default constructor and name constructor should only be used for contruct @@ -54,6 +206,14 @@ class EagerVariable final { ConstructVariableFromTensor(tensor); } else if (tensor.is_selected_rows()) { ConstructVariableFromTensor(tensor); + } else if (IsVariableCompatTensor(tensor) && + static_cast(tensor.impl().get()) + ->IsType()) { + ConstructVariableFromCompatTensor(tensor); + } else if (IsVariableCompatTensor(tensor) && + static_cast(tensor.impl().get()) + ->IsType()) { + ConstructVariableFromCompatTensor(tensor); } else { PADDLE_THROW(paddle::platform::errors::Fatal( "Unrecognized egr::EagerVariable type, only " @@ -119,6 +279,22 @@ class EagerVariable final { *framework_tensor = *tensor_dense; } + template + void ConstructVariableFromCompatTensor( + const paddle::experimental::Tensor& tensor) { + auto* framework_holder = var_.GetMutable(); + // Contruct framework::Tensor from egr::EagerVariable + auto* compat_tensor = + static_cast(tensor.impl().get()); + PADDLE_ENFORCE_NOT_NULL(compat_tensor, + paddle::platform::errors::Fatal( + "Tensor %s holds empty impl, this should not " + "happend since we should " + "treat all kinds of tensor as what they are.", + tensor.name())); + *framework_holder = compat_tensor->Get(); + } + private: std::string name_{""}; paddle::framework::Variable var_; diff --git a/paddle/fluid/eager/tests/data_structure_tests/eager_tensor_test.cc b/paddle/fluid/eager/tests/data_structure_tests/eager_tensor_test.cc index a9a50a3621767bb8108af808cb86f9961cd512af..edbb441f27a08dc29010ef950dc5c2639617b1a9 100644 --- a/paddle/fluid/eager/tests/data_structure_tests/eager_tensor_test.cc +++ b/paddle/fluid/eager/tests/data_structure_tests/eager_tensor_test.cc @@ -233,3 +233,88 @@ TEST(EagerVariable, DataLayout) { layout = paddle::imperative::GetDataLayout(eager_var); CHECK_EQ(layout, paddle::experimental::DataLayout::NCHW); } + +TEST(VariableCompatTensor, MemberFunction) { + egr::VariableCompatTensor var_tensor; + // test GetMutable and Get + var_tensor.GetMutable(); + auto& vocab = var_tensor.Get(); + EXPECT_EQ(vocab.size(), 0UL); + bool caught_exception = false; + try { + var_tensor.GetMutable(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("The Variable type must be") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + // test Type and IsType + EXPECT_TRUE(var_tensor.IsType()); + EXPECT_EQ(var_tensor.Type(), + static_cast(paddle::framework::proto::VarType::VOCAB)); + // test valid and initialized + EXPECT_TRUE(var_tensor.IsInitialized()); + EXPECT_TRUE(var_tensor.valid()); + EXPECT_TRUE(var_tensor.initialized()); + // test name + EXPECT_EQ(var_tensor.name(), "VariableCompatTensor"); + // test other throw error methods + caught_exception = false; + try { + var_tensor.numel(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("numel") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + caught_exception = false; + try { + var_tensor.dims(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("dims") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + caught_exception = false; + try { + var_tensor.dtype(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("dtype") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + caught_exception = false; + try { + var_tensor.layout(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("layout") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + caught_exception = false; + try { + var_tensor.place(); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("place") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + caught_exception = false; + try { + var_tensor.AllocateFrom(nullptr, phi::DataType::UNDEFINED); + } catch (paddle::platform::EnforceNotMet& error) { + caught_exception = true; + std::string ex_msg = error.what(); + EXPECT_TRUE(ex_msg.find("AllocateFrom") != std::string::npos); + } + EXPECT_TRUE(caught_exception); + // test Clear + var_tensor.Clear(); + EXPECT_FALSE(var_tensor.IsInitialized()); +} diff --git a/paddle/fluid/pybind/eager_method.cc b/paddle/fluid/pybind/eager_method.cc index 0661da775df84d789199bb25cd54a11a0a786ae6..4d7b80a4e8c966bf64bc10d60dbb15ecf21c8ed4 100644 --- a/paddle/fluid/pybind/eager_method.cc +++ b/paddle/fluid/pybind/eager_method.cc @@ -18,6 +18,7 @@ typedef SSIZE_T ssize_t; #include #include +#include #include #include "pybind11/numpy.h" @@ -675,7 +676,9 @@ static PyObject* tensor_method_get_underline_tensor(TensorObject* self, PyObject* kwargs) { EAGER_TRY if (!self->tensor.defined()) { - RETURN_PY_NONE + // The original `get_tensor` method of Variable will create a empty tensor + phi::DenseTensor empty_tensor; + return ToPyObject(&empty_tensor); } if (self->tensor.is_dense_tensor()) { auto* tensor = @@ -1275,6 +1278,47 @@ static PyObject* tensor__copy_gradient_from(TensorObject* self, PyObject* args, EAGER_CATCH_AND_THROW_RETURN_NULL } + +static PyObject* tensor_method_set_vocab(TensorObject* self, PyObject* args, + PyObject* kwargs) { + EAGER_TRY + using Vocab = std::unordered_map; + auto vocab = CastPyArg2Vocab(PyTuple_GET_ITEM(args, 0), 0); + auto var_tensor = std::make_shared(); + *var_tensor->GetMutable() = vocab; + self->tensor.set_impl(var_tensor); + RETURN_PY_NONE + EAGER_CATCH_AND_THROW_RETURN_NULL +} + +static PyObject* tensor_method_set_string_list(TensorObject* self, + PyObject* args, + PyObject* kwargs) { + EAGER_TRY + using Strings = std::vector; + auto strings = CastPyArg2Strings(PyTuple_GET_ITEM(args, 0), 0); + auto var_tensor = std::make_shared(); + *var_tensor->GetMutable() = strings; + self->tensor.set_impl(var_tensor); + RETURN_PY_NONE + EAGER_CATCH_AND_THROW_RETURN_NULL +} + +static PyObject* tensor_method_get_map_tensor(TensorObject* self, + PyObject* args, + PyObject* kwargs) { + EAGER_TRY + PADDLE_ENFORCE_EQ( + egr::IsVariableCompatTensor(self->tensor), true, + paddle::platform::errors::Fatal( + "this method is only effective for VariableCompatTensor")); + using Vocab = std::unordered_map; + auto* var_tensor = + static_cast(self->tensor.impl().get()); + return ToPyObject(var_tensor->Get()); + EAGER_CATCH_AND_THROW_RETURN_NULL +} + static PyObject* tensor_method_get_non_zero_indices(TensorObject* self, PyObject* args, PyObject* kwargs) { @@ -1655,6 +1699,15 @@ PyMethodDef variable_methods[] = { {"_copy_gradient_from", (PyCFunction)(void (*)(void))tensor__copy_gradient_from, METH_VARARGS | METH_KEYWORDS, NULL}, + /** the methods to adapt old dygraph, will be removed in the future **/ + {"set_string_list", + (PyCFunction)(void (*)(void))tensor_method_set_string_list, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"set_vocab", (PyCFunction)(void (*)(void))tensor_method_set_vocab, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"get_map_tensor", + (PyCFunction)(void (*)(void))tensor_method_get_map_tensor, + METH_VARARGS | METH_KEYWORDS, NULL}, /***the method of sparse tensor****/ {"indices", (PyCFunction)(void (*)(void))tensor_method_get_non_zero_indices, METH_VARARGS | METH_KEYWORDS, NULL}, diff --git a/paddle/fluid/pybind/eager_properties.cc b/paddle/fluid/pybind/eager_properties.cc index 0473c29a3342bec49570190144bfeae6fb6b64a9..590ecfbad4be5a1a5bd353eab97c0e2f24c926b7 100644 --- a/paddle/fluid/pybind/eager_properties.cc +++ b/paddle/fluid/pybind/eager_properties.cc @@ -58,6 +58,10 @@ PyObject* tensor_properties_get_type(TensorObject* self, void* closure) { return ToPyObject(paddle::framework::proto::VarType::LOD_TENSOR); } else if (self->tensor.is_selected_rows()) { return ToPyObject(paddle::framework::proto::VarType::SELECTED_ROWS); + } else if (egr::IsVariableCompatTensor(self->tensor)) { + return ToPyObject(static_cast( + static_cast(self->tensor.impl().get()) + ->Type())); } else { RETURN_PY_NONE } @@ -152,11 +156,27 @@ PyObject* tensor_properties_get_shape(TensorObject* self, void* closure) { if (!self->tensor.defined()) { return ToPyObject(value); } - auto ddim = self->tensor.shape(); - size_t rank = static_cast(ddim.size()); - value.resize(rank); - for (size_t i = 0; i < rank; i++) { - value[i] = ddim[i]; + if (egr::IsVariableCompatTensor(self->tensor)) { + auto* var_tensor = static_cast( + self->tensor.impl().get()); + if (var_tensor->IsType()) { + value.emplace_back(static_cast( + var_tensor->Get().size())); + } else if (var_tensor->IsType()) { + value.emplace_back(static_cast( + var_tensor->Get().size())); + } else { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor only support get shape from Vocab or " + "Strings.")); + } + } else { + auto ddim = self->tensor.shape(); + size_t rank = static_cast(ddim.size()); + value.resize(rank); + for (size_t i = 0; i < rank; i++) { + value[i] = ddim[i]; + } } return ToPyObject(value); @@ -183,8 +203,22 @@ PyObject* tensor_properties_get_dtype(TensorObject* self, void* closure) { // be same to old dygraph return ToPyObject(framework::proto::VarType::FP32); } - return ToPyObject( - paddle::framework::TransToProtoVarType(self->tensor.type())); + if (egr::IsVariableCompatTensor(self->tensor)) { + auto* var_tensor = static_cast( + self->tensor.impl().get()); + if (var_tensor->IsType()) { + return ToPyObject(framework::proto::VarType::RAW); + } else if (var_tensor->IsType()) { + return ToPyObject(framework::proto::VarType::STRING); + } else { + PADDLE_THROW(paddle::platform::errors::Unavailable( + "VariableCompatTensor only support get shape from Vocab or " + "Strings.")); + } + } else { + return ToPyObject( + paddle::framework::TransToProtoVarType(self->tensor.type())); + } EAGER_CATCH_AND_THROW_RETURN_NULL } diff --git a/paddle/fluid/pybind/eager_utils.cc b/paddle/fluid/pybind/eager_utils.cc index acdaa0293b09037d9562ecf309458fe3de16c8d2..4707f757d8bfb8cc7e12d34bf54ef2556b24fc48 100644 --- a/paddle/fluid/pybind/eager_utils.cc +++ b/paddle/fluid/pybind/eager_utils.cc @@ -472,6 +472,28 @@ paddle::framework::proto::VarType::Type CastPyArg2ProtoType(PyObject* obj, return dtype; } +std::unordered_map CastPyArg2Vocab(PyObject* obj, + ssize_t arg_pos) { + if (PyDict_Check(obj)) { + return ::pybind11::handle(obj) + .cast>(); + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "argument (position %d) must be dict, but got %s", arg_pos + 1, + reinterpret_cast(obj->ob_type)->tp_name)); + } +} + +std::vector CastPyArg2Strings(PyObject* obj, ssize_t arg_pos) { + if (PyList_Check(obj)) { + return ::pybind11::handle(obj).cast>(); + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "argument (position %d) must be list, but got %s", arg_pos + 1, + reinterpret_cast(obj->ob_type)->tp_name)); + } +} + paddle::CustomOpKernelContext CastPyArg2CustomOpKernelContext(PyObject* obj, ssize_t arg_pos) { if (PyObject_IsInstance( @@ -719,6 +741,28 @@ PyObject* ToPyObject( return dict; } +PyObject* ToPyObject(const std::unordered_map& value) { + PyObject* dict = PyDict_New(); + for (const auto map_iter : value) { + // Convert Key + PyObject* key_string = + PyUnicode_FromWideChar(map_iter.first.c_str(), map_iter.first.size()); + if (!key_string) { + PADDLE_THROW(platform::errors::Fatal( + "Unable to convert std::wstring to PyObject")); + } + + // Convert Val + PyObject* py_int = PyLong_FromLong(map_iter.second); + + if (PyDict_SetItem(dict, key_string, py_int) != 0) { + PADDLE_THROW( + platform::errors::Fatal("Unable to set key:value for py_dict")); + } + } + return dict; +} + // For Final State Dygraph, // We directly use paddle::optional(Tensor) as dispensable Tensor paddle::optional GetOptionalTensorFromArgs( diff --git a/paddle/fluid/pybind/eager_utils.h b/paddle/fluid/pybind/eager_utils.h index 5273433208d118ece1c1b0d1b6f230df3092f767..c8e1cd4ad0b7570b30ddad38a2ca992a4feaf9bb 100644 --- a/paddle/fluid/pybind/eager_utils.h +++ b/paddle/fluid/pybind/eager_utils.h @@ -65,6 +65,9 @@ std::vector> CastPyArg2VectorOfVectorOfSize_t( PyObject* obj, size_t arg_pos); framework::proto::VarType::Type CastPyArg2ProtoType(PyObject* obj, ssize_t arg_pos); +std::unordered_map CastPyArg2Vocab(PyObject* obj, + ssize_t arg_pos); +std::vector CastPyArg2Strings(PyObject* obj, ssize_t arg_pos); PyObject* ToPyObject(int value); PyObject* ToPyObject(uint32_t value); @@ -96,6 +99,7 @@ PyObject* ToPyObject(const paddle::framework::proto::VarType& type); PyObject* ToPyObject(const void* value); PyObject* ToPyObject( const std::unordered_map>& value); +PyObject* ToPyObject(const std::unordered_map& value); template struct TupleTensorResult { diff --git a/paddle/phi/api/lib/tensor.cc b/paddle/phi/api/lib/tensor.cc index a7b89d7a4dca9348278803a47e1cf3665bb2a53d..a340c0fed10d871efc8bb018741d03afce1fd00f 100644 --- a/paddle/phi/api/lib/tensor.cc +++ b/paddle/phi/api/lib/tensor.cc @@ -394,8 +394,8 @@ uint32_t Tensor::current_inplace_version() { static_cast(impl_.get())->InplaceVersionCounter(); return inplace_version_counter.CurrentVersion(); } else { - PADDLE_THROW(phi::errors::Unimplemented( - "current_inplace_version is only supported on DenseTensor now.")); + LOG_FIRST_N(WARNING, 1) + << "current_inplace_version is only supported on DenseTensor now."; } return 0; } diff --git a/python/paddle/fluid/tests/unittests/test_faster_tokenizer_op.py b/python/paddle/fluid/tests/unittests/test_faster_tokenizer_op.py index 87c4656cfa809c3d53463815ca0bd6d8f13c2e52..a460c5f252777db85a98ca01d16c4bb39ab3b344 100755 --- a/python/paddle/fluid/tests/unittests/test_faster_tokenizer_op.py +++ b/python/paddle/fluid/tests/unittests/test_faster_tokenizer_op.py @@ -22,8 +22,7 @@ import numpy as np import paddle import paddle.nn as nn from paddle.dataset.common import DATA_HOME -from paddle.fluid.framework import core, _non_static_mode, _enable_legacy_dygraph -_enable_legacy_dygraph() +from paddle.fluid.framework import core, _non_static_mode, _test_eager_guard from paddle.fluid.layer_helper import LayerHelper from paddle import _C_ops @@ -151,13 +150,12 @@ class Predictor(object): class TestBertTokenizerOp(unittest.TestCase): def setUp(self): self.bert_tokenizer = BertTokenizer.from_pretrained("bert-base-chinese") - self.faster_tokenizer = FasterTokenizer(self.bert_tokenizer.vocab) - self.init_data() self.save_path = os.path.join(DATA_HOME, "fast_tokenizer") self.param_path = os.path.join(self.save_path, "model.pdparams") self.inference_path = os.path.join(self.save_path, "inference") def init_data(self): + self.faster_tokenizer = FasterTokenizer(self.bert_tokenizer.vocab) self.text = [ '选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。' '酒店装修一般,但还算整洁。 泳池在大堂的屋顶,因此很小,不过女儿倒是喜欢。 包的早餐是西式的,' @@ -179,8 +177,8 @@ class TestBertTokenizerOp(unittest.TestCase): self.texts_tensor = to_string_tensor(self.texts, "texts") self.text_pairs_tensor = to_string_tensor(self.text_pairs, "text_pairs") - def test_padding(self): - + def run_padding(self): + self.init_data() self.max_seq_len = 128 self.pad_to_max_seq_len = True self.is_split_into_words = False @@ -283,7 +281,13 @@ class TestBertTokenizerOp(unittest.TestCase): np.allclose( token_type_ids, py_token_type_ids, rtol=0, atol=0.01)) - def test_no_padding(self): + def test_padding(self): + with _test_eager_guard(): + self.run_padding() + self.run_padding() + + def run_no_padding(self): + self.init_data() self.max_seq_len = 128 self.pad_to_max_seq_len = False self.is_split_into_words = False @@ -336,7 +340,13 @@ class TestBertTokenizerOp(unittest.TestCase): np.allclose( token_type_ids, py_token_type_ids, rtol=0, atol=0.01)) - def test_is_split_into_words(self): + def test_no_padding(self): + with _test_eager_guard(): + self.run_no_padding() + self.run_no_padding() + + def run_is_split_into_words(self): + self.init_data() self.is_split_into_words = True input_ids, token_type_ids = self.faster_tokenizer( @@ -355,7 +365,13 @@ class TestBertTokenizerOp(unittest.TestCase): np.allclose( token_type_ids, py_token_type_ids, rtol=0, atol=0.01)) + def test_is_split_into_words(self): + with _test_eager_guard(): + self.run_is_split_into_words() + self.run_is_split_into_words() + def test_inference(self): + self.init_data() if not os.path.exists(self.save_path): os.makedirs(self.save_path, exist_ok=True) paddle.save(self.faster_tokenizer.state_dict(), self.param_path) @@ -383,6 +399,7 @@ class TestBertTokenizerOp(unittest.TestCase): token_type_ids, py_token_type_ids, rtol=0, atol=0.01)) def test_feed_string_var(self): + self.init_data() paddle.enable_static() x = paddle.static.data( name="x", shape=[-1], dtype=core.VarDesc.VarType.STRINGS)