{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 数据处理概述"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.9.0/tutorials/zh_cn/dataset/mindspore_overview.ipynb)&emsp;[![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.9.0/tutorials/zh_cn/dataset/mindspore_overview.py)&emsp;[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_source.svg)](https://atomgit.com/mindspore/docs/blob/r2.9.0/tutorials/source_zh_cn/dataset/overview.ipynb)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "MindSpore Dataset 提供两种数据处理能力：数据处理Pipeline模式和数据处理轻量化模式。\n",
    "\n",
    "1. 数据处理Pipeline模式：提供基于C++ Runtime的并发数据处理流水线（Pipeline）能力。用户通过定义数据集加载、数据变换、数据批处理（Batch）等流程，实现数据集的高效加载、高效处理、高效Batch。并发度可调、缓存可调等能力，实现为NPU卡训练提供零Bottle Neck的训练数据。\n",
    "\n",
    "2. 数据处理轻量化模式：支持用户使用数据变换操作（如：Resize、Crop、HWC2CHW等）进行单个样本的数据处理。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据处理Pipeline模式\n",
    "\n",
    "用户通过API定义的Dataset流水线，运行训练进程后Dataset会从数据集中循环加载数据 -> 处理 -> Batch -> 迭代器，最终用于训练。\n",
    "\n",
    "![MindSpore Dataset Pipeline](https://www.mindspore.cn/docs/zh-CN/r2.9.0/_images/dataset_pipeline.png)\n",
    "\n",
    "如上图所示，MindSpore Dataset模块使得用户很简便地定义数据预处理Pipeline，并以最高效（多进程/多线程）的方式处理数据集中样本，具体的步骤参考如下：\n",
    "\n",
    "- 数据集加载（Dataset）：用户可以方便地使用Dataset类 ([标准格式数据集加载](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.loading.html#%E6%A0%87%E5%87%86%E6%A0%BC%E5%BC%8F%E6%95%B0%E6%8D%AE%E9%9B%86%E5%8A%A0%E8%BD%BD)、[视觉数据集](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.loading.html#%E8%A7%86%E8%A7%89%E6%95%B0%E6%8D%AE%E9%9B%86)、[文本数据集](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.loading.html#%E6%96%87%E6%9C%AC%E6%95%B0%E6%8D%AE%E9%9B%86)、[音频数据集](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.loading.html#%E9%9F%B3%E9%A2%91%E6%95%B0%E6%8D%AE%E9%9B%86)) 来加载已支持的数据集，或者通过 UDF Loader + [GeneratorDataset 自定义数据集](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.GeneratorDataset.html#mindspore.dataset.GeneratorDataset) 实现Python层自定义数据集的加载。加载类方法可以使用多种Sampler、数据分片、数据shuffle等功能；\n",
    "\n",
    "- 数据集操作（filter/ skip）：用户通过数据集对象方法 [.shuffle](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/operation/mindspore.dataset.Dataset.shuffle.html#mindspore.dataset.Dataset.shuffle)、[.filter](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/operation/mindspore.dataset.Dataset.filter.html#mindspore.dataset.Dataset.filter)、[.skip](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/operation/mindspore.dataset.Dataset.skip.html#mindspore.dataset.Dataset.skip)、[.split](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/operation/mindspore.dataset.Dataset.split.html#mindspore.dataset.Dataset.split)、[.take](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/operation/mindspore.dataset.Dataset.take.html#mindspore.dataset.Dataset.take)等来实现数据集的进一步混洗、过滤、跳过、最多获取条数等操作；\n",
    "\n",
    "- 数据集样本变换操作（map）：用户可以将数据变换操作 （[vision数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E8%A7%86%E8%A7%89) ， [nlp数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E6%96%87%E6%9C%AC) ， [audio数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E9%9F%B3%E9%A2%91) ） 添加到map操作中执行，数据预处理过程中可以定义多个map操作，用于执行不同变换操作。数据变换操作也可以是用户自定义变换的 PyFunc ；\n",
    "\n",
    "- 批（batch）：用户在样本完成变换后，使用 [.batch](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/batch/mindspore.dataset.Dataset.batch.html#mindspore.dataset.Dataset.batch) 操作将多个样本组织成batch，也可以通过batch的参数 per_batch_map 来自定义batch逻辑；\n",
    "\n",
    "- 迭代器（create_dict_iterator）：最后用户通过数据集对象方法 [.create_dict_iterator](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/iterator/mindspore.dataset.Dataset.create_dict_iterator.html#mindspore.dataset.Dataset.create_dict_iterator)、[.create_tuple_iterator](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/dataset_method/iterator/mindspore.dataset.Dataset.create_tuple_iterator.html#mindspore.dataset.Dataset.create_tuple_iterator) 来创建迭代器将预处理完成的数据循环输出。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据集加载\n",
    "\n",
    "下面主要介绍单个数据集加载、数据集组合、数据集切分、数据集保存等常用数据集加载方式。\n",
    "\n",
    "#### 单个数据集加载\n",
    "\n",
    "数据集加载类用于实现本地磁盘、OBS和共享存储上的训练数据集加载，将存储上的数据集Load至内存中。数据集加载接口如下：\n",
    "\n",
    "| 数据集接口分类  | API列表  | 说明 |\n",
    "|------------------------|----------------------------------------------------------|--------------------------------------------------------------|\n",
    "| 标准格式数据集  | [MindDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.MindDataset.html#mindspore.dataset.MindDataset) 、 [TFRecordDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.TFRecordDataset.html#mindspore.dataset.TFRecordDataset) 、 [CSVDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.CSVDataset.html#mindspore.dataset.CSVDataset) 等 | 其中 MindDataset 依赖 MindSpore 数据格式， 详见： [格式转换](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/record.html) |\n",
    "| 自定义数据集  | [GeneratorDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.GeneratorDataset.html#mindspore.dataset.GeneratorDataset) 、 [RandomDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.RandomDataset.html#mindspore.dataset.RandomDataset) 等 | 其中 GeneratorDataset 负责加载用户自定义DataLoader， 详见： [自定义数据集](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E9%9B%86) |\n",
    "| 常用数据集  | [ImageFolderDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.ImageFolderDataset.html#mindspore.dataset.ImageFolderDataset) 、 [Cifar10Dataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.Cifar10Dataset.html#mindspore.dataset.Cifar10Dataset) 、 [IWSLT2017Dataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.IWSLT2017Dataset.html#mindspore.dataset.IWSLT2017Dataset) 、 [LJSpeechDataset](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/dataset/mindspore.dataset.LJSpeechDataset.html#mindspore.dataset.LJSpeechDataset) 等 | 用于常用的开源数据集 |\n",
    "\n",
    "以上数据集加载（[示例](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E6%95%B0%E6%8D%AE%E9%9B%86%E5%8A%A0%E8%BD%BD)）中，可以配置不同的参数，以实现不同的加载效果，常用参数举例如下：\n",
    "\n",
    "- `columns_list`：过滤数据集中指定的列，仅针对部分数据集接口。默认值：None，加载所有数据列。\n",
    "\n",
    "- `num_parallel_workers`：配置数据集的读取并发数。默认值：8。\n",
    "\n",
    "- 通过参数配置数据集的采样逻辑：\n",
    "\n",
    "    - `shuffle`：开启混洗。默认值：True。\n",
    "\n",
    "    - `num_shards` 和 `shard_id`：对数据集进行分片。默认值：None，不分片。\n",
    "\n",
    "    - 其他更多的采样逻辑可以参考：[数据采样](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/sampler.html)。\n",
    "\n",
    "#### 数据集组合\n",
    "\n",
    "数据集组合可以将多个数据集以串联/并联的方式组合起来，形成一个全新的dataset对象，详见[数据操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/eager.html#数据操作)。\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 数据集切分\n",
    "\n",
    "将数据集切分成训练数据集和验证数据集，分别用于训练过程和验证过程，详见[数据操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/eager.html#数据操作)。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 数据集保存\n",
    "\n",
    "将数据集重新保存到MindRecord数据格式，详见[数据操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/eager.html#数据操作)。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "### 数据变换\n",
    "\n",
    "#### 普通数据变换\n",
    "\n",
    "用户可以使用多种数据变换操作：\n",
    "\n",
    "- `.map(...)`：变换操作。\n",
    "- `.filter(...)`：过滤操作。\n",
    "- `.project(...)`：对多列进行排序和过滤。\n",
    "- `.rename(...)` 对指定列重命名。\n",
    "- `.shuffle(...)` 对数据进行缓存区大小的混洗。\n",
    "- `.skip(...)` 跳过数据集的前 n 条。\n",
    "- `.take(...)` 只读数据集的前 n 条样本。\n",
    "\n",
    "下面重点说明 `.map(...)` 的使用方法：\n",
    "\n",
    "- 在 `.map(...)` 中使用Dataset提供的数据变换操作\n",
    "\n",
    "    Dataset提供了丰富的[数据变换操作](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#)，这些数据变换操作可以直接放在 `.map(...)` 中使用。具体使用方法参考 [map变换操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E5%86%85%E7%BD%AE%E6%95%B0%E6%8D%AE%E5%8F%98%E6%8D%A2%E6%93%8D%E4%BD%9C)。\n",
    "\n",
    "- 在 `.map(...)` 中使用自定义数据变换操作\n",
    "\n",
    "    Dataset也支持用户自定义的数据变换操作，仅需将用户自定义函数传递给 `.map(...)` 即可。具体使用方法参考：[自定义map变换操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E5%8F%98%E6%8D%A2%E6%93%8D%E4%BD%9C)。\n",
    "\n",
    "- 在 `.map(...)` 中返回Dict数据结构数据\n",
    "\n",
    "    Dataset也支持在用户自定义的数据变换操作中返回Dict数据结构，使得定义的数据变换更加灵活。具体使用方法参考：[自定义map变换操作处理字典对象](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/python_objects.html#%E8%87%AA%E5%AE%9A%E4%B9%89map%E5%A2%9E%E5%BC%BA%E6%93%8D%E4%BD%9C%E5%A4%84%E7%90%86%E5%AD%97%E5%85%B8%E5%AF%B9%E8%B1%A1)。\n",
    "\n",
    "#### 自动数据增强\n",
    "\n",
    "除了以上的普通数据变换，Dataset 还提供了一种自动数据变换方式，可以基于特定策略自动对图像进行数据变换处理。详细说明见：[自动数据增强](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/augment.html)。\n",
    "\n",
    "### 数据batch\n",
    "\n",
    "Dataset提供 `.batch(...)` 操作，可以很方便的将数据变换操作后的样本组织成batch。有两种使用方式：\n",
    "\n",
    "1. 默认 `.batch(...)` 操作，将batch_size个样本组织成shape为 (batch_size, ...)的数据，详细用法请参考 [batch操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E6%95%B0%E6%8D%AEbatch)；\n",
    "\n",
    "2. 自定义 `.batch(..., per_batch_map, ...)` 操作，支持用户将 [np.ndarray, nd.ndarray, ...] 多条数据按照自定义逻辑组织batch，详细用法请参考 [自定义batch操作](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/python_objects.html#batch%E6%93%8D%E4%BD%9C%E5%A4%84%E7%90%86%E5%AD%97%E5%85%B8%E5%AF%B9%E8%B1%A1)。\n",
    "\n",
    "### 数据集迭代器\n",
    "\n",
    "用户在定义完成 `数据集加载（xxDataset）-> 数据处理（.map）-> 数据batch（.batch）` Dataset流水线（Pipeline）后，可以通过创建迭代器方法 `.create_dict_iterator(...)` / `.create_tuple_iterator(...)` 循环将数据输出。具体的使用方法参考：[数据集迭代器](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html#%E6%95%B0%E6%8D%AE%E9%9B%86%E8%BF%AD%E4%BB%A3%E5%99%A8)。\n",
    "\n",
    "### 性能优化\n",
    "\n",
    "#### 数据处理性能优化\n",
    "\n",
    "针对数据处理Pipeline性能不足的场景，可以参考[数据处理性能优化](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/optimize.html)来进一步优化性能，以满足训练端到端性能要求。\n",
    "\n",
    "#### 单节点数据缓存\n",
    "\n",
    "另外，对于推理场景，为了追求极致的性能，可以使用 [单节点数据缓存](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/cache.html) 将数据集缓存于本地内存中，以加速数据集的读取和预处理。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据处理轻量化模式\n",
    "\n",
    "用户可以直接使用数据变换操作处理一条数据，返回值即是数据变换的结果。\n",
    "\n",
    "数据变换操作（[vision数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E8%A7%86%E8%A7%89) ，[nlp数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E6%96%87%E6%9C%AC) ，[audio数据变换](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.dataset.transforms.html#%E9%9F%B3%E9%A2%91)）可以像调用普通函数一样直接来使用。常见用法是：先初始化数据变换对象，然后调用数据变换操作方法，传入需要处理的数据，最后得到处理的结果。示例详见[轻量化数据变换](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/eager.html#轻量化数据变换)。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 其他特性\n",
    "\n",
    "### 数据处理管道支持Python对象\n",
    "\n",
    "数据处理管道中的特定操作（如自定义数据集GeneratorDataset、自定义map增强操作、自定义batch(per_batch_map=...)）支持任意Python类型对象作为输入。详见[数据处理管道支持Python对象](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/dataset/python_objects.html)。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.5 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "vscode": {
   "interpreter": {
    "hash": "5109d816b82be14675a6b11f8e0f0d2e80f029176ed3710d54e125caa8520dfd"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
