You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

map_op_test.cc 28 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. /**
  2. * Copyright 2019-2021 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. #include <iostream>
  17. #include <memory>
  18. #include <vector>
  19. #include "common/common.h"
  20. #include "minddata/dataset/core/client.h"
  21. #include "minddata/dataset/core/tensor.h"
  22. #include "minddata/dataset/engine/datasetops/source/image_folder_op.h"
  23. #include "minddata/dataset/engine/datasetops/source/tf_reader_op.h"
  24. #include "minddata/dataset/engine/jagged_connector.h"
  25. #include "minddata/dataset/kernels/image/decode_op.h"
  26. #include "minddata/dataset/kernels/image/resize_op.h"
  27. #include "minddata/dataset/kernels/tensor_op.h"
  28. #include "utils/log_adapter.h"
  29. using namespace mindspore::dataset;
  30. using mindspore::LogStream;
  31. using mindspore::MsLogLevel::INFO;
  32. namespace mindspore {
  33. namespace dataset {
  34. namespace test {
  35. class NoOp : public TensorOp {
  36. public:
  37. NoOp(){};
  38. ~NoOp(){};
  39. Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override {
  40. *output = std::move(input);
  41. return Status::OK();
  42. };
  43. void Print(std::ostream &out) const override { out << "NoOp"; };
  44. std::string Name() const override { return kNoOp; }
  45. };
  46. class ThreeToOneOp : public TensorOp {
  47. public:
  48. ThreeToOneOp(){};
  49. ~ThreeToOneOp(){};
  50. uint32_t NumInput() override { return 3; }
  51. // Compute function that holds the actual implementation of the operation.
  52. Status Compute(const TensorRow &input, TensorRow *output) override {
  53. output->push_back(input[0]);
  54. return Status::OK();
  55. };
  56. void Print(std::ostream &out) const override { out << "ThreeToOneOp"; };
  57. std::string Name() const override { return "ThreeToOneOp"; }
  58. };
  59. class OneToThreeOp : public TensorOp {
  60. public:
  61. OneToThreeOp(){};
  62. ~OneToThreeOp(){};
  63. uint32_t NumOutput() override { return 3; }
  64. // Compute function that holds the actual implementation of the operation.
  65. // Simply pushing the same shared pointer of the first element of input vector three times.
  66. Status Compute(const TensorRow &input, TensorRow *output) override {
  67. output->push_back(input[0]);
  68. output->push_back(input[0]);
  69. output->push_back(input[0]);
  70. return Status::OK();
  71. };
  72. void Print(std::ostream &out) const override { out << "OneToThreeOp"; };
  73. std::string Name() const override { return "OneToThreeOp"; };
  74. };
  75. } // namespace test
  76. } // namespace dataset
  77. } // namespace mindspore
  78. class MindDataTestMapOp : public UT::DatasetOpTesting {
  79. public:
  80. void SetUp() override {
  81. DatasetOpTesting::SetUp();
  82. dataset_path_ = datasets_root_path_ + "" + "/testDataset2/testDataset2.data";
  83. schema_path_ = datasets_root_path_ + "" + "/testDataset2/datasetSchema.json";
  84. GlobalInit();
  85. // Start with an empty execution tree
  86. my_tree_ = std::make_shared<ExecutionTree>();
  87. }
  88. std::shared_ptr<TFReaderOp> CreateTFReaderOp() {
  89. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  90. auto op_connector_size = config_manager->op_connector_size();
  91. std::unique_ptr<DataSchema> schema = std::make_unique<DataSchema>();
  92. std::vector<std::string> columns_to_load = {"image", "label", "A", "B"};
  93. (void)schema->LoadSchemaFile(schema_path_, columns_to_load);
  94. std::vector<std::string> files = {dataset_path_};
  95. std::shared_ptr<TFReaderOp> my_tfreader_op = std::make_shared<TFReaderOp>(
  96. 1, 2, 0, files, std::move(schema), op_connector_size, columns_to_load, false, 1, 0, false);
  97. (void)my_tfreader_op->Init();
  98. return my_tfreader_op;
  99. }
  100. std::shared_ptr<ExecutionTree> my_tree_;
  101. private:
  102. std::string dataset_path_;
  103. std::string schema_path_;
  104. };
  105. std::shared_ptr<ImageFolderOp> ImageFolder(int64_t num_works, int64_t rows, int64_t conns, std::string path,
  106. bool shuf = false, std::shared_ptr<SamplerRT> sampler = nullptr,
  107. std::map<std::string, int32_t> map = {}, bool decode = false);
  108. // std::shared_ptr<ExecutionTree> Build(std::vector<std::shared_ptr<DatasetOp>> ops);
  109. // TestAsMap scenario:
  110. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  111. // A TensorOp that does nothing picks the "image" column and produces a column named "X".
  112. // Thus, based on the new MapOp behaviour, the column ordering will be |X|label|A|B|.
  113. // Verify that the "image" column is removed and "X" column is added.
  114. TEST_F(MindDataTestMapOp, TestAsMap) {
  115. Status rc;
  116. MS_LOG(INFO) << "Doing TestAsMap.";
  117. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  118. auto my_tfreader_op = this->CreateTFReaderOp();
  119. rc = my_tree_->AssociateNode(my_tfreader_op);
  120. EXPECT_TRUE(rc.IsOk());
  121. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  122. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  123. my_func_list.push_back(my_no_op);
  124. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  125. auto op_connector_size = config_manager->op_connector_size();
  126. std::vector<std::string> in_columns = {"image"};
  127. std::vector<std::string> out_columns = {"X"};
  128. std::shared_ptr<MapOp> my_map_op =
  129. std::make_shared<MapOp>(in_columns, out_columns, std::move(my_func_list), 1, op_connector_size);
  130. rc = my_tree_->AssociateNode(my_map_op);
  131. EXPECT_TRUE(rc.IsOk());
  132. rc = my_map_op->AddChild(my_tfreader_op);
  133. EXPECT_TRUE(rc.IsOk());
  134. // Assign the tree root
  135. rc = my_tree_->AssignRoot(my_map_op);
  136. EXPECT_TRUE(rc.IsOk());
  137. // Now prepare the tree
  138. rc = my_tree_->Prepare();
  139. EXPECT_TRUE(rc.IsOk());
  140. rc = my_tree_->Launch();
  141. EXPECT_TRUE(rc.IsOk());
  142. // Start the loop of reading tensors from our pipeline
  143. DatasetIterator di(my_tree_);
  144. TensorMap tensor_map;
  145. rc = di.GetNextAsMap(&tensor_map);
  146. EXPECT_TRUE(rc.IsOk());
  147. EXPECT_EQ(tensor_map.size(), 4);
  148. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  149. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  150. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  151. EXPECT_NE(tensor_map.find("A"), tensor_map.end());
  152. EXPECT_NE(tensor_map.find("B"), tensor_map.end());
  153. }
  154. // Test3to1 scenario:
  155. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  156. // A 3-to-1 TensorOp picks the columns [image, A, B] and produce a column named "X".
  157. // Thus, based on the new MapOp behaviour, the column ordering will be |X|label|.
  158. // Verify that the only columns "X" and "label" exist.
  159. TEST_F(MindDataTestMapOp, Test3to1) {
  160. Status rc;
  161. MS_LOG(INFO) << "Doing Test3to1.";
  162. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  163. auto my_tfreader_op = this->CreateTFReaderOp();
  164. rc = my_tree_->AssociateNode(my_tfreader_op);
  165. EXPECT_TRUE(rc.IsOk());
  166. auto my_op = std::make_shared<mindspore::dataset::test::ThreeToOneOp>();
  167. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  168. my_func_list.push_back(my_op);
  169. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  170. auto op_connector_size = config_manager->op_connector_size();
  171. std::vector<std::string> in_columns = {"image", "A", "B"};
  172. std::vector<std::string> out_columns = {"X"};
  173. std::shared_ptr<MapOp> my_map_op =
  174. std::make_shared<MapOp>(in_columns, out_columns, std::move(my_func_list), 1, op_connector_size);
  175. rc = my_tree_->AssociateNode(my_map_op);
  176. EXPECT_TRUE(rc.IsOk());
  177. rc = my_map_op->AddChild(my_tfreader_op);
  178. EXPECT_TRUE(rc.IsOk());
  179. rc = my_tree_->AssignRoot(my_map_op);
  180. EXPECT_TRUE(rc.IsOk());
  181. rc = my_tree_->Prepare();
  182. EXPECT_TRUE(rc.IsOk());
  183. rc = my_tree_->Launch();
  184. EXPECT_TRUE(rc.IsOk());
  185. // Start the loop of reading tensors from our pipeline
  186. DatasetIterator di(my_tree_);
  187. TensorMap tensor_map;
  188. rc = di.GetNextAsMap(&tensor_map);
  189. EXPECT_TRUE(rc.IsOk());
  190. while (!tensor_map.empty()) {
  191. EXPECT_EQ(tensor_map.size(), 2);
  192. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  193. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  194. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  195. EXPECT_EQ(tensor_map.find("A"), tensor_map.end());
  196. EXPECT_EQ(tensor_map.find("B"), tensor_map.end());
  197. rc = di.GetNextAsMap(&tensor_map);
  198. EXPECT_TRUE(rc.IsOk());
  199. }
  200. }
  201. // Test1to3 scenario:
  202. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  203. // A 1-to-3 TensorOp picks the columns [image] and produce a column named [X, Y, Z].
  204. // Thus, based on the new MapOp behaviour, the column ordering will be |X|Y|Z|label|A|B|.
  205. // Verify that the only columns X, Y, Z are added (to the front) and followed by columns label, A, B..
  206. TEST_F(MindDataTestMapOp, Test1to3) {
  207. Status rc;
  208. MS_LOG(INFO) << "Doing Test1to3.";
  209. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  210. auto my_tfreader_op = this->CreateTFReaderOp();
  211. rc = my_tree_->AssociateNode(my_tfreader_op);
  212. EXPECT_TRUE(rc.IsOk());
  213. auto my_op = std::make_shared<mindspore::dataset::test::OneToThreeOp>();
  214. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  215. my_func_list.push_back(my_op);
  216. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  217. auto op_connector_size = config_manager->op_connector_size();
  218. std::vector<std::string> in_columns = {"image"};
  219. std::vector<std::string> out_columns = {"X", "Y", "Z"};
  220. std::shared_ptr<MapOp> my_map_op =
  221. std::make_shared<MapOp>(in_columns, out_columns, std::move(my_func_list), 1, op_connector_size);
  222. // ProjectOp
  223. std::vector<std::string> columns_to_project = {"X", "Y", "Z", "label", "A", "B"};
  224. std::shared_ptr<ProjectOp> my_project_op = std::make_shared<ProjectOp>(columns_to_project);
  225. rc = my_tree_->AssociateNode(my_project_op);
  226. ASSERT_TRUE(rc.IsOk());
  227. rc = my_tree_->AssignRoot(my_project_op);
  228. ASSERT_TRUE(rc.IsOk());
  229. rc = my_tree_->AssociateNode(my_map_op);
  230. EXPECT_TRUE(rc.IsOk());
  231. rc = my_project_op->AddChild(my_map_op);
  232. EXPECT_TRUE(rc.IsOk());
  233. rc = my_map_op->AddChild(my_tfreader_op);
  234. EXPECT_TRUE(rc.IsOk());
  235. rc = my_tree_->Prepare();
  236. EXPECT_TRUE(rc.IsOk());
  237. rc = my_tree_->Launch();
  238. EXPECT_TRUE(rc.IsOk());
  239. // Start the loop of reading tensors from our pipeline
  240. DatasetIterator di(my_tree_);
  241. TensorMap tensor_map;
  242. rc = di.GetNextAsMap(&tensor_map);
  243. EXPECT_TRUE(rc.IsOk());
  244. EXPECT_EQ(tensor_map.size(), 6);
  245. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  246. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  247. EXPECT_NE(tensor_map.find("A"), tensor_map.end());
  248. EXPECT_NE(tensor_map.find("B"), tensor_map.end());
  249. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  250. EXPECT_NE(tensor_map.find("Y"), tensor_map.end());
  251. EXPECT_NE(tensor_map.find("Z"), tensor_map.end());
  252. // Getting the next row as vector (by position).
  253. TensorRow tensor_list;
  254. rc = di.FetchNextTensorRow(&tensor_list);
  255. EXPECT_TRUE(rc.IsOk());
  256. // Based on the schema file, create the golden result to compare with.
  257. std::vector<DataType::Type> golden_types({DataType::Type::DE_UINT8, DataType::Type::DE_UINT8,
  258. DataType::Type::DE_UINT8, DataType::Type::DE_INT64,
  259. DataType::Type::DE_FLOAT32, DataType::Type::DE_INT64});
  260. std::vector<uint64_t> golden_ranks({3, 3, 3, 1, 4, 1});
  261. std::vector<TensorShape> golden_shapes({TensorShape({3, 4, 2}), TensorShape({3, 4, 2}), TensorShape({3, 4, 2}),
  262. TensorShape({7}), TensorShape({1, 13, 14, 12}), TensorShape({9})});
  263. while (!tensor_list.empty()) {
  264. for (uint32_t i = 0; i < tensor_list.size(); i++) {
  265. EXPECT_EQ(tensor_list[i]->type(), golden_types[i]);
  266. EXPECT_EQ(tensor_list[i]->Rank(), golden_ranks[i]);
  267. EXPECT_EQ(tensor_list[i]->shape(), golden_shapes[i]);
  268. EXPECT_NE(tensor_list[i]->GetBuffer(), nullptr);
  269. }
  270. rc = di.FetchNextTensorRow(&tensor_list);
  271. EXPECT_TRUE(rc.IsOk());
  272. }
  273. }
  274. // TestMultiTensorOp scenario:
  275. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  276. // A series of 3-to-1 and 1-to-3 TensorOps are applied to [image, A, B] and
  277. // produce final output columns [X, Y, Z].
  278. // Based on the new MapOp behaviour, the column ordering will be |X|Y|Z|label|.
  279. TEST_F(MindDataTestMapOp, TestMultiTensorOp) {
  280. Status rc;
  281. MS_LOG(INFO) << "Doing TestMultiTensorOp.";
  282. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  283. auto my_tfreader_op = this->CreateTFReaderOp();
  284. rc = my_tree_->AssociateNode(my_tfreader_op);
  285. EXPECT_TRUE(rc.IsOk());
  286. auto my_op1 = std::make_shared<mindspore::dataset::test::ThreeToOneOp>();
  287. auto my_op2 = std::make_shared<mindspore::dataset::test::OneToThreeOp>();
  288. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  289. my_func_list.push_back(my_op1);
  290. my_func_list.push_back(my_op2);
  291. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  292. auto op_connector_size = config_manager->op_connector_size();
  293. std::vector<std::string> in_columns = {"image", "A", "B"};
  294. std::vector<std::string> out_columns = {"X", "Y", "Z"};
  295. std::shared_ptr<MapOp> my_map_op =
  296. std::make_shared<MapOp>(in_columns, out_columns, std::move(my_func_list), 1, op_connector_size);
  297. rc = my_tree_->AssociateNode(my_map_op);
  298. EXPECT_TRUE(rc.IsOk());
  299. rc = my_map_op->AddChild(my_tfreader_op);
  300. EXPECT_TRUE(rc.IsOk());
  301. rc = my_tree_->AssignRoot(my_map_op);
  302. EXPECT_TRUE(rc.IsOk());
  303. rc = my_tree_->Prepare();
  304. EXPECT_TRUE(rc.IsOk());
  305. rc = my_tree_->Launch();
  306. EXPECT_TRUE(rc.IsOk());
  307. // Start the loop of reading tensors from our pipeline
  308. DatasetIterator di(my_tree_);
  309. TensorMap tensor_map;
  310. rc = di.GetNextAsMap(&tensor_map);
  311. EXPECT_TRUE(rc.IsOk());
  312. while (!tensor_map.empty()) {
  313. EXPECT_EQ(tensor_map.size(), 4);
  314. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  315. EXPECT_EQ(tensor_map.find("A"), tensor_map.end());
  316. EXPECT_EQ(tensor_map.find("B"), tensor_map.end());
  317. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  318. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  319. EXPECT_NE(tensor_map.find("Y"), tensor_map.end());
  320. EXPECT_NE(tensor_map.find("Z"), tensor_map.end());
  321. // XYZ are Tensor shared_ptr to image, so it should have the same shape as image column.
  322. EXPECT_EQ(tensor_map["X"]->shape(), TensorShape({3, 4, 2}));
  323. EXPECT_EQ(tensor_map["Y"]->shape(), TensorShape({3, 4, 2}));
  324. EXPECT_EQ(tensor_map["Z"]->shape(), TensorShape({3, 4, 2}));
  325. rc = di.GetNextAsMap(&tensor_map);
  326. EXPECT_TRUE(rc.IsOk());
  327. }
  328. }
  329. TEST_F(MindDataTestMapOp, TestTFReaderRepeatMap) {
  330. Status rc;
  331. MS_LOG(INFO) << "Doing TestTFReaderRepeatMap.";
  332. uint32_t num_repeats = 3;
  333. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total
  334. // of 10 rows.
  335. auto my_tfreader_op = this->CreateTFReaderOp();
  336. rc = my_tree_->AssociateNode(my_tfreader_op);
  337. EXPECT_TRUE(rc.IsOk());
  338. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  339. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  340. my_func_list.push_back(my_no_op);
  341. std::shared_ptr<RepeatOp> my_repeat_op = std::make_shared<RepeatOp>(num_repeats);
  342. rc = my_tree_->AssociateNode(my_repeat_op);
  343. EXPECT_TRUE(rc.IsOk());
  344. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  345. auto op_connector_size = config_manager->op_connector_size();
  346. std::vector<std::string> in_columns = {"label"};
  347. std::vector<std::string> out_columns = {};
  348. std::shared_ptr<MapOp> my_map_op =
  349. std::make_shared<MapOp>(in_columns, out_columns, std::move(my_func_list), 5, op_connector_size);
  350. rc = my_tree_->AssociateNode(my_map_op);
  351. EXPECT_TRUE(rc.IsOk());
  352. rc = my_map_op->AddChild(my_repeat_op);
  353. EXPECT_TRUE(rc.IsOk());
  354. my_tfreader_op->set_total_repeats(num_repeats);
  355. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  356. rc = my_repeat_op->AddChild(my_tfreader_op);
  357. EXPECT_TRUE(rc.IsOk());
  358. rc = my_tree_->AssignRoot(my_map_op);
  359. EXPECT_TRUE(rc.IsOk());
  360. rc = my_tree_->Prepare();
  361. EXPECT_TRUE(rc.IsOk());
  362. rc = my_tree_->Launch();
  363. EXPECT_TRUE(rc.IsOk());
  364. // Start the loop of reading tensors from our pipeline
  365. DatasetIterator di(my_tree_);
  366. TensorRow tensor_list;
  367. rc = di.FetchNextTensorRow(&tensor_list);
  368. EXPECT_TRUE(rc.IsOk());
  369. EXPECT_EQ(tensor_list.size(), 4);
  370. uint32_t row_count = 0;
  371. while (!tensor_list.empty()) {
  372. row_count++;
  373. MS_LOG(INFO) << "row_count: " << row_count << ".";
  374. rc = di.FetchNextTensorRow(&tensor_list);
  375. EXPECT_TRUE(rc.IsOk());
  376. }
  377. ASSERT_EQ(row_count, 10 * num_repeats);
  378. }
  379. TEST_F(MindDataTestMapOp, TestTFReaderMapRepeat) {
  380. Status rc;
  381. MS_LOG(INFO) << "Doing TestTFReaderMapRepeat.";
  382. uint32_t num_repeats = 3;
  383. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total
  384. // of 10 rows.
  385. auto my_tfreader_op = this->CreateTFReaderOp();
  386. rc = my_tree_->AssociateNode(my_tfreader_op);
  387. EXPECT_TRUE(rc.IsOk());
  388. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  389. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  390. my_func_list.push_back(my_no_op);
  391. std::shared_ptr<RepeatOp> my_repeat_op = std::make_shared<RepeatOp>(num_repeats);
  392. rc = my_tree_->AssociateNode(my_repeat_op);
  393. EXPECT_TRUE(rc.IsOk());
  394. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  395. auto op_connector_size = config_manager->op_connector_size();
  396. std::vector<std::string> input_columns = {"label"};
  397. std::vector<std::string> output_columns = {};
  398. std::shared_ptr<MapOp> my_map_op =
  399. std::make_shared<MapOp>(input_columns, output_columns, std::move(my_func_list), 50, op_connector_size);
  400. rc = my_tree_->AssociateNode(my_map_op);
  401. EXPECT_TRUE(rc.IsOk());
  402. my_map_op->set_total_repeats(num_repeats);
  403. my_map_op->set_num_repeats_per_epoch(num_repeats);
  404. rc = my_repeat_op->AddChild(my_map_op);
  405. EXPECT_TRUE(rc.IsOk());
  406. my_tfreader_op->set_total_repeats(num_repeats);
  407. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  408. rc = my_map_op->AddChild(my_tfreader_op);
  409. EXPECT_TRUE(rc.IsOk());
  410. rc = my_tree_->AssignRoot(my_repeat_op);
  411. EXPECT_TRUE(rc.IsOk());
  412. rc = my_tree_->Prepare();
  413. EXPECT_TRUE(rc.IsOk());
  414. rc = my_tree_->Launch();
  415. EXPECT_TRUE(rc.IsOk());
  416. // Start the loop of reading tensors from our pipeline
  417. DatasetIterator di(my_tree_);
  418. TensorRow tensor_list;
  419. rc = di.FetchNextTensorRow(&tensor_list);
  420. EXPECT_TRUE(rc.IsOk());
  421. EXPECT_EQ(tensor_list.size(), 4);
  422. uint32_t row_count = 0;
  423. while (!tensor_list.empty()) {
  424. row_count++;
  425. MS_LOG(INFO) << "row_count: " << row_count << ".";
  426. rc = di.FetchNextTensorRow(&tensor_list);
  427. EXPECT_TRUE(rc.IsOk());
  428. }
  429. ASSERT_EQ(row_count, 10 * num_repeats);
  430. }
  431. TEST_F(MindDataTestMapOp, TFReader_Decode_Repeat_Resize) {
  432. Status rc;
  433. MS_LOG(INFO) << "Doing TFReader_Decode_Repeat_Resize.";
  434. uint32_t num_repeats = 2;
  435. std::string dataset_path = datasets_root_path_ + "/" + "test_tf_file_3_images/train-0000-of-0001.data";
  436. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  437. auto op_connector_size = config_manager->op_connector_size();
  438. std::unique_ptr<DataSchema> schema = std::make_unique<DataSchema>();
  439. std::vector<std::string> columns_to_load = {"image", "label"};
  440. std::vector<std::string> files = {dataset_path};
  441. std::shared_ptr<TFReaderOp> my_tfreader_op = std::make_shared<TFReaderOp>(
  442. 1, 2, 0, files, std::move(schema), op_connector_size, columns_to_load, false, 1, 0, false);
  443. (void)my_tfreader_op->Init();
  444. rc = my_tree_->AssociateNode(my_tfreader_op);
  445. EXPECT_TRUE(rc.IsOk());
  446. auto decode_op = std::make_shared<DecodeOp>();
  447. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  448. my_func_list.push_back(decode_op);
  449. std::shared_ptr<RepeatOp> my_repeat_op = std::make_shared<RepeatOp>(num_repeats);
  450. rc = my_tree_->AssociateNode(my_repeat_op);
  451. EXPECT_TRUE(rc.IsOk());
  452. std::vector<std::string> input_columns = {"image"};
  453. std::vector<std::string> output_columns = {};
  454. std::shared_ptr<MapOp> my_map_decode_op =
  455. std::make_shared<MapOp>(input_columns, output_columns, std::move(my_func_list), 4, op_connector_size);
  456. rc = my_tree_->AssociateNode(my_map_decode_op);
  457. EXPECT_TRUE(rc.IsOk());
  458. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  459. std::vector<std::shared_ptr<TensorOp>> my_func_list2;
  460. my_func_list2.push_back(resize_op);
  461. std::shared_ptr<MapOp> my_map_resize_op =
  462. std::make_shared<MapOp>(input_columns, output_columns, std::move(my_func_list2), 5, op_connector_size);
  463. rc = my_tree_->AssociateNode(my_map_resize_op);
  464. EXPECT_TRUE(rc.IsOk());
  465. my_tfreader_op->set_total_repeats(num_repeats);
  466. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  467. rc = my_map_decode_op->AddChild(my_tfreader_op);
  468. EXPECT_TRUE(rc.IsOk());
  469. my_map_decode_op->set_total_repeats(num_repeats);
  470. my_map_decode_op->set_num_repeats_per_epoch(num_repeats);
  471. rc = my_repeat_op->AddChild(my_map_decode_op);
  472. EXPECT_TRUE(rc.IsOk());
  473. rc = my_map_resize_op->AddChild(my_repeat_op);
  474. EXPECT_TRUE(rc.IsOk());
  475. rc = my_tree_->AssignRoot(my_map_resize_op);
  476. EXPECT_TRUE(rc.IsOk());
  477. rc = my_tree_->Prepare();
  478. EXPECT_TRUE(rc.IsOk());
  479. rc = my_tree_->Launch();
  480. EXPECT_TRUE(rc.IsOk());
  481. // Start the loop of reading tensors from our pipeline
  482. DatasetIterator di(my_tree_);
  483. TensorRow tensor_list;
  484. rc = di.FetchNextTensorRow(&tensor_list);
  485. EXPECT_TRUE(rc.IsOk());
  486. EXPECT_EQ(tensor_list.size(), 2);
  487. uint32_t row_count = 0;
  488. while (!tensor_list.empty()) {
  489. row_count++;
  490. rc = di.FetchNextTensorRow(&tensor_list);
  491. EXPECT_TRUE(rc.IsOk());
  492. }
  493. ASSERT_EQ(row_count, 6);
  494. }
  495. TEST_F(MindDataTestMapOp, ImageFolder_Decode_Repeat_Resize) {
  496. Status rc;
  497. MS_LOG(INFO) << "Doing ImageFolder_Decode_Repeat_Resize.";
  498. std::string folder_path = datasets_root_path_ + "/testPK/data";
  499. uint32_t num_repeats = 2;
  500. std::shared_ptr<RepeatOp> repeat_op = std::make_shared<RepeatOp>(num_repeats);
  501. EXPECT_TRUE(rc.IsOk());
  502. auto decode_op = std::make_shared<DecodeOp>();
  503. std::vector<std::shared_ptr<TensorOp>> func_list;
  504. func_list.push_back(decode_op);
  505. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  506. int32_t op_connector_size = config_manager->op_connector_size();
  507. int32_t num_parallel_workers = config_manager->num_parallel_workers();
  508. std::vector<std::string> input_columns = {"image"};
  509. std::vector<std::string> output_columns = {};
  510. std::shared_ptr<MapOp> map_decode_map =
  511. std::make_shared<MapOp>(input_columns, output_columns, func_list, 4, op_connector_size);
  512. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  513. std::vector<std::shared_ptr<TensorOp>> func_list2;
  514. func_list2.push_back(resize_op);
  515. std::shared_ptr<MapOp> map_resize_op =
  516. std::make_shared<MapOp>(input_columns, output_columns, func_list2, 5, op_connector_size);
  517. auto image_folder_op = ImageFolder(num_parallel_workers, 2, 32, folder_path, false);
  518. image_folder_op->set_total_repeats(num_repeats);
  519. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  520. map_decode_map->set_total_repeats(num_repeats);
  521. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  522. my_tree_ = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  523. rc = my_tree_->Prepare();
  524. EXPECT_TRUE(rc.IsOk());
  525. rc = my_tree_->Launch();
  526. EXPECT_TRUE(rc.IsOk());
  527. // Start the loop of reading tensors from our pipeline
  528. DatasetIterator di(my_tree_);
  529. TensorMap tensor_map;
  530. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  531. EXPECT_TRUE(rc.IsOk());
  532. uint64_t i = 0;
  533. int32_t label = 0;
  534. int32_t img_class[] = {0, 1, 2, 3};
  535. std::string result;
  536. while (tensor_map.size() != 0) {
  537. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  538. MS_LOG(DEBUG) << "row:" << i << "\tlabel:" << label << "\n";
  539. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  540. // Dump all the image into string, to be used as a comparison later.
  541. result.append((char *)tensor_map["image"]->GetBuffer(), (int64_t)tensor_map["image"]->Size());
  542. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  543. i++;
  544. }
  545. EXPECT_TRUE(i == 88);
  546. // Part-2 : creating mapop with performance mode = false, to check if the result is the same
  547. // as when performance mode = true.
  548. repeat_op = std::make_shared<RepeatOp>(num_repeats);
  549. EXPECT_TRUE(rc.IsOk());
  550. map_decode_map = std::make_shared<MapOp>(input_columns, output_columns, func_list, 14, op_connector_size);
  551. map_resize_op = std::make_shared<MapOp>(input_columns, output_columns, func_list2, 15, op_connector_size);
  552. image_folder_op = ImageFolder(16, 2, 32, folder_path, false);
  553. image_folder_op->set_total_repeats(num_repeats);
  554. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  555. map_decode_map->set_total_repeats(num_repeats);
  556. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  557. auto my_tree_2 = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  558. rc = my_tree_2->Prepare();
  559. EXPECT_TRUE(rc.IsOk());
  560. rc = my_tree_2->Launch();
  561. EXPECT_TRUE(rc.IsOk());
  562. // Start the loop of reading tensors from our pipeline
  563. DatasetIterator di2(my_tree_2);
  564. ASSERT_OK(di2.GetNextAsMap(&tensor_map));
  565. EXPECT_TRUE(rc.IsOk());
  566. i = 0;
  567. label = 0;
  568. std::string result2;
  569. while (tensor_map.size() != 0) {
  570. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  571. MS_LOG(DEBUG) << "row:" << i << "\tlabel:" << label << "\n";
  572. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  573. result2.append((char *)tensor_map["image"]->GetBuffer(), (int64_t)tensor_map["image"]->Size());
  574. ASSERT_OK(di2.GetNextAsMap(&tensor_map));
  575. i++;
  576. }
  577. EXPECT_TRUE(i == 88);
  578. EXPECT_EQ(result.size(), result2.size());
  579. EXPECT_EQ(result, result2);
  580. }
  581. TEST_F(MindDataTestMapOp, ImageFolder_Decode_Repeat_Resize_NoInputColumns) {
  582. Status rc;
  583. MS_LOG(INFO) << "Doing ImageFolder_Decode_Repeat_Resize_NoInputColumns.";
  584. std::string folder_path = datasets_root_path_ + "/testPK/data";
  585. uint32_t num_repeats = 2;
  586. std::shared_ptr<RepeatOp> repeat_op = std::make_shared<RepeatOp>(num_repeats);
  587. ;
  588. auto decode_op = std::make_shared<DecodeOp>();
  589. std::vector<std::shared_ptr<TensorOp>> func_list;
  590. func_list.push_back(decode_op);
  591. std::shared_ptr<ConfigManager> config_manager = GlobalContext::config_manager();
  592. auto op_connector_size = config_manager->op_connector_size();
  593. std::vector<std::string> input_columns = {};
  594. std::vector<std::string> output_columns = {};
  595. std::shared_ptr<MapOp> map_decode_map =
  596. std::make_shared<MapOp>(input_columns, output_columns, std::move(func_list), 4, op_connector_size);
  597. ;
  598. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  599. std::vector<std::shared_ptr<TensorOp>> func_list2;
  600. func_list2.push_back(resize_op);
  601. std::shared_ptr<MapOp> map_resize_op =
  602. std::make_shared<MapOp>(input_columns, output_columns, std::move(func_list2), 5, op_connector_size);
  603. ;
  604. auto image_folder_op = ImageFolder(16, 2, 32, folder_path, false);
  605. image_folder_op->set_total_repeats(num_repeats);
  606. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  607. map_decode_map->set_total_repeats(num_repeats);
  608. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  609. my_tree_ = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  610. rc = my_tree_->Prepare();
  611. EXPECT_TRUE(rc.IsOk());
  612. rc = my_tree_->Launch();
  613. EXPECT_TRUE(rc.IsOk());
  614. // Start the loop of reading tensors from our pipeline
  615. DatasetIterator di(my_tree_);
  616. TensorMap tensor_map;
  617. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  618. EXPECT_TRUE(rc.IsOk());
  619. uint64_t i = 0;
  620. int32_t label = 0;
  621. int32_t img_class[] = {0, 1, 2, 3};
  622. std::string result;
  623. while (tensor_map.size() != 0) {
  624. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  625. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  626. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  627. i++;
  628. }
  629. EXPECT_TRUE(i == 88);
  630. }