Browse Source

TensorOp decoupling stage 3 (transform ops)

Signed-off-by: alex-yuyue <yue.yu1@huawei.com>
pull/14579/head
alex-yuyue 4 years ago
parent
commit
83aaed09bb
11 changed files with 724 additions and 127 deletions
  1. +0
    -69
      mindspore/ccsrc/minddata/dataset/api/python/bindings/dataset/kernels/data/bindings.cc
  2. +88
    -0
      mindspore/ccsrc/minddata/dataset/api/python/bindings/dataset/kernels/ir/bindings.cc
  3. +73
    -0
      mindspore/ccsrc/minddata/dataset/api/transforms.cc
  4. +1
    -33
      mindspore/ccsrc/minddata/dataset/core/tensor_helpers.h
  5. +10
    -0
      mindspore/ccsrc/minddata/dataset/include/constants.h
  6. +144
    -0
      mindspore/ccsrc/minddata/dataset/include/transforms.h
  7. +0
    -9
      mindspore/ccsrc/minddata/dataset/kernels/data/data_utils.h
  8. +75
    -0
      mindspore/ccsrc/minddata/dataset/kernels/ir/data/transforms_ir.cc
  9. +75
    -0
      mindspore/ccsrc/minddata/dataset/kernels/ir/data/transforms_ir.h
  10. +25
    -16
      mindspore/dataset/transforms/c_transforms.py
  11. +233
    -0
      tests/ut/cpp/dataset/c_api_transforms_test.cc

+ 0
- 69
mindspore/ccsrc/minddata/dataset/api/python/bindings/dataset/kernels/data/bindings.cc View File

@@ -18,91 +18,22 @@
#include "pybind11/stl_bind.h" #include "pybind11/stl_bind.h"


#include "minddata/dataset/api/python/pybind_register.h" #include "minddata/dataset/api/python/pybind_register.h"
#include "minddata/dataset/core/tensor_helpers.h"
#include "minddata/dataset/kernels/data/concatenate_op.h"
#include "minddata/dataset/kernels/data/fill_op.h" #include "minddata/dataset/kernels/data/fill_op.h"
#include "minddata/dataset/kernels/data/mask_op.h"
#include "minddata/dataset/kernels/data/pad_end_op.h"
#include "minddata/dataset/kernels/data/slice_op.h"
#include "minddata/dataset/kernels/data/to_float16_op.h" #include "minddata/dataset/kernels/data/to_float16_op.h"


namespace mindspore { namespace mindspore {
namespace dataset { namespace dataset {


PYBIND_REGISTER(ConcatenateOp, 1, ([](const py::module *m) {
(void)py::class_<ConcatenateOp, TensorOp, std::shared_ptr<ConcatenateOp>>(*m, "ConcatenateOp")
.def(py::init<int8_t, std::shared_ptr<Tensor>, std::shared_ptr<Tensor>>());
}));

PYBIND_REGISTER( PYBIND_REGISTER(
FillOp, 1, ([](const py::module *m) { FillOp, 1, ([](const py::module *m) {
(void)py::class_<FillOp, TensorOp, std::shared_ptr<FillOp>>(*m, "FillOp").def(py::init<std::shared_ptr<Tensor>>()); (void)py::class_<FillOp, TensorOp, std::shared_ptr<FillOp>>(*m, "FillOp").def(py::init<std::shared_ptr<Tensor>>());
})); }));


PYBIND_REGISTER(MaskOp, 1, ([](const py::module *m) {
(void)py::class_<MaskOp, TensorOp, std::shared_ptr<MaskOp>>(*m, "MaskOp")
.def(py::init<RelationalOp, std::shared_ptr<Tensor>, DataType>());
}));

PYBIND_REGISTER(PadEndOp, 1, ([](const py::module *m) {
(void)py::class_<PadEndOp, TensorOp, std::shared_ptr<PadEndOp>>(*m, "PadEndOp")
.def(py::init<TensorShape, std::shared_ptr<Tensor>>());
}));

PYBIND_REGISTER(SliceOption, 0, ([](const py::module *m) {
(void)py::class_<SliceOption>(*m, "SliceOption")
.def(py::init([](const py::slice &py_slice) {
Slice c_slice;
if (!py_slice.attr("start").is_none() && !py_slice.attr("stop").is_none() &&
!py_slice.attr("step").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("start")),
py::reinterpret_borrow<py::int_>(py_slice.attr("stop")),
py::reinterpret_borrow<py::int_>(py_slice.attr("step")));
} else if (py_slice.attr("start").is_none() && py_slice.attr("step").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("stop")));
} else if (!py_slice.attr("start").is_none() && !py_slice.attr("stop").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("start")),
py::reinterpret_borrow<py::int_>(py_slice.attr("stop")));
}

if (!c_slice.valid()) {
THROW_IF_ERROR(
Status(StatusCode::kMDUnexpectedError, __LINE__, __FILE__, "Wrong slice object"));
}
return SliceOption(c_slice);
}))
.def(py::init([](const py::list &py_list) {
std::vector<dsize_t> indices;
for (auto l : py_list) {
indices.push_back(py::reinterpret_borrow<py::int_>(l));
}
return SliceOption(indices);
}))
.def(py::init<bool>())
.def(py::init<SliceOption>());
}));

PYBIND_REGISTER(SliceOp, 1, ([](const py::module *m) {
(void)py::class_<SliceOp, TensorOp, std::shared_ptr<SliceOp>>(*m, "SliceOp")
.def(py::init<std::vector<SliceOption>>());
}));

PYBIND_REGISTER(ToFloat16Op, 1, ([](const py::module *m) { PYBIND_REGISTER(ToFloat16Op, 1, ([](const py::module *m) {
(void)py::class_<ToFloat16Op, TensorOp, std::shared_ptr<ToFloat16Op>>(*m, "ToFloat16Op", (void)py::class_<ToFloat16Op, TensorOp, std::shared_ptr<ToFloat16Op>>(*m, "ToFloat16Op",
py::dynamic_attr()) py::dynamic_attr())
.def(py::init<>()); .def(py::init<>());
})); }));


PYBIND_REGISTER(RelationalOp, 0, ([](const py::module *m) {
(void)py::enum_<RelationalOp>(*m, "RelationalOp", py::arithmetic())
.value("EQ", RelationalOp::kEqual)
.value("NE", RelationalOp::kNotEqual)
.value("LT", RelationalOp::kLess)
.value("LE", RelationalOp::kLessEqual)
.value("GT", RelationalOp::kGreater)
.value("GE", RelationalOp::kGreaterEqual)
.export_values();
}));

} // namespace dataset } // namespace dataset
} // namespace mindspore } // namespace mindspore

