1 /** 2 * Copyright 2020-2023 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_DATASET_TRANSFORMS_H_ 18 #define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_DATASET_TRANSFORMS_H_ 19 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include "include/api/dual_abi_helper.h" 26 #include "include/api/status.h" 27 #include "include/api/types.h" 28 #include "include/dataset/constants.h" 29 30 namespace mindspore { 31 namespace dataset { 32 class TensorOperation; 33 34 // We need the following two groups of forward declaration to friend the class in class TensorTransform. 35 namespace transforms { 36 class Compose; 37 class RandomApply; 38 class RandomChoice; 39 } // namespace transforms 40 41 namespace vision { 42 class BoundingBoxAugment; 43 class RandomSelectSubpolicy; 44 class UniformAugment; 45 } // namespace vision 46 47 // Abstract class to represent a tensor transform operation in the data pipeline. 48 /// \class TensorTransform transforms.h 49 /// \brief A base class to represent a tensor transform operation in the data pipeline. 50 class DATASET_API TensorTransform : public std::enable_shared_from_this<TensorTransform> { 51 friend class Dataset; 52 friend class Execute; 53 friend class transforms::Compose; 54 friend class transforms::RandomApply; 55 friend class transforms::RandomChoice; 56 friend class vision::BoundingBoxAugment; 57 friend class vision::RandomSelectSubpolicy; 58 friend class vision::UniformAugment; 59 60 public: 61 /// \brief Constructor 62 TensorTransform() = default; 63 64 /// \brief Destructor 65 virtual ~TensorTransform() = default; 66 67 protected: 68 /// \brief Pure virtual function to convert a TensorTransform class into a IR TensorOperation object. 69 /// \return shared pointer to the newly created TensorOperation. 70 virtual std::shared_ptr<TensorOperation> Parse() = 0; 71 72 /// \brief Virtual function to convert a TensorTransform class into a IR TensorOperation object. 73 /// \param[in] env A string to determine the running environment 74 /// \return shared pointer to the newly created TensorOperation. Parse(const MapTargetDevice & env)75 virtual std::shared_ptr<TensorOperation> Parse(const MapTargetDevice &env) { return nullptr; } 76 }; 77 78 /// \brief Slice object used in SliceOption. 79 class DATASET_API Slice { 80 public: 81 /// \brief Constructor, with start, stop and step default to 0. Slice()82 Slice() : start_(0), stop_(0), step_(0) {} 83 84 /// \brief Constructor. 85 /// \param[in] start Starting integer specifying where to start the slicing. 86 /// \param[in] stop Ending integer specifying where to stop the slicing. 87 /// \param[in] step An integer specifying the step of the slicing. 88 /// \par Example 89 /// \code 90 /// /* Slice dimension from 2 to 10 with step 2. */ 91 /// Slice(0, 10, 2); 92 /// \endcode Slice(dsize_t start,dsize_t stop,dsize_t step)93 Slice(dsize_t start, dsize_t stop, dsize_t step) : start_(start), stop_(stop), step_(step) {} 94 95 /// \brief Constructor, with step=1 96 /// \param[in] start Starting integer specifying where to start the slicing. 97 /// \param[in] stop Ending integer specifying where to stop the slicing. 98 /// \par Example 99 /// \code 100 /// /* Slice dimension from 5 to 10 with step 1. */ 101 /// Slice(5, 10); 102 /// \endcode Slice(dsize_t start,dsize_t stop)103 Slice(dsize_t start, dsize_t stop) : start_(start), stop_(stop), step_(1) {} 104 105 /// \brief Constructor, with start=0 and step=1 106 /// \param[in] stop Ending integer specifying where to stop the slicing. 107 /// \par Example 108 /// \code 109 /// /* Slice dimension from 0 to 5 with step 1. */ 110 /// Slice(5); 111 /// \endcode Slice(dsize_t stop)112 explicit Slice(dsize_t stop) : start_(0), stop_(stop), step_(1) {} 113 114 Slice(Slice const &slice) = default; 115 116 Slice &operator=(const Slice &slice) = default; 117 118 ~Slice() = default; 119 valid()120 bool valid() const { return step_ != 0; } 121 dsize_t start_; 122 dsize_t stop_; 123 dsize_t step_; 124 }; 125 126 /// \brief SliceOption used in Slice TensorTransform. 127 class DATASET_API SliceOption { 128 public: 129 /// \param[in] all Slice the whole dimension 130 /// \par Example 131 /// \code 132 /// /* Slice all the data. */ 133 /// SliceOption slice_option = SliceOption(True); 134 /// \endcode SliceOption(bool all)135 explicit SliceOption(bool all) : all_(all) {} 136 137 /// \param[in] indices Slice these indices along the dimension. Negative indices are supported. 138 /// \par Example 139 /// \code 140 /// /* Slice the given dimensions. */ 141 /// std::vector<int64_t> indices = {0, 3, 6, 7}; 142 /// SliceOption slice_option = SliceOption(indices); 143 /// \endcode SliceOption(const std::vector<dsize_t> & indices)144 explicit SliceOption(const std::vector<dsize_t> &indices) : indices_(indices) {} 145 146 /// \param[in] slice Slice the generated indices from the slice object along the dimension. 147 /// \par Example 148 /// \code 149 /// /* Slice dimension from 2 to 10 with step 2. */ 150 /// SliceOption slice_option = SliceOption(Slice(0, 10, 2)); 151 /// transforms::Slice slice_op = transforms::Slice({slice_option}); 152 /// \endcode SliceOption(const Slice & slice)153 explicit SliceOption(const Slice &slice) : slice_(slice) {} 154 155 SliceOption(SliceOption const &slice) = default; 156 157 SliceOption &operator=(const SliceOption &slice) = default; 158 159 ~SliceOption() = default; 160 161 // only one of the following will be valid 162 // given indices to slice the Tensor. 163 std::vector<dsize_t> indices_ = {}; 164 // Slice object. All start, stop and step are 0 if invalid. 165 Slice slice_; 166 bool all_ = false; 167 }; 168 169 // Transform operations for performing data transformation. 170 namespace transforms { 171 172 /// \brief Compose a list of transforms into a single transform. 173 class DATASET_API Compose final : public TensorTransform { 174 public: 175 /// \brief Constructor. 176 /// \param[in] transforms A vector of raw pointers to TensorTransform objects to be applied. 177 /// \par Example 178 /// \code 179 /// /* Define operations */ 180 /// auto resize_op(new vision::Resize({30, 30})); 181 /// auto center_crop_op(new vision::CenterCrop({16, 16})); 182 /// auto compose_op(new transforms::Compose({resize_op, center_crop_op})); 183 /// 184 /// /* dataset is an instance of Dataset object */ 185 /// dataset = dataset->Map({compose_op}, // operations 186 /// {"image"}); // input columns 187 /// \endcode 188 explicit Compose(const std::vector<TensorTransform *> &transforms); 189 190 /// \brief Constructor. 191 /// \param[in] transforms A vector of shared pointers to TensorTransform objects to be applied. 192 /// \par Example 193 /// \code 194 /// /* Define operations */ 195 /// std::shared_ptr<TensorTransform> resize_op(new vision::Resize({30, 30})); 196 /// std::shared_ptr<TensorTransform> center_crop_op(new vision::CenterCrop({16, 16})); 197 /// std::shared_ptr<TensorTransform> compose_op(new transforms::Compose({resize_op, center_crop_op})); 198 /// 199 /// /* dataset is an instance of Dataset object */ 200 /// dataset = dataset->Map({compose_op}, // operations 201 /// {"image"}); // input columns 202 /// \endcode 203 explicit Compose(const std::vector<std::shared_ptr<TensorTransform>> &transforms); 204 205 /// \brief Constructor. 206 /// \param[in] transforms A vector of TensorTransform objects to be applied. 207 /// \par Example 208 /// \code 209 /// /* Define operations */ 210 /// vision::Resize resize_op = vision::Resize({30, 30}); 211 /// vision::CenterCrop center_crop_op = vision::CenterCrop({16, 16}); 212 /// transforms::Compose compose_op = transforms::Compose({resize_op, center_crop_op}); 213 /// 214 /// /* dataset is an instance of Dataset object */ 215 /// dataset = dataset->Map({compose_op}, // operations 216 /// {"image"}); // input columns 217 /// \endcode 218 explicit Compose(const std::vector<std::reference_wrapper<TensorTransform>> &transforms); 219 220 /// \brief Destructor 221 ~Compose() override = default; 222 223 protected: 224 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 225 /// \return Shared pointer to TensorOperation object. 226 std::shared_ptr<TensorOperation> Parse() override; 227 228 private: 229 struct Data; 230 std::shared_ptr<Data> data_; 231 }; 232 233 /// \brief Concatenate all tensors into a single tensor. 234 class DATASET_API Concatenate final : public TensorTransform { 235 public: 236 /// \brief Constructor. 237 /// \param[in] axis Concatenate the tensors along given axis, only support 0 or -1 so far (default=0). 238 /// \param[in] prepend MSTensor to be prepended to the concatenated tensors (default={}). 239 /// \param[in] append MSTensor to be appended to the concatenated tensors (default={}). 240 /// \par Example 241 /// \code 242 /// /* Define operations */ 243 /// mindspore::MSTensor append_MSTensor; 244 /// mindspore::MSTensor prepend_MSTensor; 245 /// auto concatenate_op = transforms::Concatenate(0, append_MSTensor, prepend_MSTensor); 246 /// 247 /// /* dataset is an instance of Dataset object */ 248 /// dataset = dataset->Map({concatenate_op}, // operations 249 /// {"column"}); // input columns 250 /// \endcode 251 explicit Concatenate(int8_t axis = 0, const MSTensor &prepend = {}, const MSTensor &append = {}); 252 253 /// \brief Destructor 254 ~Concatenate() override = default; 255 256 protected: 257 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 258 /// \return Shared pointer to TensorOperation object. 259 std::shared_ptr<TensorOperation> Parse() override; 260 261 private: 262 struct Data; 263 std::shared_ptr<Data> data_; 264 }; 265 266 /// \brief Duplicate the input tensor to a new output tensor. 267 /// The input tensor is carried over to the output list. 268 class DATASET_API Duplicate final : public TensorTransform { 269 public: 270 /// \brief Constructor. 271 /// \par Example 272 /// \code 273 /// /* Define operations */ 274 /// auto duplicate_op = transforms::Duplicate(); 275 /// 276 /// /* dataset is an instance of Dataset object */ 277 /// dataset = dataset->Map({duplicate_op}, // operations 278 /// {"column"}, // input columns 279 /// {"column", "column_copy"}); // output columns 280 /// \endcode 281 Duplicate(); 282 283 /// \brief Destructor 284 ~Duplicate() override = default; 285 286 protected: 287 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 288 /// \return Shared pointer to TensorOperation object. 289 std::shared_ptr<TensorOperation> Parse() override; 290 }; 291 292 /// \brief Fill all elements in the tensor with the specified value. 293 /// The output tensor will have the same shape and type as the input tensor. 294 class DATASET_API Fill final : public TensorTransform { 295 public: 296 /// \brief Constructor. 297 /// \param[in] fill_value Scalar value to fill the tensor with. 298 /// It can only be MSTensor of the following types from mindspore::DataType: 299 /// String, Bool, Int8/16/32/64, UInt8/16/32/64, Float16/32/64. 300 /// \par Example 301 /// \code 302 /// /* Define operations */ 303 /// mindspore::MSTensor tensor; 304 /// auto fill_op = transforms::Fill(tensor); 305 /// 306 /// /* dataset is an instance of Dataset object */ 307 /// dataset = dataset->Map({fill_op}, // operations 308 /// {"column"}); // input columns 309 /// \endcode 310 explicit Fill(const MSTensor &fill_value); 311 312 /// \brief Destructor 313 ~Fill() override = default; 314 315 protected: 316 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 317 /// \return Shared pointer to TensorOperation object. 318 std::shared_ptr<TensorOperation> Parse() override; 319 320 private: 321 struct Data; 322 std::shared_ptr<Data> data_; 323 }; 324 325 /// \brief Mask content of the input tensor with the given predicate. 326 /// Any element of the tensor that matches the predicate will be evaluated to True, otherwise False. 327 class DATASET_API Mask final : public TensorTransform { 328 public: 329 /// \brief Constructor. 330 /// \param[in] op One of the relational operators: EQ, NE LT, GT, LE or GE. 331 /// \param[in] constant Constant to be compared to. It can only be MSTensor of the following types 332 /// from mindspore::DataType: String, Int, Float, Bool. 333 /// \param[in] ms_type Type of the generated mask. It can only be numeric or boolean datatype. 334 /// (default=mindspore::DataType::kNumberTypeBool) 335 /// \par Example 336 /// \code 337 /// /* Define operations */ 338 /// mindspore::MSTensor constant; 339 /// auto mask_op = transforms::Mask(RelationalOp::kEqual, constant); 340 /// 341 /// /* dataset is an instance of Dataset object */ 342 /// dataset = dataset->Map({mask_op}, // operations 343 /// {"column"}); // input columns 344 /// \endcode 345 explicit Mask(RelationalOp op, const MSTensor &constant, 346 mindspore::DataType ms_type = mindspore::DataType(mindspore::DataType::kNumberTypeBool)); 347 348 /// \brief Destructor 349 ~Mask() override = default; 350 351 protected: 352 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 353 /// \return Shared pointer to TensorOperation object. 354 std::shared_ptr<TensorOperation> Parse() override; 355 356 private: 357 struct Data; 358 std::shared_ptr<Data> data_; 359 }; 360 361 /// \brief Convert the labels into OneHot format. 362 class DATASET_API OneHot final : public TensorTransform { 363 public: 364 /// \brief Constructor. 365 /// \param[in] num_classes number of classes. 366 /// \param[in] smoothing_rate smoothing rate default(0.0). 367 /// \par Example 368 /// \code 369 /// /* Define operations */ 370 /// mindspore::MSTensor constant; 371 /// auto one_hot_op = transforms::OneHot(10); 372 /// 373 /// /* dataset is an instance of Dataset object */ 374 /// dataset = dataset->Map({one_hot_op}, // operations 375 /// {"column"}); // input columns 376 /// \endcode 377 explicit OneHot(int32_t num_classes, double smoothing_rate = 0.0); 378 379 /// \brief Destructor 380 ~OneHot() override = default; 381 382 protected: 383 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 384 /// \return Shared pointer to TensorOperation object. 385 std::shared_ptr<TensorOperation> Parse() override; 386 387 private: 388 struct Data; 389 std::shared_ptr<Data> data_; 390 }; 391 392 /// \brief Pad input tensor according to pad_shape 393 class DATASET_API PadEnd final : public TensorTransform { 394 public: 395 /// \brief Constructor. 396 /// \param[in] pad_shape List of integers representing the shape needed, need to have same rank with input tensor. 397 /// Dimensions that set to `-1` will not be padded (i.e., original dim will be used). 398 /// Shorter dimensions will truncate the values. 399 /// \param[in] pad_value Value used to pad (default={}). 400 /// \par Example 401 /// \code 402 /// /* Define operations */ 403 /// mindspore::MSTensor constant; 404 /// auto pad_end_op = transforms::PadEnd({224, 224, 1}, {constant}); 405 /// 406 /// /* dataset is an instance of Dataset object */ 407 /// dataset = dataset->Map({pad_end_op}, // operations 408 /// {"column"}); // input columns 409 /// \endcode 410 explicit PadEnd(const std::vector<dsize_t> &pad_shape, const MSTensor &pad_value = {}); 411 412 /// \brief Destructor 413 ~PadEnd() override = default; 414 415 protected: 416 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 417 /// \return Shared pointer to TensorOperation object. 418 std::shared_ptr<TensorOperation> Parse() override; 419 420 private: 421 struct Data; 422 std::shared_ptr<Data> data_; 423 }; 424 425 /// \brief Randomly perform a series of transforms with a given probability. 426 class DATASET_API RandomApply final : public TensorTransform { 427 public: 428 /// \brief Constructor. 429 /// \param[in] transforms A vector of raw pointers to TensorTransform objects to be applied. 430 /// \param[in] prob The probability to apply the transformation list (default=0.5). 431 /// \par Example 432 /// \code 433 /// /* Define operations */ 434 /// auto resize_op(new vision::Resize({30, 30})); 435 /// auto center_crop_op(new vision::CenterCrop({16, 16})); 436 /// auto random_op(new transforms::RandomApply({resize_op, center_crop_op})); 437 /// 438 /// /* dataset is an instance of Dataset object */ 439 /// dataset = dataset->Map({random_op}, // operations 440 /// {"image"}); // input columns 441 /// \endcode 442 explicit RandomApply(const std::vector<TensorTransform *> &transforms, double prob = 0.5); 443 444 /// \brief Constructor. 445 /// \param[in] transforms A vector of shared pointers to TensorTransform objects to be applied. 446 /// \param[in] prob The probability to apply the transformation list (default=0.5). 447 /// \par Example 448 /// \code 449 /// /* Define operations */ 450 /// std::shared_ptr<TensorTransform> resize_op(new vision::Resize({30, 30})); 451 /// std::shared_ptr<TensorTransform> center_crop_op(new vision::CenterCrop({16, 16})); 452 /// std::shared_ptr<TensorTransform> random_op(new transforms::RandomApply({resize_op, center_crop_op})); 453 /// 454 /// /* dataset is an instance of Dataset object */ 455 /// dataset = dataset->Map({random_op}, // operations 456 /// {"image"}); // input columns 457 /// \endcode 458 explicit RandomApply(const std::vector<std::shared_ptr<TensorTransform>> &transforms, double prob = 0.5); 459 460 /// \brief Constructor. 461 /// \param[in] transforms A vector of TensorTransform objects to be applied. 462 /// \param[in] prob The probability to apply the transformation list (default=0.5). 463 /// \par Example 464 /// \code 465 /// /* Define operations */ 466 /// vision::Resize resize_op = vision::Resize({30, 30}); 467 /// vision::CenterCrop center_crop_op = vision::CenterCrop({16, 16}); 468 /// transforms::RandomApply random_op = transforms::RandomApply({resize_op, center_crop_op}); 469 /// 470 /// /* dataset is an instance of Dataset object */ 471 /// dataset = dataset->Map({random_op}, // operations 472 /// {"image"}); // input columns 473 /// \endcode 474 explicit RandomApply(const std::vector<std::reference_wrapper<TensorTransform>> &transforms, double prob = 0.5); 475 476 /// \brief Destructor 477 ~RandomApply() override = default; 478 479 protected: 480 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 481 /// \return Shared pointer to TensorOperation object. 482 std::shared_ptr<TensorOperation> Parse() override; 483 484 private: 485 struct Data; 486 std::shared_ptr<Data> data_; 487 }; 488 489 /// \brief Randomly select one transform from a list of transforms to perform on the input tensor. 490 class DATASET_API RandomChoice final : public TensorTransform { 491 public: 492 /// \brief Constructor. 493 /// \param[in] transforms A vector of raw pointers to TensorTransform objects to be applied. 494 /// \par Example 495 /// \code 496 /// /* Define operations */ 497 /// auto resize_op(new vision::Resize({30, 30})); 498 /// auto center_crop_op(new vision::CenterCrop({16, 16})); 499 /// auto random_op(new transforms::RandomChoice({resize_op, center_crop_op})); 500 /// 501 /// /* dataset is an instance of Dataset object */ 502 /// dataset = dataset->Map({random_op}, // operations 503 /// {"image"}); // input columns 504 /// \endcode 505 explicit RandomChoice(const std::vector<TensorTransform *> &transforms); 506 507 /// \brief Constructor. 508 /// \param[in] transforms A vector of shared pointers to TensorTransform objects to be applied. 509 /// \par Example 510 /// \code 511 /// /* Define operations */ 512 /// std::shared_ptr<TensorTransform> resize_op(new vision::Resize({30, 30})); 513 /// std::shared_ptr<TensorTransform> center_crop_op(new vision::CenterCrop({16, 16})); 514 /// std::shared_ptr<TensorTransform> random_op(new transforms::RandomChoice({resize_op, center_crop_op})); 515 /// 516 /// /* dataset is an instance of Dataset object */ 517 /// dataset = dataset->Map({random_op}, // operations 518 /// {"image"}); // input columns 519 /// \endcode 520 explicit RandomChoice(const std::vector<std::shared_ptr<TensorTransform>> &transforms); 521 522 /// \brief Constructor. 523 /// \param[in] transforms A vector of TensorTransform objects to be applied. 524 /// \par Example 525 /// \code 526 /// /* Define operations */ 527 /// vision::Resize resize_op = vision::Resize({30, 30}); 528 /// vision::CenterCrop center_crop_op = vision::CenterCrop({16, 16}); 529 /// transforms::RandomChoice random_op = transforms::RandomChoice({resize_op, center_crop_op}); 530 /// 531 /// /* dataset is an instance of Dataset object */ 532 /// dataset = dataset->Map({random_op}, // operations 533 /// {"image"}); // input columns 534 /// \endcode 535 explicit RandomChoice(const std::vector<std::reference_wrapper<TensorTransform>> &transforms); 536 537 /// \brief Destructor 538 ~RandomChoice() override = default; 539 540 protected: 541 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 542 /// \return Shared pointer to TensorOperation object. 543 std::shared_ptr<TensorOperation> Parse() override; 544 545 private: 546 struct Data; 547 std::shared_ptr<Data> data_; 548 }; 549 550 /// \brief Extract a tensor out using the given n slices. 551 /// The functionality of Slice is similar to the feature of indexing of NumPy. 552 /// (Currently only rank-1 tensors are supported). 553 class DATASET_API Slice final : public TensorTransform { 554 public: 555 /// \brief Constructor. 556 /// \param[in] slice_input Vector of SliceOption. 557 /// \par Example 558 /// \code 559 /// /* Define operations */ 560 /// SliceOption slice_option = SliceOption(Slice(0, 3, 2)); 561 /// transforms::Slice slice_op = transforms::Slice({slice_option}); 562 /// 563 /// /* dataset is an instance of Dataset object */ 564 /// dataset = dataset->Map({slice_op}, // operations 565 /// {"column"}); // input columns 566 /// \endcode 567 explicit Slice(const std::vector<SliceOption> &slice_input); 568 569 /// \brief Destructor 570 ~Slice() override = default; 571 572 protected: 573 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 574 /// \return Shared pointer to TensorOperation object. 575 std::shared_ptr<TensorOperation> Parse() override; 576 577 private: 578 struct Data; 579 std::shared_ptr<Data> data_; 580 }; 581 582 /// \brief Cast the MindSpore data type of a tensor to another. 583 class DATASET_API TypeCast final : public TensorTransform { 584 public: 585 /// \brief Constructor. 586 /// \param[in] data_type mindspore::DataType to be cast to. 587 /// \par Example 588 /// \code 589 /// /* Define operations */ 590 /// auto typecast_op = transforms::TypeCast(mindspore::DataType::kNumberTypeUInt8); 591 /// 592 /// /* dataset is an instance of Dataset object */ 593 /// dataset = dataset->Map({typecast_op}, // operations 594 /// {"column"}); // input columns 595 /// \endcode 596 explicit TypeCast(mindspore::DataType data_type); 597 598 /// \brief Destructor 599 ~TypeCast() override = default; 600 601 protected: 602 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 603 /// \return Shared pointer to TensorOperation object. 604 std::shared_ptr<TensorOperation> Parse() override; 605 606 private: 607 struct Data; 608 std::shared_ptr<Data> data_; 609 }; 610 611 /// \brief Return an output tensor that contains all the unique elements of the input tensor in 612 /// the same order as they appear in the input tensor. 613 class DATASET_API Unique final : public TensorTransform { 614 public: 615 /// \brief Constructor. 616 /// \par Example 617 /// \code 618 /// /* Define operations */ 619 /// auto unique_op = transforms::Unique(); 620 /// 621 /// /* dataset is an instance of Dataset object */ 622 /// dataset = dataset->Map({unique_op}, // operations 623 /// {"column"}); // input columns 624 /// \endcode 625 Unique(); 626 627 /// \brief Destructor 628 ~Unique() override = default; 629 630 protected: 631 /// \brief The function to convert a TensorTransform object into a TensorOperation object. 632 /// \return Shared pointer to TensorOperation object. 633 std::shared_ptr<TensorOperation> Parse() override; 634 }; 635 } // namespace transforms 636 } // namespace dataset 637 } // namespace mindspore 638 #endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_DATASET_TRANSFORMS_H_ 639