{ "cells": [ { "cell_type": "markdown", "id": "7e31ebc8-b449-4052-b959-8f473b6c9fb7", "metadata": {}, "source": [ "[![在线运行](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.0/resource/_static/logo_modelarts.png)](https://authoring-modelarts-cnnorth4.huaweicloud.com/console/lab?share-url-b64=aHR0cHM6Ly9vYnMuZHVhbHN0YWNrLmNuLW5vcnRoLTQubXlodWF3ZWljbG91ZC5jb20vbWluZHNwb3JlLXdlYnNpdGUvbm90ZWJvb2svcjIuMC90dXRvcmlhbHMvemhfY24vYmVnaW5uZXIvbWluZHNwb3JlX3RyYW5zZm9ybXMuaXB5bmI=&imageid=e225a9aa-230a-4ea5-a538-b5faed64a6a6) [![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.0/resource/_static/logo_notebook.png)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.0/tutorials/zh_cn/beginner/mindspore_transforms.ipynb) [![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.0/resource/_static/logo_download_code.png)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.0/tutorials/zh_cn/beginner/mindspore_transforms.py) [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.0/resource/_static/logo_source.png)](https://gitee.com/mindspore/docs/blob/r2.0/tutorials/source_zh_cn/beginner/transforms.ipynb)\n", "\n", "[基本介绍](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/introduction.html) || [快速入门](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/quick_start.html) || [张量 Tensor](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/tensor.html) || [数据集 Dataset](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/dataset.html) || **数据变换 Transforms** || [网络构建](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/model.html) || [函数式自动微分](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/autograd.html) || [模型训练](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/train.html) || [保存与加载](https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/save_load.html)" ] }, { "cell_type": "markdown", "id": "ca3f817f-57c1-42df-9529-3e390d067cf1", "metadata": {}, "source": [ "# 数据变换 Transforms\n", "\n", "通常情况下,直接加载的原始数据并不能直接送入神经网络进行训练,此时我们需要对其进行数据预处理。MindSpore提供不同种类的数据变换(Transforms),配合数据处理Pipeline来实现数据预处理。所有的Transforms均可通过`map`方法传入,实现对指定数据列的处理。\n", "\n", "`mindspore.dataset`提供了面向图像、文本、音频等不同数据类型的Transforms,同时也支持使用Lambda函数。下面分别对其进行介绍。" ] }, { "cell_type": "code", "execution_count": 1, "id": "20a2f211-4515-4442-8c2b-c02b64dc668e", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from PIL import Image\n", "from download import download\n", "from mindspore.dataset import transforms, vision, text\n", "from mindspore.dataset import GeneratorDataset, MnistDataset" ] }, { "cell_type": "markdown", "id": "761ddc32-ab75-41ee-91d6-f4a4709be632", "metadata": { "tags": [] }, "source": [ "## Common Transforms\n", "\n", "`mindspore.dataset.transforms`模块支持一系列通用Transforms。这里我们以`Compose`为例,介绍其使用方式。\n", "\n", "### Compose\n", "\n", "`Compose`接收一个数据增强操作序列,然后将其组合成单个数据增强操作。我们仍基于Mnist数据集呈现Transforms的应用效果。" ] }, { "cell_type": "code", "execution_count": 2, "id": "abf6b9fe-688a-4dac-9a00-962eda1eb64f", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/MNIST_Data.zip (10.3 MB)\n", "\n", "file_sizes: 100%|██████████████████████████| 10.8M/10.8M [00:01<00:00, 9.01MB/s]\n", "Extracting zip file...\n", "Successfully downloaded / unzipped to ./\n" ] } ], "source": [ "# Download data from open datasets\n", "\n", "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/\" \\\n", " \"notebook/datasets/MNIST_Data.zip\"\n", "path = download(url, \"./\", kind=\"zip\", replace=True)\n", "\n", "train_dataset = MnistDataset('MNIST_Data/train')" ] }, { "cell_type": "code", "execution_count": 3, "id": "1bab3ebe-d258-4581-ad69-9bb85a7b7814", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(28, 28, 1)\n" ] } ], "source": [ "image, label = next(train_dataset.create_tuple_iterator())\n", "print(image.shape)" ] }, { "cell_type": "code", "execution_count": 4, "id": "87f4777b-1794-43b9-9816-44360b9c51db", "metadata": {}, "outputs": [], "source": [ "composed = transforms.Compose(\n", " [\n", " vision.Rescale(1.0 / 255.0, 0),\n", " vision.Normalize(mean=(0.1307,), std=(0.3081,)),\n", " vision.HWC2CHW()\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "0adfef6c-d730-4f0c-9a53-720cfc0d61c0", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(1, 28, 28)\n" ] } ], "source": [ "train_dataset = train_dataset.map(composed, 'image')\n", "image, label = next(train_dataset.create_tuple_iterator())\n", "print(image.shape)" ] }, { "cell_type": "markdown", "id": "750f876f-8263-4ea6-b085-5d3275f3e311", "metadata": {}, "source": [ "更多通用Transforms详见[mindspore.dataset.transforms](https://www.mindspore.cn/docs/zh-CN/r2.0/api_python/mindspore.dataset.transforms.html)。" ] }, { "cell_type": "markdown", "id": "23afcc06-4bfd-4a57-97e2-b5c09e05b142", "metadata": {}, "source": [ "## Vision Transforms\n", "\n", "`mindspore.dataset.vision`模块提供一系列针对图像数据的Transforms。在Mnist数据处理过程中,使用了`Rescale`、`Normalize`和`HWC2CHW`变换。下面对其进行详述。" ] }, { "cell_type": "markdown", "id": "4cda18d2-7ad0-47c9-970a-ed5900c4ee3b", "metadata": {}, "source": [ "### Rescale\n", "\n", "`Rescale`变换用于调整图像像素值的大小,包括两个参数:\n", "\n", "- rescale:缩放因子。\n", "- shift:平移因子。\n", "\n", "图像的每个像素将根据这两个参数进行调整,输出的像素值为$output_{i} = input_{i} * rescale + shift$。\n", "\n", "这里我们先使用numpy随机生成一个像素值在\\[0, 255\\]的图像,将其像素值进行缩放。" ] }, { "cell_type": "code", "execution_count": 6, "id": "c99377ed-e1ae-4c6f-8285-cde61039c069", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[170 10 218 ... 81 128 96]\n [ 2 107 146 ... 239 178 165]\n [232 137 235 ... 222 109 216]\n ...\n [193 140 60 ... 72 133 144]\n [232 175 58 ... 55 110 94]\n [152 241 105 ... 187 45 43]]\n" ] } ], "source": [ "random_np = np.random.randint(0, 255, (48, 48), np.uint8)\n", "random_image = Image.fromarray(random_np)\n", "print(random_np)" ] }, { "cell_type": "markdown", "id": "9b17ac44-14ec-48a4-a43a-da4de1ad5c3e", "metadata": {}, "source": [ "为了更直观地呈现Transform前后的数据对比,我们使用Transforms的[Eager模式](https://www.mindspore.cn/tutorials/zh-CN/r2.0/advanced/dataset/eager.html)进行演示。首先实例化Transform对象,然后调用对象进行数据处理。" ] }, { "cell_type": "code", "execution_count": 7, "id": "516f4169-a13f-42b2-b976-222b029194a1", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[0.6666667 0.03921569 0.854902 ... 0.31764707 0.5019608 0.37647063]\n [0.00784314 0.41960788 0.57254905 ... 0.93725497 0.69803923 0.64705884]\n [0.909804 0.5372549 0.9215687 ... 0.8705883 0.427451 0.8470589 ]\n ...\n [0.7568628 0.54901963 0.23529413 ... 0.28235295 0.52156866 0.5647059 ]\n [0.909804 0.6862745 0.227451 ... 0.21568629 0.43137258 0.36862746]\n [0.59607846 0.9450981 0.41176474 ... 0.73333335 0.1764706 0.16862746]]\n" ] } ], "source": [ "rescale = vision.Rescale(1.0 / 255.0, 0)\n", "rescaled_image = rescale(random_image)\n", "print(rescaled_image)" ] }, { "cell_type": "markdown", "id": "3cb95c6d-3db1-486f-b302-e97ab33c1d17", "metadata": {}, "source": [ "可以看到,使用`Rescale`后的每个像素值都进行了缩放。" ] }, { "cell_type": "markdown", "id": "3361af8a-08f7-45f5-92b6-1ad3889c82e8", "metadata": {}, "source": [ "### Normalize\n", "\n", "`Normalize`变换用于对输入图像的归一化,包括三个参数:\n", "\n", "- mean:图像每个通道的均值。\n", "- std:图像每个通道的标准差。\n", "- is_hwc:输入图像格式为(height, width, channel)还是(channel, height, width)。\n", "\n", "图像的每个通道将根据`mean`和`std`进行调整,计算公式为$output_{c} = \\frac{input_{c} - mean_{c}}{std_{c}}$,其中 $c$代表通道索引。" ] }, { "cell_type": "code", "execution_count": 8, "id": "e370e1a3-1101-4280-be6a-befb0fbb532d", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[ 1.7395868 -0.29693064 2.3505423 ... 0.60677403 1.2050011\n 0.7976976 ]\n [-0.3987565 0.9377082 1.4341093 ... 2.617835 1.8414128\n 1.6759458 ]\n [ 2.5287375 1.3195552 2.5669222 ... 2.4014552 0.9631647\n 2.3250859 ]\n ...\n [ 2.0323365 1.3577399 0.33948112 ... 0.49221992 1.2686423\n 1.4086528 ]\n [ 2.5287375 1.803228 0.31402466 ... 0.27583995 0.9758929\n 0.77224106]\n [ 1.5104787 2.6432917 0.9122518 ... 1.9559668 0.14855757\n 0.12310111]]\n" ] } ], "source": [ "normalize = vision.Normalize(mean=(0.1307,), std=(0.3081,))\n", "normalized_image = normalize(rescaled_image)\n", "print(normalized_image)" ] }, { "cell_type": "markdown", "id": "cdf32c52-9f7c-428a-97d3-3c207e4ad092", "metadata": {}, "source": [ "### HWC2CHW\n", "\n", "`HWC2CHW`变换用于转换图像格式。在不同的硬件设备中可能会对(height, width, channel)或(channel, height, width)两种不同格式有针对性优化。MindSpore设置HWC为默认图像格式,在有CHW格式需求时,可使用该变换进行处理。\n", "\n", "这里我们先将前文中`normalized_image`处理为HWC格式,然后进行转换。可以看到转换前后的shape发生了变化。" ] }, { "cell_type": "code", "execution_count": 9, "id": "3725b284-f2df-45f3-a7f7-8c3a68e3d44a", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(48, 48, 1) (1, 48, 48)\n" ] } ], "source": [ "hwc_image = np.expand_dims(normalized_image, -1)\n", "hwc2chw = vision.HWC2CHW()\n", "chw_image = hwc2chw(hwc_image)\n", "print(hwc_image.shape, chw_image.shape)" ] }, { "cell_type": "markdown", "id": "43ab9fbc-3201-425b-a5f0-62696a5446a0", "metadata": {}, "source": [ "更多Vision Transforms详见[mindspore.dataset.vision](https://www.mindspore.cn/docs/zh-CN/r2.0/api_python/mindspore.dataset.transforms.html#视觉)。" ] }, { "cell_type": "markdown", "id": "1128625a-8bdc-4e90-8a2f-b951f4b27752", "metadata": {}, "source": [ "## Text Transforms" ] }, { "cell_type": "markdown", "id": "0a25654c-2850-4df0-9214-531c25f751af", "metadata": {}, "source": [ "`mindspore.dataset.text`模块提供一系列针对文本数据的Transforms。与图像数据不同,文本数据需要有分词(Tokenize)、构建词表、Token转Index等操作。这里简单介绍其使用方法。\n", "\n", "首先我们定义三段文本,作为待处理的数据,并使用`GeneratorDataset`进行加载。" ] }, { "cell_type": "code", "execution_count": 10, "id": "6d93837b-d975-4044-8e24-58fb2f4e5011", "metadata": {}, "outputs": [], "source": [ "texts = ['Welcome to Beijing']" ] }, { "cell_type": "code", "execution_count": 11, "id": "598bca9b-e755-4fe2-a7d6-b152e82c9d1a", "metadata": {}, "outputs": [], "source": [ "test_dataset = GeneratorDataset(texts, 'text')" ] }, { "cell_type": "markdown", "id": "a9ab6175-6b60-495e-bb4d-37b97052c11e", "metadata": {}, "source": [ "### PythonTokenizer\n", "\n", "分词(Tokenize)操作是文本数据的基础处理方法,MindSpore提供多种不同的Tokenizer。这里我们选择基础的`PythonTokenizer`举例,此Tokenizer允许用户自由实现分词策略。随后我们利用`map`操作将此分词器应用到输入的文本中,对其进行分词。" ] }, { "cell_type": "code", "execution_count": 12, "id": "6636e1d1-59b9-4198-bab9-5a7343a66710", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[Tensor(shape=[3], dtype=String, value= ['Welcome', 'to', 'Beijing'])]\n" ] } ], "source": [ "def my_tokenizer(content):\n", " return content.split()\n", "\n", "test_dataset = test_dataset.map(text.PythonTokenizer(my_tokenizer))\n", "print(next(test_dataset.create_tuple_iterator()))" ] }, { "cell_type": "markdown", "id": "d7ed698c-1edc-4c56-8a24-498ade32b2b9", "metadata": {}, "source": [ "### Lookup\n", "\n", "`Lookup`为词表映射变换,用来将Token转换为Index。在使用`Lookup`前,需要构造词表,一般可以加载已有的词表,或使用`Vocab`生成词表。这里我们选择使用`Vocab.from_dataset`方法从数据集中生成词表。" ] }, { "cell_type": "code", "execution_count": 13, "id": "00884c33-a3ee-4b8f-8ee3-582d210fce85", "metadata": {}, "outputs": [], "source": [ "vocab = text.Vocab.from_dataset(test_dataset)" ] }, { "cell_type": "markdown", "id": "5a7dbd0a-5c0f-49f6-b562-feb0ddabfba1", "metadata": {}, "source": [ "获得词表后我们可以使用`vocab`方法查看词表。" ] }, { "cell_type": "code", "execution_count": 14, "id": "cebc8d0d-a9e4-45c3-bc00-742d903632e9", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "{'to': 2, 'Beijing': 0, 'Welcome': 1}\n" ] } ], "source": [ "print(vocab.vocab())" ] }, { "cell_type": "markdown", "id": "ccde57b8-74f9-4ff2-915f-17bd1da87c59", "metadata": {}, "source": [ "生成词表后,可以配合`map`方法进行词表映射变换,将Token转为Index。" ] }, { "cell_type": "code", "execution_count": 15, "id": "8919313b-e1c8-45e0-8b81-e0815f75b626", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[Tensor(shape=[3], dtype=Int32, value= [1, 2, 0])]\n" ] } ], "source": [ "test_dataset = test_dataset.map(text.Lookup(vocab))\n", "print(next(test_dataset.create_tuple_iterator()))" ] }, { "cell_type": "markdown", "id": "425077b8-0a15-4317-9d44-16d0bc84ea4c", "metadata": {}, "source": [ "更多Text Transforms详见[mindspore.dataset.text](https://www.mindspore.cn/docs/zh-CN/r2.0/api_python/mindspore.dataset.transforms.html#文本)。" ] }, { "cell_type": "markdown", "id": "2103e098-7a4f-43da-af61-14640aeb66e7", "metadata": { "tags": [] }, "source": [ "## Lambda Transforms\n", "\n", "Lambda函数是一种不需要名字、由一个单独表达式组成的匿名函数,表达式会在调用时被求值。Lambda Transforms可以加载任意定义的Lambda函数,提供足够的灵活度。在这里,我们首先使用一个简单的Lambda函数,对输入数据乘2:" ] }, { "cell_type": "code", "execution_count": 16, "id": "f49555eb-82a2-449e-b97f-ce9620e9d7d4", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[Tensor(shape=[], dtype=Int64, value= 2)], [Tensor(shape=[], dtype=Int64, value= 4)], [Tensor(shape=[], dtype=Int64, value= 6)]]\n" ] } ], "source": [ "test_dataset = GeneratorDataset([1, 2, 3], 'data', shuffle=False)\n", "test_dataset = test_dataset.map(lambda x: x * 2)\n", "print(list(test_dataset.create_tuple_iterator()))" ] }, { "cell_type": "markdown", "id": "5e8f538c-9b88-48aa-924e-e1023fbd2f5b", "metadata": {}, "source": [ "可以看到`map`传入Lambda函数后,迭代获得数据进行了乘2操作。\n", "\n", "我们也可以定义较复杂的函数,配合Lambda函数实现复杂数据处理:" ] }, { "cell_type": "code", "execution_count": 17, "id": "124f2f07-cc2f-4093-ba1f-9de56adcf06a", "metadata": {}, "outputs": [], "source": [ "def func(x):\n", " return x * x + 2\n", "\n", "test_dataset = test_dataset.map(lambda x: func(x))" ] }, { "cell_type": "code", "execution_count": 18, "id": "0deb59e5-54c3-4c12-9e00-f48570b9bb77", "metadata": {}, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[Tensor(shape=[], dtype=Int64, value= 6)], [Tensor(shape=[], dtype=Int64, value= 18)], [Tensor(shape=[], dtype=Int64, value= 38)]]\n" ] } ], "source": [ "print(list(test_dataset.create_tuple_iterator()))" ] } ], "metadata": { "kernelspec": { "display_name": "MindSpore", "language": "python", "name": "mindspore" }, "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": "8c9da313289c39257cb28b126d2dadd33153d4da4d524f730c81a4aaccbd2ca7" } } }, "nbformat": 4, "nbformat_minor": 5 }