+ 88
- 0
mindspore/ccsrc/minddata/dataset/api/python/bindings/dataset/kernels/ir/bindings.cc View File

@@ -15,6 +15,7 @@
*/ */
#include "pybind11/pybind11.h" #include "pybind11/pybind11.h"


#include "mindspore/ccsrc/minddata/dataset/include/transforms.h"
#include "minddata/dataset/api/python/pybind_register.h" #include "minddata/dataset/api/python/pybind_register.h"
#include "minddata/dataset/core/global_context.h" #include "minddata/dataset/core/global_context.h"


@@ -64,6 +65,16 @@ PYBIND_REGISTER(
})); }));
})); }));


PYBIND_REGISTER(ConcatenateOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::ConcatenateOperation, TensorOperation,
std::shared_ptr<transforms::ConcatenateOperation>>(*m, "ConcatenateOperation")
.def(py::init([](int8_t axis, std::shared_ptr<Tensor> prepend, std::shared_ptr<Tensor> append) {
auto concatenate = std::make_shared<transforms::ConcatenateOperation>(axis, prepend, append);
THROW_IF_ERROR(concatenate->ValidateParams());
return concatenate;
}));
}));

PYBIND_REGISTER( PYBIND_REGISTER(
DuplicateOperation, 1, ([](const py::module *m) { DuplicateOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::DuplicateOperation, TensorOperation, std::shared_ptr<transforms::DuplicateOperation>>( (void)py::class_<transforms::DuplicateOperation, TensorOperation, std::shared_ptr<transforms::DuplicateOperation>>(
@@ -75,6 +86,17 @@ PYBIND_REGISTER(
})); }));
})); }));


PYBIND_REGISTER(MaskOperation, 1, ([](const py::module *m) {
(void)
py::class_<transforms::MaskOperation, TensorOperation, std::shared_ptr<transforms::MaskOperation>>(
*m, "MaskOperation")
.def(py::init([](RelationalOp op, std::shared_ptr<Tensor> constant, DataType dtype) {
auto mask = std::make_shared<transforms::MaskOperation>(op, constant, dtype);
THROW_IF_ERROR(mask->ValidateParams());
return mask;
}));
}));

PYBIND_REGISTER( PYBIND_REGISTER(
OneHotOperation, 1, ([](const py::module *m) { OneHotOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::OneHotOperation, TensorOperation, std::shared_ptr<transforms::OneHotOperation>>( (void)py::class_<transforms::OneHotOperation, TensorOperation, std::shared_ptr<transforms::OneHotOperation>>(
@@ -86,6 +108,17 @@ PYBIND_REGISTER(
})); }));
})); }));


PYBIND_REGISTER(
PadEndOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::PadEndOperation, TensorOperation, std::shared_ptr<transforms::PadEndOperation>>(
*m, "PadEndOperation")
.def(py::init([](TensorShape pad_shape, std::shared_ptr<Tensor> pad_value) {
auto pad_end = std::make_shared<transforms::PadEndOperation>(pad_shape, pad_value);
THROW_IF_ERROR(pad_end->ValidateParams());
return pad_end;
}));
}));

PYBIND_REGISTER(RandomChoiceOperation, 1, ([](const py::module *m) { PYBIND_REGISTER(RandomChoiceOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::RandomChoiceOperation, TensorOperation, (void)py::class_<transforms::RandomChoiceOperation, TensorOperation,
std::shared_ptr<transforms::RandomChoiceOperation>>(*m, "RandomChoiceOperation") std::shared_ptr<transforms::RandomChoiceOperation>>(*m, "RandomChoiceOperation")
@@ -110,6 +143,50 @@ PYBIND_REGISTER(RandomApplyOperation, 1, ([](const py::module *m) {
})); }));
})); }));


PYBIND_REGISTER(
SliceOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::SliceOperation, TensorOperation, std::shared_ptr<transforms::SliceOperation>>(
*m, "SliceOperation")
.def(py::init([](std::vector<SliceOption> slice_input) {
auto slice = std::make_shared<transforms::SliceOperation>(slice_input);
THROW_IF_ERROR(slice->ValidateParams());
return slice;
}));
}));

PYBIND_REGISTER(SliceOption, 0, ([](const py::module *m) {
(void)py::class_<SliceOption>(*m, "SliceOption")
.def(py::init([](const py::slice &py_slice) {
Slice c_slice;
if (!py_slice.attr("start").is_none() && !py_slice.attr("stop").is_none() &&
!py_slice.attr("step").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("start")),
py::reinterpret_borrow<py::int_>(py_slice.attr("stop")),
py::reinterpret_borrow<py::int_>(py_slice.attr("step")));
} else if (py_slice.attr("start").is_none() && py_slice.attr("step").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("stop")));
} else if (!py_slice.attr("start").is_none() && !py_slice.attr("stop").is_none()) {
c_slice = Slice(py::reinterpret_borrow<py::int_>(py_slice.attr("start")),
py::reinterpret_borrow<py::int_>(py_slice.attr("stop")));
}

if (!c_slice.valid()) {
THROW_IF_ERROR(
Status(StatusCode::kMDUnexpectedError, __LINE__, __FILE__, "Wrong slice object"));
}
return SliceOption(c_slice);
}))
.def(py::init([](const py::list &py_list) {
std::vector<dsize_t> indices;
for (auto l : py_list) {
indices.push_back(py::reinterpret_borrow<py::int_>(l));
}
return SliceOption(indices);
}))
.def(py::init<bool>())
.def(py::init<SliceOption>());
}));

PYBIND_REGISTER( PYBIND_REGISTER(
TypeCastOperation, 1, ([](const py::module *m) { TypeCastOperation, 1, ([](const py::module *m) {
(void)py::class_<transforms::TypeCastOperation, TensorOperation, std::shared_ptr<transforms::TypeCastOperation>>( (void)py::class_<transforms::TypeCastOperation, TensorOperation, std::shared_ptr<transforms::TypeCastOperation>>(
@@ -132,5 +209,16 @@ PYBIND_REGISTER(
})); }));
})); }));


PYBIND_REGISTER(RelationalOp, 0, ([](const py::module *m) {
(void)py::enum_<RelationalOp>(*m, "RelationalOp", py::arithmetic())
.value("EQ", RelationalOp::kEqual)
.value("NE", RelationalOp::kNotEqual)
.value("LT", RelationalOp::kLess)
.value("LE", RelationalOp::kLessEqual)
.value("GT", RelationalOp::kGreater)
.value("GE", RelationalOp::kGreaterEqual)
.export_values();
}));

} // namespace dataset } // namespace dataset
} // namespace mindspore } // namespace mindspore

+ 73
- 0
mindspore/ccsrc/minddata/dataset/api/transforms.cc View File

@@ -18,6 +18,7 @@


#include <algorithm> #include <algorithm>


#include "mindspore/ccsrc/minddata/dataset/core/type_id.h"
#include "minddata/dataset/kernels/ir/data/transforms_ir.h" #include "minddata/dataset/kernels/ir/data/transforms_ir.h"


namespace mindspore { namespace mindspore {
@@ -56,11 +57,52 @@ Compose::Compose(const std::vector<std::reference_wrapper<TensorTransform>> &tra


std::shared_ptr<TensorOperation> Compose::Parse() { return std::make_shared<ComposeOperation>(data_->transforms_); } std::shared_ptr<TensorOperation> Compose::Parse() { return std::make_shared<ComposeOperation>(data_->transforms_); }


#ifndef ENABLE_ANDROID
// Constructor to Concatenate
struct Concatenate::Data {
explicit Data(int8_t axis, MSTensor prepend, MSTensor append) : axis_(axis), prepend_(prepend), append_(append) {}
int8_t axis_;
MSTensor prepend_;
MSTensor append_;
};

Concatenate::Concatenate(int8_t axis, MSTensor prepend, MSTensor append)
: data_(std::make_shared<Data>(axis, prepend, append)) {}

std::shared_ptr<TensorOperation> Concatenate::Parse() {
std::shared_ptr<Tensor> out_prepend, out_append;
Tensor::CreateFromMSTensor(data_->prepend_, &out_prepend);
Tensor::CreateFromMSTensor(data_->append_, &out_append);
return std::make_shared<ConcatenateOperation>(data_->axis_, out_prepend, out_append);
}
#endif // not ENABLE_ANDROID

// Constructor to Duplicate // Constructor to Duplicate
Duplicate::Duplicate() {} Duplicate::Duplicate() {}


std::shared_ptr<TensorOperation> Duplicate::Parse() { return std::make_shared<DuplicateOperation>(); } std::shared_ptr<TensorOperation> Duplicate::Parse() { return std::make_shared<DuplicateOperation>(); }


#ifndef ENABLE_ANDROID
// Constructor to Mask
struct Mask::Data {
explicit Data(RelationalOp op, MSTensor constant, mindspore::DataType ms_type)
: op_(op), constant_(constant), ms_type_(ms_type) {}
RelationalOp op_;
MSTensor constant_;
mindspore::DataType ms_type_;
};

Mask::Mask(RelationalOp op, MSTensor constant, mindspore::DataType ms_type)
: data_(std::make_shared<Data>(op, constant, ms_type)) {}

std::shared_ptr<TensorOperation> Mask::Parse() {
std::shared_ptr<Tensor> out_constant;
Tensor::CreateFromMSTensor(data_->constant_, &out_constant);
DataType de_type = dataset::MSTypeToDEType(static_cast<TypeId>(data_->ms_type_));
return std::make_shared<MaskOperation>(data_->op_, out_constant, de_type);
}
#endif // not ENABLE_ANDROID

// Constructor to OneHot // Constructor to OneHot
struct OneHot::Data { struct OneHot::Data {
explicit Data(int32_t num_classes) : num_classes_(num_classes) {} explicit Data(int32_t num_classes) : num_classes_(num_classes) {}
@@ -71,6 +113,25 @@ OneHot::OneHot(int32_t num_classes) : data_(std::make_shared<Data>(num_classes))


std::shared_ptr<TensorOperation> OneHot::Parse() { return std::make_shared<OneHotOperation>(data_->num_classes_); } std::shared_ptr<TensorOperation> OneHot::Parse() { return std::make_shared<OneHotOperation>(data_->num_classes_); }


#ifndef ENABLE_ANDROID
// Constructor to PadEnd
struct PadEnd::Data {
explicit Data(const std::vector<dsize_t> &pad_shape, MSTensor pad_value)
: pad_shape_(pad_shape), pad_value_(pad_value) {}
std::vector<dsize_t> pad_shape_;
MSTensor pad_value_;
};

PadEnd::PadEnd(const std::vector<dsize_t> &pad_shape, MSTensor pad_value)
: data_(std::make_shared<Data>(pad_shape, pad_value)) {}

std::shared_ptr<TensorOperation> PadEnd::Parse() {
std::shared_ptr<Tensor> pad_value;
Tensor::CreateFromMSTensor(data_->pad_value_, &pad_value);
return std::make_shared<PadEndOperation>(TensorShape(data_->pad_shape_), pad_value);
}
#endif // not ENABLE_ANDROID

// Constructor to RandomApply. // Constructor to RandomApply.
struct RandomApply::Data { struct RandomApply::Data {
std::vector<std::shared_ptr<TensorOperation>> transforms_; std::vector<std::shared_ptr<TensorOperation>> transforms_;
@@ -136,6 +197,18 @@ std::shared_ptr<TensorOperation> RandomChoice::Parse() {
return std::make_shared<RandomChoiceOperation>(data_->transforms_); return std::make_shared<RandomChoiceOperation>(data_->transforms_);
} }


#ifndef ENABLE_ANDROID
// Constructor to Slice
struct Slice::Data {
explicit Data(const std::vector<SliceOption> &slice_input) : slice_input_(slice_input) {}
std::vector<SliceOption> slice_input_;
};

Slice::Slice(const std::vector<SliceOption> &slice_input) : data_(std::make_shared<Data>(slice_input)) {}

std::shared_ptr<TensorOperation> Slice::Parse() { return std::make_shared<SliceOperation>(data_->slice_input_); }
#endif // not ENABLE_ANDROID

// Constructor to TypeCast // Constructor to TypeCast
struct TypeCast::Data { struct TypeCast::Data {
explicit Data(const std::vector<char> &data_type) : data_type_(CharToString(data_type)) {} explicit Data(const std::vector<char> &data_type) : data_type_(CharToString(data_type)) {}


+ 1
- 33
mindspore/ccsrc/minddata/dataset/core/tensor_helpers.h View File

@@ -19,43 +19,11 @@
#include <memory> #include <memory>
#include <vector> #include <vector>


#include "mindspore/ccsrc/minddata/dataset/include/transforms.h"
#include "minddata/dataset/include/constants.h" #include "minddata/dataset/include/constants.h"


namespace mindspore { namespace mindspore {
namespace dataset { namespace dataset {
class Slice {
public:
Slice() : start_(0), stop_(0), step_(0) {}
Slice(dsize_t start, dsize_t stop, dsize_t step) : start_(start), stop_(stop), step_(step) {}
Slice(dsize_t start, dsize_t stop) : start_(start), stop_(stop), step_(1) {}
explicit Slice(dsize_t stop) : start_(0), stop_(stop), step_(1) {}
Slice(Slice const &slice) = default;

~Slice() = default;

bool valid() const { return step_ != 0; }
dsize_t start_;
dsize_t stop_;
dsize_t step_;
};

class SliceOption {
public:
explicit SliceOption(bool all) : all_(all) {}
explicit SliceOption(std::vector<dsize_t> indices) : indices_(indices) {}
explicit SliceOption(Slice slice) : slice_(slice) {}
SliceOption(SliceOption const &slice) = default;

~SliceOption() = default;

// only one of the following will be valid
// given indices to slice the Tensor.
std::vector<dsize_t> indices_ = {};
// Slice object. All start, stop and step are 0 if invalid.
Slice slice_;
bool all_ = false;
};

/// Recursive helper function to generate indices based on vector of SliceOptions. It recursively iterates through each /// Recursive helper function to generate indices based on vector of SliceOptions. It recursively iterates through each
/// range represented by slice_options to generate a list of indices to be sliced. /// range represented by slice_options to generate a list of indices to be sliced.
/// \param[out] matrix Generated nested vector of indices /// \param[out] matrix Generated nested vector of indices


+ 10
- 0
mindspore/ccsrc/minddata/dataset/include/constants.h View File

@@ -71,6 +71,16 @@ enum class NormalizeForm {
kNfkd, kNfkd,
}; };


// Possible values for Mask
enum class RelationalOp {
kEqual = 0, // ==
kNotEqual, // !=
kLess, // <
kLessEqual, // <=
kGreater, // >
kGreaterEqual, // >=
};

// Possible values for SamplingStrategy // Possible values for SamplingStrategy
enum class SamplingStrategy { kRandom = 0, kEdgeWeight = 1 }; enum class SamplingStrategy { kRandom = 0, kEdgeWeight = 1 };




+ 144
- 0
mindspore/ccsrc/minddata/dataset/include/transforms.h View File

@@ -75,6 +75,54 @@ class TensorTransform : public std::enable_shared_from_this<TensorTransform> {
virtual std::shared_ptr<TensorOperation> Parse(const MapTargetDevice &env) { return nullptr; } virtual std::shared_ptr<TensorOperation> Parse(const MapTargetDevice &env) { return nullptr; }
}; };


/// \brief Slice object used in SliceOption.
class Slice {
public:
/// \brief Constructor, with start, stop and step default to 0.
Slice() : start_(0), stop_(0), step_(0) {}
/// \brief Constructor.
/// \param[in] start Starting integer specifying where to start the slicing.
/// \param[in] stop Ending integer specifying where to stop the slicing.
/// \param[in] step An integer specifying the step of the slicing.
Slice(dsize_t start, dsize_t stop, dsize_t step) : start_(start), stop_(stop), step_(step) {}
/// \brief Constructor, with step=1
/// \param[in] start Starting integer specifying where to start the slicing.
/// \param[in] stop Ending integer specifying where to stop the slicing.
Slice(dsize_t start, dsize_t stop) : start_(start), stop_(stop), step_(1) {}
/// \brief Constructor, with start=0 and step=1
/// \param[in] stop Ending integer specifying where to stop the slicing.
explicit Slice(dsize_t stop) : start_(0), stop_(stop), step_(1) {}
Slice(Slice const &slice) = default;

~Slice() = default;

bool valid() const { return step_ != 0; }
dsize_t start_;
dsize_t stop_;
dsize_t step_;
};

/// \brief SliceOption used in Slice Op.
class SliceOption {
public:
/// \param[in] all Slice the whole dimension
explicit SliceOption(bool all) : all_(all) {}
/// \param[in] indices Slice these indices along the dimension. Negative indices are supported.
explicit SliceOption(std::vector<dsize_t> indices) : indices_(indices) {}
/// \param[in] slice Slice the generated indices from the slice object along the dimension.
explicit SliceOption(Slice slice) : slice_(slice) {}
SliceOption(SliceOption const &slice) = default;

~SliceOption() = default;

// only one of the following will be valid
// given indices to slice the Tensor.
std::vector<dsize_t> indices_ = {};
// Slice object. All start, stop and step are 0 if invalid.
Slice slice_;
bool all_ = false;
};

// Transform operations for performing data transformation. // Transform operations for performing data transformation.
namespace transforms { namespace transforms {


@@ -105,6 +153,29 @@ class Compose final : public TensorTransform {
std::shared_ptr<Data> data_; std::shared_ptr<Data> data_;
}; };


/// \brief Concatenate Op.
/// \notes Tensor operation that concatenates all columns into a single tensor.
class Concatenate final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] axis Concatenate the tensors along given axis (Default=0).
/// \param[in] prepend MSTensor to be prepended to the already concatenated tensors (Default={}).
/// \param[in] append MSTensor to be appended to the already concatenated tensors (Default={}).
explicit Concatenate(int8_t axis = 0, MSTensor prepend = {}, MSTensor append = {});

/// \brief Destructor
~Concatenate() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief Duplicate Op. /// \brief Duplicate Op.
/// \notes Duplicate the input tensor to a new output tensor. /// \notes Duplicate the input tensor to a new output tensor.
/// The input tensor is carried over to the output list. /// The input tensor is carried over to the output list.
@@ -122,6 +193,32 @@ class Duplicate final : public TensorTransform {
std::shared_ptr<TensorOperation> Parse() override; std::shared_ptr<TensorOperation> Parse() override;
}; };


/// \brief Mask Op.
/// \notes Mask content of the input tensor with the given predicate.
/// Any element of the tensor that matches the predicate will be evaluated to True, otherwise False.
class Mask final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] op One of the relational operators EQ, NE LT, GT, LE or GE.
/// \param[in] constant Constant to be compared to.
/// Can only be MSTensor of str, int, float, bool.
/// \param[in] de_type Type of the generated mask (Default to be mindspore::DataType::kNumberTypeBool).
explicit Mask(RelationalOp op, MSTensor constant,
mindspore::DataType ms_type = mindspore::DataType(mindspore::DataType::kNumberTypeBool));

/// \brief Destructor
~Mask() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief OneHot Op. /// \brief OneHot Op.
/// \notes Convert the labels into OneHot format. /// \notes Convert the labels into OneHot format.
class OneHot final : public TensorTransform { class OneHot final : public TensorTransform {
@@ -143,6 +240,30 @@ class OneHot final : public TensorTransform {
std::shared_ptr<Data> data_; std::shared_ptr<Data> data_;
}; };


/// \brief PadEnd Op.
/// \notes Pad input tensor according to pad_shape, need to have same rank.
class PadEnd final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] pad_shape List of integers representing the shape needed.
/// Dimensions that set to `None` will not be padded (i.e., original dim will be used).
/// Shorter dimensions will truncate the values.
/// \param[in] pad_value Value used to pad. Default to be {}.
explicit PadEnd(const std::vector<dsize_t> &pad_shape, MSTensor pad_value = {});

/// \brief Destructor
~PadEnd() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief RandomApply Op. /// \brief RandomApply Op.
/// \notes Randomly perform a series of transforms with a given probability. /// \notes Randomly perform a series of transforms with a given probability.
class RandomApply final : public TensorTransform { class RandomApply final : public TensorTransform {
@@ -200,6 +321,29 @@ class RandomChoice final : public TensorTransform {
std::shared_ptr<Data> data_; std::shared_ptr<Data> data_;
}; };


/// \brief Slice Op.
/// \notes Slice operation to extract a tensor out using the given n slices.
/// The functionality of Slice is similar to NumPy's indexing feature.
/// (Currently only rank-1 tensors are supported).
class Slice final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] slice_input Vector of SliceOption
explicit Slice(const std::vector<SliceOption> &slice_input);

/// \brief Destructor
~Slice() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief TypeCast Op. /// \brief TypeCast Op.
/// \notes Tensor operation to cast to a given MindSpore data type. /// \notes Tensor operation to cast to a given MindSpore data type.
class TypeCast final : public TensorTransform { class TypeCast final : public TensorTransform {


+ 0
- 9
mindspore/ccsrc/minddata/dataset/kernels/data/data_utils.h View File

@@ -124,15 +124,6 @@ Status PadEndStringHelper(const std::shared_ptr<Tensor> &src, std::vector<std::s
const TensorShape &dst_shape, std::vector<dsize_t> cur_ind, size_t cur_dim, const TensorShape &dst_shape, std::vector<dsize_t> cur_ind, size_t cur_dim,
const std::string &pad_value); const std::string &pad_value);


enum class RelationalOp {
kEqual = 0, // ==
kNotEqual, // !=
kLess, // <
kLessEqual, // <=
kGreater, // >
kGreaterEqual, // >=
};

/// Helper method that masks the input tensor /// Helper method that masks the input tensor
/// @tparam T type of the tensor /// @tparam T type of the tensor
/// @param input[in] input tensor /// @param input[in] input tensor


+ 75
- 0
mindspore/ccsrc/minddata/dataset/kernels/ir/data/transforms_ir.cc View File

@@ -20,10 +20,22 @@


// Kernel data headers (in alphabetical order) // Kernel data headers (in alphabetical order)
#include "minddata/dataset/kernels/data/compose_op.h" #include "minddata/dataset/kernels/data/compose_op.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/data/concatenate_op.h"
#endif
#include "minddata/dataset/kernels/data/duplicate_op.h" #include "minddata/dataset/kernels/data/duplicate_op.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/data/mask_op.h"
#endif
#include "minddata/dataset/kernels/data/one_hot_op.h" #include "minddata/dataset/kernels/data/one_hot_op.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/data/pad_end_op.h"
#endif
#include "minddata/dataset/kernels/data/random_apply_op.h" #include "minddata/dataset/kernels/data/random_apply_op.h"
#include "minddata/dataset/kernels/data/random_choice_op.h" #include "minddata/dataset/kernels/data/random_choice_op.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/data/slice_op.h"
#endif
#include "minddata/dataset/kernels/data/type_cast_op.h" #include "minddata/dataset/kernels/data/type_cast_op.h"
#ifndef ENABLE_ANDROID #ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/data/unique_op.h" #include "minddata/dataset/kernels/data/unique_op.h"
@@ -58,11 +70,55 @@ std::shared_ptr<TensorOp> ComposeOperation::Build() {
return std::make_shared<ComposeOp>(tensor_ops); return std::make_shared<ComposeOp>(tensor_ops);
} }


#ifndef ENABLE_ANDROID
// ConcatenateOperation
ConcatenateOperation::ConcatenateOperation(int8_t axis, const std::shared_ptr<Tensor> &prepend,
const std::shared_ptr<Tensor> &append)
: axis_(axis), prepend_(prepend), append_(append) {}

Status ConcatenateOperation::ValidateParams() {
if (axis_ != 0 && axis_ != -1) {
std::string err_msg = "Concatenate: Only 1D concatenation supported.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (prepend_) {
if (prepend_->shape().Size() != 1) {
std::string err_msg = "Concatenate: Can only prepend 1D arrays.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
if (append_) {
if (append_->shape().Size() != 1) {
std::string err_msg = "Concatenate: Can only append 1D arrays.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
return Status::OK();
}

std::shared_ptr<TensorOp> ConcatenateOperation::Build() {
return std::make_shared<ConcatenateOp>(axis_, prepend_, append_);
}
#endif

// DuplicateOperation // DuplicateOperation
Status DuplicateOperation::ValidateParams() { return Status::OK(); } Status DuplicateOperation::ValidateParams() { return Status::OK(); }


std::shared_ptr<TensorOp> DuplicateOperation::Build() { return std::make_shared<DuplicateOp>(); } std::shared_ptr<TensorOp> DuplicateOperation::Build() { return std::make_shared<DuplicateOp>(); }


#ifndef ENABLE_ANDROID
// MaskOperation
MaskOperation::MaskOperation(RelationalOp op, const std::shared_ptr<Tensor> &constant, DataType dtype)
: op_(op), constant_(constant), dtype_(dtype) {}

Status MaskOperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> MaskOperation::Build() { return std::make_shared<MaskOp>(op_, constant_, dtype_); }
#endif

// OneHotOperation // OneHotOperation
OneHotOperation::OneHotOperation(int32_t num_classes) : num_classes_(num_classes) {} OneHotOperation::OneHotOperation(int32_t num_classes) : num_classes_(num_classes) {}


@@ -85,6 +141,16 @@ Status OneHotOperation::to_json(nlohmann::json *out_json) {
return Status::OK(); return Status::OK();
} }


#ifndef ENABLE_ANDROID
// PadEndOperation
PadEndOperation::PadEndOperation(const TensorShape &pad_shape, const std::shared_ptr<Tensor> &pad_value)
: pad_shape_(pad_shape), pad_value_(pad_value) {}

Status PadEndOperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> PadEndOperation::Build() { return std::make_shared<PadEndOp>(pad_shape_, pad_value_); }
#endif

// PreBuiltOperation // PreBuiltOperation
PreBuiltOperation::PreBuiltOperation(std::shared_ptr<TensorOp> tensor_op) : op_(tensor_op) { PreBuiltOperation::PreBuiltOperation(std::shared_ptr<TensorOp> tensor_op) : op_(tensor_op) {
#ifdef ENABLE_PYTHON #ifdef ENABLE_PYTHON
@@ -137,6 +203,15 @@ std::shared_ptr<TensorOp> RandomChoiceOperation::Build() {
return std::make_shared<RandomChoiceOp>(tensor_ops); return std::make_shared<RandomChoiceOp>(tensor_ops);
} }


#ifndef ENABLE_ANDROID
// SliceOperation
SliceOperation::SliceOperation(const std::vector<SliceOption> &slice_input) : slice_input_(slice_input) {}

Status SliceOperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> SliceOperation::Build() { return std::make_shared<SliceOp>(slice_input_); }
#endif

// TypeCastOperation // TypeCastOperation
TypeCastOperation::TypeCastOperation(std::string data_type) : data_type_(data_type) {} TypeCastOperation::TypeCastOperation(std::string data_type) : data_type_(data_type) {}




+ 75
- 0
mindspore/ccsrc/minddata/dataset/kernels/ir/data/transforms_ir.h View File

@@ -28,9 +28,13 @@ namespace mindspore {
namespace dataset { namespace dataset {
// Char arrays storing name of corresponding classes (in alphabetical order) // Char arrays storing name of corresponding classes (in alphabetical order)
constexpr char kComposeOperation[] = "Compose"; constexpr char kComposeOperation[] = "Compose";
constexpr char kConcatenateOperation[] = "Concatenate";
constexpr char kDuplicateOperation[] = "Duplicate"; constexpr char kDuplicateOperation[] = "Duplicate";
constexpr char kMaskOperation[] = "Mask";
constexpr char kOneHotOperation[] = "OneHot"; constexpr char kOneHotOperation[] = "OneHot";
constexpr char kPadEndOperation[] = "PadEnd";
constexpr char kPreBuiltOperation[] = "PreBuilt"; constexpr char kPreBuiltOperation[] = "PreBuilt";
constexpr char kSliceOperation[] = "Slice";
constexpr char kRandomApplyOperation[] = "RandomApply"; constexpr char kRandomApplyOperation[] = "RandomApply";
constexpr char kRandomChoiceOperation[] = "RandomChoice"; constexpr char kRandomChoiceOperation[] = "RandomChoice";
constexpr char kTypeCastOperation[] = "TypeCast"; constexpr char kTypeCastOperation[] = "TypeCast";
@@ -56,6 +60,25 @@ class ComposeOperation : public TensorOperation {
std::vector<std::shared_ptr<TensorOperation>> transforms_; std::vector<std::shared_ptr<TensorOperation>> transforms_;
}; };


class ConcatenateOperation : public TensorOperation {
public:
explicit ConcatenateOperation(int8_t axis, const std::shared_ptr<Tensor> &prepend,
const std::shared_ptr<Tensor> &append);

~ConcatenateOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kConcatenateOperation; }

private:
int8_t axis_;
std::shared_ptr<Tensor> prepend_;
std::shared_ptr<Tensor> append_;
};

class DuplicateOperation : public TensorOperation { class DuplicateOperation : public TensorOperation {
public: public:
DuplicateOperation() = default; DuplicateOperation() = default;
@@ -69,6 +92,24 @@ class DuplicateOperation : public TensorOperation {
std::string Name() const override { return kDuplicateOperation; } std::string Name() const override { return kDuplicateOperation; }
}; };


class MaskOperation : public TensorOperation {
public:
explicit MaskOperation(RelationalOp op, const std::shared_ptr<Tensor> &constant, DataType dtype);

~MaskOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kMaskOperation; }

private:
RelationalOp op_;
std::shared_ptr<Tensor> constant_;
DataType dtype_;
};

class OneHotOperation : public TensorOperation { class OneHotOperation : public TensorOperation {
public: public:
explicit OneHotOperation(int32_t num_classes); explicit OneHotOperation(int32_t num_classes);
@@ -87,6 +128,23 @@ class OneHotOperation : public TensorOperation {
int32_t num_classes_; int32_t num_classes_;
}; };


class PadEndOperation : public TensorOperation {
public:
explicit PadEndOperation(const TensorShape &pad_shape, const std::shared_ptr<Tensor> &pad_value);

~PadEndOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kPadEndOperation; }

private:
TensorShape pad_shape_;
std::shared_ptr<Tensor> pad_value_;
};

class PreBuiltOperation : public TensorOperation { class PreBuiltOperation : public TensorOperation {
public: public:
explicit PreBuiltOperation(std::shared_ptr<TensorOp> tensor_op); explicit PreBuiltOperation(std::shared_ptr<TensorOp> tensor_op);
@@ -137,6 +195,23 @@ class RandomChoiceOperation : public TensorOperation {
private: private:
std::vector<std::shared_ptr<TensorOperation>> transforms_; std::vector<std::shared_ptr<TensorOperation>> transforms_;
}; };

class SliceOperation : public TensorOperation {
public:
explicit SliceOperation(const std::vector<SliceOption> &slice_input);

~SliceOperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kSliceOperation; }

private:
std::vector<SliceOption> slice_input_;
};

class TypeCastOperation : public TensorOperation { class TypeCastOperation : public TensorOperation {
public: public:
explicit TypeCastOperation(std::string data_type); explicit TypeCastOperation(std::string data_type);


+ 25
- 16
mindspore/dataset/transforms/c_transforms.py View File

@@ -160,7 +160,7 @@ class _SliceOption(cde.SliceOption):
super().__init__(slice_option) super().__init__(slice_option)




class Slice(cde.SliceOp):
class Slice():
""" """
Slice operation to extract a tensor out using the given n slices. Slice operation to extract a tensor out using the given n slices.


@@ -200,7 +200,10 @@ class Slice(cde.SliceOp):
def __init__(self, *slices): def __init__(self, *slices):
slice_input_ = list(slices) slice_input_ = list(slices)
slice_input_ = [_SliceOption(slice_dim) for slice_dim in slice_input_] slice_input_ = [_SliceOption(slice_dim) for slice_dim in slice_input_]
super().__init__(slice_input_)
self.slice_input_ = slice_input_

def parse(self):
return cde.SliceOperation(self.slice_input_)




class Relational(IntEnum): class Relational(IntEnum):
@@ -220,7 +223,7 @@ DE_C_RELATIONAL = {Relational.EQ: cde.RelationalOp.EQ,
Relational.LE: cde.RelationalOp.LE} Relational.LE: cde.RelationalOp.LE}




class Mask(cde.MaskOp):
class Mask():
""" """
Mask content of the input tensor with the given predicate. Mask content of the input tensor with the given predicate.
Any element of the tensor that matches the predicate will be evaluated to True, otherwise False. Any element of the tensor that matches the predicate will be evaluated to True, otherwise False.
@@ -250,12 +253,15 @@ class Mask(cde.MaskOp):


@check_mask_op @check_mask_op
def __init__(self, operator, constant, dtype=mstype.bool_): def __init__(self, operator, constant, dtype=mstype.bool_):
dtype = mstype_to_detype(dtype)
constant = cde.Tensor(np.array(constant))
super().__init__(DE_C_RELATIONAL[operator], constant, dtype)
self.operator = operator
self.dtype = mstype_to_detype(dtype)
self.constant = cde.Tensor(np.array(constant))

def parse(self):
return cde.MaskOperation(DE_C_RELATIONAL[self.operator], self.constant, self.dtype)




class PadEnd(cde.PadEndOp):
class PadEnd():
""" """
Pad input tensor according to pad_shape, need to have same rank. Pad input tensor according to pad_shape, need to have same rank.


@@ -284,12 +290,14 @@ class PadEnd(cde.PadEndOp):


@check_pad_end @check_pad_end
def __init__(self, pad_shape, pad_value=None): def __init__(self, pad_shape, pad_value=None):
if pad_value is not None:
pad_value = cde.Tensor(np.array(pad_value))
super().__init__(cde.TensorShape(pad_shape), pad_value)
self.pad_shape = cde.TensorShape(pad_shape)
self.pad_value = cde.Tensor(np.array(pad_value)) if pad_value is not None else pad_value

def parse(self):
return cde.PadEndOperation(self.pad_shape, self.pad_value)




class Concatenate(cde.ConcatenateOp):
class Concatenate():
""" """
Tensor operation that concatenates all columns into a single tensor. Tensor operation that concatenates all columns into a single tensor.


@@ -311,11 +319,12 @@ class Concatenate(cde.ConcatenateOp):


@check_concat_type @check_concat_type
def __init__(self, axis=0, prepend=None, append=None): def __init__(self, axis=0, prepend=None, append=None):
if prepend is not None:
prepend = cde.Tensor(np.array(prepend))
if append is not None:
append = cde.Tensor(np.array(append))
super().__init__(axis, prepend, append)
self.axis = axis
self.prepend = cde.Tensor(np.array(prepend)) if prepend is not None else prepend
self.append = cde.Tensor(np.array(append)) if append is not None else append

def parse(self):
return cde.ConcatenateOperation(self.axis, self.prepend, self.append)




class Duplicate(TensorOperation): class Duplicate(TensorOperation):


+ 233
- 0
tests/ut/cpp/dataset/c_api_transforms_test.cc View File

@@ -137,6 +137,70 @@ TEST_F(MindDataTestPipeline, TestComposeFail3) {
EXPECT_EQ(iter, nullptr); EXPECT_EQ(iter, nullptr);
} }


TEST_F(MindDataTestPipeline, TestConcatenateSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestConcatenateSuccess.";

// Create a RandomDataset
u_int32_t curr_seed = GlobalContext::config_manager()->seed();
GlobalContext::config_manager()->set_seed(246);
std::shared_ptr<SchemaObj> schema = Schema();
schema->add_column("col1", mindspore::DataType::kNumberTypeInt16, {1});
std::shared_ptr<Dataset> ds = RandomData(4, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(2);
EXPECT_NE(ds, nullptr);

// Create Concatenate op
std::vector<std::int16_t> prepend_vector = {1, 2};
std::shared_ptr<Tensor> prepend_tensor;
ASSERT_OK(Tensor::CreateFromVector(prepend_vector, &prepend_tensor));
mindspore::MSTensor prepend_MSTensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(prepend_tensor));

std::vector<std::int16_t> append_vector = {3};
std::shared_ptr<Tensor> append_tensor;
ASSERT_OK(Tensor::CreateFromVector(append_vector, &append_tensor));
mindspore::MSTensor append_MSTensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(append_tensor));

transforms::Concatenate concatenate = transforms::Concatenate(0, prepend_MSTensor, append_MSTensor);

// Create a Map operation on ds
ds = ds->Map({concatenate}, {"col1"});
EXPECT_NE(ds, nullptr);

// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);

// Iterate the dataset and get each row
std::unordered_map<std::string, mindspore::MSTensor> row;
iter->GetNextRow(&row);

std::vector<std::vector<std::int16_t>> expected = {
{1, 2, 31354, 3}, {1, 2, -5655, 3}, {1, 2, -17734, 3}, {1, 2, -17220, 3}};

// Check concatnate results
uint64_t i = 0;
while (row.size() != 0) {
auto ind = row["col1"];
std::shared_ptr<Tensor> de_expected_tensor;
ASSERT_OK(Tensor::CreateFromVector(expected[i], &de_expected_tensor));
mindspore::MSTensor expected_tensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_expected_tensor));
EXPECT_MSTENSOR_EQ(ind, expected_tensor);
iter->GetNextRow(&row);
i++;
}

EXPECT_EQ(i, 4);

// Manually terminate the pipeline
iter->Stop();
GlobalContext::config_manager()->set_seed(curr_seed);
}

TEST_F(MindDataTestPipeline, TestDuplicateSuccess) { TEST_F(MindDataTestPipeline, TestDuplicateSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestDuplicateSuccess."; MS_LOG(INFO) << "Doing MindDataTestPipeline-TestDuplicateSuccess.";


@@ -177,6 +241,59 @@ TEST_F(MindDataTestPipeline, TestDuplicateSuccess) {
iter->Stop(); iter->Stop();
} }


TEST_F(MindDataTestPipeline, TestMaskSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestMaskSuccess.";

// Create a RandomDataset
u_int32_t curr_seed = GlobalContext::config_manager()->seed();
GlobalContext::config_manager()->set_seed(246);
std::shared_ptr<SchemaObj> schema = Schema();
schema->add_column("col1", mindspore::DataType::kNumberTypeInt16, {4});
std::shared_ptr<Dataset> ds = RandomData(4, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(2);
EXPECT_NE(ds, nullptr);

// Create Mask op
std::shared_ptr<Tensor> constant_tensor;
ASSERT_OK(Tensor::CreateScalar(0, &constant_tensor));
mindspore::MSTensor constant_MSTensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(constant_tensor));
transforms::Mask mask = transforms::Mask(RelationalOp::kGreater, constant_MSTensor);
ds = ds->Map({mask}, {"col1"});
EXPECT_NE(ds, nullptr);

// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);

// Iterate the dataset and get each row
std::unordered_map<std::string, mindspore::MSTensor> row;
iter->GetNextRow(&row);

std::vector<std::vector<bool>> expected = {
{true, true, true, true}, {false, false, false, false}, {false, false, false, false}, {false, false, false, false}};

uint64_t i = 0;
while (row.size() != 0) {
auto ind = row["col1"];
std::shared_ptr<Tensor> de_expected_tensor;
ASSERT_OK(Tensor::CreateFromVector(expected[i], &de_expected_tensor));
mindspore::MSTensor expected_tensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_expected_tensor));
EXPECT_MSTENSOR_EQ(ind, expected_tensor);
iter->GetNextRow(&row);
i++;
}

EXPECT_EQ(i, 4);

// Manually terminate the pipeline
iter->Stop();
GlobalContext::config_manager()->set_seed(curr_seed);
}

TEST_F(MindDataTestPipeline, TestOneHotSuccess1) { TEST_F(MindDataTestPipeline, TestOneHotSuccess1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestOneHotSuccess1."; MS_LOG(INFO) << "Doing MindDataTestPipeline-TestOneHotSuccess1.";
// Testing CutMixBatch on a batch of CHW images // Testing CutMixBatch on a batch of CHW images
@@ -330,6 +447,59 @@ TEST_F(MindDataTestPipeline, TestOneHotFail2) {
EXPECT_EQ(iter, nullptr); EXPECT_EQ(iter, nullptr);
} }


TEST_F(MindDataTestPipeline, TestPadEndSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestPadEndSuccess.";

// Create a RandomDataset
u_int32_t curr_seed = GlobalContext::config_manager()->seed();
GlobalContext::config_manager()->set_seed(246);
std::shared_ptr<SchemaObj> schema = Schema();
schema->add_column("col1", mindspore::DataType::kNumberTypeInt16, {1});
std::shared_ptr<Dataset> ds = RandomData(4, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(2);
EXPECT_NE(ds, nullptr);

// Create PadEnd op
std::shared_ptr<Tensor> pad_value;
ASSERT_OK(Tensor::CreateScalar(0, &pad_value));
mindspore::MSTensor pad_value_MSTensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(pad_value));

transforms::PadEnd pad_end = transforms::PadEnd({3}, pad_value_MSTensor);
ds = ds->Map({pad_end}, {"col1"});
EXPECT_NE(ds, nullptr);

// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);

// Iterate the dataset and get each row
std::unordered_map<std::string, mindspore::MSTensor> row;
iter->GetNextRow(&row);

std::vector<std::vector<std::int16_t>> expected = {{31354, 0, 0}, {-5655, 0, 0}, {-17734, 0, 0}, {-17220, 0, 0}};

uint64_t i = 0;
while (row.size() != 0) {
auto ind = row["col1"];
std::shared_ptr<Tensor> de_expected_tensor;
ASSERT_OK(Tensor::CreateFromVector(expected[i], &de_expected_tensor));
mindspore::MSTensor expected_tensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_expected_tensor));
EXPECT_MSTENSOR_EQ(ind, expected_tensor);
iter->GetNextRow(&row);
i++;
}

EXPECT_EQ(i, 4);

// Manually terminate the pipeline
iter->Stop();
GlobalContext::config_manager()->set_seed(curr_seed);
}

TEST_F(MindDataTestPipeline, TestRandomApplySuccess) { TEST_F(MindDataTestPipeline, TestRandomApplySuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomApplySuccess."; MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomApplySuccess.";


@@ -565,6 +735,69 @@ TEST_F(MindDataTestPipeline, TestRandomChoiceFail3) {
EXPECT_EQ(iter, nullptr); EXPECT_EQ(iter, nullptr);
} }


TEST_F(MindDataTestPipeline, TestSliceSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestSliceSuccess.";

// Create a RandomDataset
u_int32_t curr_seed = GlobalContext::config_manager()->seed();
GlobalContext::config_manager()->set_seed(246);
std::shared_ptr<SchemaObj> schema = Schema();
schema->add_column("col1", mindspore::DataType::kNumberTypeInt16, {1});
std::shared_ptr<Dataset> ds = RandomData(4, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(2);
EXPECT_NE(ds, nullptr);

// Create concatenate op
std::vector<std::int16_t> prepend_vector = {1, 2, 3};
std::shared_ptr<Tensor> prepend_tensor;
ASSERT_OK(Tensor::CreateFromVector(prepend_vector, &prepend_tensor));
mindspore::MSTensor prepend_MSTensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(prepend_tensor));

transforms::Concatenate concatenate = transforms::Concatenate(0, prepend_MSTensor);

// Create a Map operation on ds
ds = ds->Map({concatenate}, {"col1"});
EXPECT_NE(ds, nullptr);

// Apply Slice op on ds, get the first and third elements in each row.
SliceOption slice_option = SliceOption(Slice(0, 3, 2));
transforms::Slice slice = transforms::Slice({slice_option});
ds = ds->Map({slice}, {"col1"});
EXPECT_NE(ds, nullptr);

// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);

// Iterate the dataset and get each row
std::unordered_map<std::string, mindspore::MSTensor> row;
iter->GetNextRow(&row);

std::vector<std::vector<std::int16_t>> expected = {{1, 3}, {1, 3}, {1, 3}, {1, 3}};

// Check slice results
uint64_t i = 0;
while (row.size() != 0) {
auto ind = row["col1"];
std::shared_ptr<Tensor> de_expected_tensor;
ASSERT_OK(Tensor::CreateFromVector(expected[i], &de_expected_tensor));
mindspore::MSTensor expected_tensor =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_expected_tensor));
EXPECT_MSTENSOR_EQ(ind, expected_tensor);
iter->GetNextRow(&row);
i++;
}

EXPECT_EQ(i, 4);

// Manually terminate the pipeline
iter->Stop();
GlobalContext::config_manager()->set_seed(curr_seed);
}

TEST_F(MindDataTestPipeline, TestTypeCastSuccess) { TEST_F(MindDataTestPipeline, TestTypeCastSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestTypeCastSuccess."; MS_LOG(INFO) << "Doing MindDataTestPipeline-TestTypeCastSuccess.";




Loading…
Cancel
Save