当前位置:网站首页>技术干货 | 数据处理好难?来看MindSpore提供的解决思路!
技术干货 | 数据处理好难?来看MindSpore提供的解决思路!
2022-07-22 21:59:00 【昇思MindSpore】

本文是AI框架分析专栏的第五篇,总体目录参见AI框架的演进趋势和MindSpore的构想:
https://zhuanlan.zhihu.com/p/225392622
数据处理其实在AI的训练和推理中占了很大的比重,但是业界在这一块的分析比较少,本文期望通过MindSpore实践给大家一些参考。
01
AI框架中的数据处理
在构建深度学习模型时,数据处理是我们最先面临的挑战。任务开始之前,由于数据量受限,或者为了得到更好的结果,通常需要进行数据增强操作,来获得能使网络受益的数据输入。典型的训练数据处理流程如下图所示:

加载
指从各种异构存储中将训练数据加载到内存中,加载时涉及数据的访问、解析等处理。
Shuffle
训练一般是多个epoch,通过shuffle打乱数据集不同epoch的数据排序,防止训练过拟合。如果数据集支持随机访问,则只需按不同顺序随机选择数据就可以非常有效地进行混洗shuffle。如果数据集不支持随机访问(或仅部分随机访问像多个文件对象),那么一个子集的数据可以加载到一个特殊的混洗缓冲区shuffle buffer中。
map
完成训练数据的处理,包括图像类数据增强、Text类分词等处理。其中,数据增强是一种创造有着不同方向的“新”数据的方法,一是从有限数据中生成“更多数据”,二是防止过拟合。
batch
训练时一般都是使用mini-batch的方式,即一个批次训练少量数据;batch算子负责构造一个批次的数据发送给训练。
repeat
可以通过repeat的方式增加训练的总数据量;一次repeat就是加载一遍整个训练集。
模型在进行推理时,同样会涉及到数据处理,典型的过程如下图所示:

推理过程的数据处理,将一张图片进行解码、缩放、中心截图、归一化、通道变换等操作后,送入模型中进行推理并得到结果。与训练相比,推理时的数据转换基本一致,不同的是推理时一般加载单样本进行处理,而非数据集。本文将重点分析AI框架在数据处理时面临的挑战以及MindSpore的解决思路。
02
难点与挑战
2.1 数据处理的高效性
当前各AI框架的数据处理主要利用CPU运算,训练则利用GPU/AI芯片,两者是并行的。理想情况下,应该在每轮迭代开始前,就准备好完成增强之后的数据,保持训练过程持续地进行。然而在实际的训练中,很多时候数据处理成为了阻碍性能提升的瓶颈:或是因为从存储中读取数据的速度不足(I/O bound),或是因为数据增强操作效率过低(CPU bound)。
根据黄氏定律,GPU/AI芯片的算力每一年会提升一倍,相比于即将失效的摩尔定律,AI芯片的算力提升速度会远大于CPU。模型迭代计算效率的不断提升,对数据处理也提出了更高的要求:数据处理过程必须足够高效,才能够避免GPU/AI芯片因为等待训练数据而空闲。
2.2 数据处理的灵活性
数据处理的灵活性挑战主要体现在以下两个方面:
数据集种类繁多,难以统一
目前已知常用的开源数据集有几百种,每种由不同的组织/机构来产生,有各自的格式与组织方式。根据深度学习任务的不同,每种类型的输入也有自身的特点。以图像为例,其包含类型、长、宽、大小等属性信息,每张训练图像被标记成某一个类别,这些图像及其对应类别的列表数据被用来进行分类等训练;以音频为例,通过训练可以直接将语音转换为文字,进一步作为智能AI的输入,完成语义理解及指令性操作。
在数据集加载时,如何支持种类繁多的图像、文本、音频、视频格式,屏蔽IO差异并将其映射到内存结构中进行下一步处理,是AI框架重点需要解决的问题。
数据增强算法非常灵活
例如CV类场景,图像作为网络的输入,需要保证一定的一致性(如:大小、通道数、归一化等),也需要有一定的泛化能力(如:镜像、旋转、混合、颜色变换等),才能使训练得到的模型具有更好的精度。研究已经证明,采用不同的数据处理逻辑,训练得到的模型精度会有明显的不同。
以resnet50和ssd为例,数据处理过程对比如下:

其中既涉及到经典的数据处理逻辑,又包含了用户自定义的处理过程。AutoML和动态shape等场景,也对数据处理的灵活性提出了更高要求。所以,提供更多、更灵活的数据处理机制,也是框架需要重点考虑的。
2.3 端云统一
训练导出的模型,在推理时如何高效进行数据处理:
网络训练生成的模型文件中,记录了训练时的计算图及权重信息,但是数据处理过程往往没有统一存储到模型中,这就导致AI工程师在使用模型进行推理时,需要重新编写数据处理代码,十分不便。
端侧资源受限,需要提供更轻量化的数据处理方式
在端侧场景下,CPU和内存资源往往比较少,在提供数据处理的能力时,要求API尽可能简单、轻便,以最少的资源占用获得最快的执行效率。同时,需要AI框架提供的库尽可能的小。所以,使用云化场景提供的数据处理机制(启动慢、资源占用大)就不是特别适用。如何在不同的场景下提供最合适的数据处理方法是AI框架面临的挑战。
典型的云侧场景与端侧场景资源对比如下:

03
MindSpore 设计思考
3.1 设计目标与思路
MindSpore的设计中,充分考虑了数据处理的高效性、灵活性以及在不同场景下的适配性。整个数据处理子系统分为以下模块:

API:数据处理过程在MindSpore中以图的形式表示,称为“数据图”。MindSpore对外提供Python API来定义数据图,内部实现图优化和图执行。
整个数据加载和预处理的流程实现为多步并行流水线(data processing pipeline),包括:
Adaptor:将上层语言(如Python)构建的数据图,转换为下层可执行的C++数据图(Execution tree)
Optimizer:数据图优化器
Runtime:运行优化后Execution tree的执行引擎
数据集算子(dataset operators):Execution tree中的某个节点,对应数据处理流水线中的一步具体操作,比如从文件夹加载训练数据的ImageFolder算子,做各种数据增强的Map算子,Repeat算子等。
数据增强算子(data augmentation operators):也可称为tensor算子,是对某个tensor变换的,比如Decode,Resize,Crop,Pad等,通常是被dataset operator中的Map算子调用。
数据增强后的结果,通过队列和前向反向计算系统相连。下面将介绍这套子系统如何达到极致的数据处理性能。
3.2 极致的处理性能
▽多段pipeline流水线

相比于业界其他框架,MindSpore采用了多段并行流水线(multi-stage parallel pipeline)的方式来构建数据处理pipeline。这种架构一方面可以更加细粒度地规划CPU等计算资源的使用,另一方面天然支持各段使用异构硬件进行流水处理,从而提高数据处理过程的吞吐量。如上图所示,每个数据集算子(inline除外)都包含一个输出Connector:由一组阻塞队列和计数器组成的保序缓冲队列。每当一个数据集算子完成一块缓存数据的处理,这个算子会将这块缓存推送到自身的输出Connector。下游的数据集算子会从上游的输出Connector里取出缓存进行后续处理。这种机制的优势包括:
(1)数据集加载、map、batch等操作以任务调度机制来驱动,每个操作的任务互相独立,上下文通过Connector来实现Pipeline;
(2)每个操作均可以实现细粒度的多线程/多进程并行加速。数据框架为用户提供调整算子线程数/多进程处理的接口,可以灵活控制各个节点的处理速度,进而实现整个数据处理Pipeline性能最优;
(3)Connector支持用户对其大小进行设置,在一定程度上可以有效的控制内存的使用率,适用于不同网络对于数据处理速度的要求。
在这种数据处理机制下,对输出数据进行保序处理是保证训练精度的关键。保序意味数据处理流水线运行时,同样顺序的原始数据输入,需要保证数据处理完成后,得到同样顺序的数据输出。MindSpore采用轮询算法来保证多个线程数据处理的有序性:
在上面的数据处理pipeline示例中,保序操作发生在下游map操作(4并发)的取出操作(单线程执行)中,其以轮询的方式取出上游队列中的数据。Connector内部有两个计数器expect_consumer_记录已经有多少个consumer从queues_中取了数据,pop_from_记录了哪个内部阻塞队列将要进行下一次取出。expect_consumer_以consumer个数取余,而pop_from_以producer个数取余。在expect_consumer_再次为0时,说明所有的local_queues_已经都处理上一批任务,然后继续下一批任务分配及处理,进而实现了上游至下游map操作的多并发保序处理。
▽数据处理与计算过程pipeline
数据pipeline会不断地进行数据处理,并把处理后的数据发送到device侧的缓存;当一个step执行结束后,会直接从device的缓存中读取下一个step的数据。

数据处理:负责将数据集处理成网络需要的输入,并传递给发送队列中,保证数据处理的高效取可;
发送队列Queue:维护数据列队,保证数据处理与网络计算过程互不影响,实现桥梁的作用;
网络计算:从发送队列中获取数据,用于迭代训练。
以上三者各司其职,相互独立,构筑整个训练过程中Pipeline。这样,只要数据队列不为空,模型训练就不会因为等待训练数据而产生瓶颈。
▽缓存技术
当数据集的size较大时,无法全部加载到memory cache,此时训练中的部分数据需要从磁盘读取,可能会遇到I/O瓶颈,增大每个epoch的cache命中率就显得尤为关键。传统的缓存管理策略采用LRU策略,没有考虑深度学习数据的读取特点:在不同的epoch之间数据是重复读取的,而在同一个epoch中随机读取。每条数据的读取概率都是相同的,因此哪个数据被缓存并不是最重要的,已经cache的数据在被使用之前不被换出更加重要。针对这个特点,我们使用了一个简单高效的缓存算法:数据一旦被缓存,就不会从cache中被换出。
在数据图优化的过程中,会根据流水线结构自动生成缓存算子,既可以缓存原始数据集,也可以缓存数据增强处理后的结果。
3.3 灵活的定制能力
整个数据处理pipeline中,用户往往需要特定的处理逻辑,这些处理逻辑有其特殊性,无法固化到框架中。因此,框架需要具备开放的能力,让用户能够定制不同的数据处理逻辑。MindSpore提供了灵活的数据集加载方式、丰富的数据处理算子、自动数据增强、数据动态Shape、数据处理Callback等机制等供开发人员在各种场景使用。
▽灵活的数据集加载方式
针对数据集种类繁多、格式与组织各异的难题,MindSpore提供了三种不同的数据集加载方式:
(1)如果用户使用常用数据集,那么可以使用MindSpore内置的API接口直接进行加载。MindSpore实现了包括CelebADataset、Cifar10Dataset、CocoDataset、ImageFolderDataset、MnistDataset、VOCDataset等数据集的C++ IO Reader加载,在保证性能的同时实现了数据集的开箱即用。
(2)用户将数据集转换为MindSpore数据格式,即MindRecord,然后通过MindSpore的API进行加载。MindRecord可以将不同的数据集格式归一化,有聚合存储、高效读取、快速编解码、灵活控制分区大小等多种优势。
(3)如果用户已经有自己数据集的Python读取类,那么可以使用MindSpore的GeneratorDataset API调用该类实现数据集加载。这种方式可以快速集成已有代码,改动最小,但因为是Python IO Reader,需要额外关注数据加载性能。
▽通过Python层自定义、C层插件的方式支持更多算子

MindSpore内置了丰富的数据处理算子。这些算子可以分为C层以及Python层,C层算子能提供较高的执行性能;Python层算子可以很方便集成第三方包完成数据处理的功能,但是性能较低,好处是易开发易使用。MindSpore支持用户扩展自定义的数据处理算子,用户可以开发C层算子代码,编译后以插件的形式注册到MindSpore的数据处理中进行调用。
▽支持自动数据增强策略
MindSpore提供了基于特定策略自动对图像进行数据增强处理的机制:通过基于概率或者回调参数的数据增强策略,可以实现算子自动选择执行,达到训练精度提升的目的。
例如对 ImageNet 数据集,自动数据增强最终搜索出的方案包含 25 个子策略组合,每个子策略包含两种变换,针对每幅图像都随机的挑选一个子策略组合,然后以一定的概率来决定是否执行子策略中的每种变换。

这些策略包括:
RandomSelectSubpolicy - 多批概率算子,随机选择其中一批执行

RandomChoice - 多个算子选择其中一个执行

RandomApply -基于某个概率执行这批算子

通过自动数据增强操作,在ImageNet数据集上可以提升1%左右的训练精度。
▽支持动态shape
MindSpore通过 per_batch_map支持用户自定义控制输出不同Shape的训练数据,满足网络需要基于不同场景调整数据Shape的诉求。

(1)用户自定义数据Shape生成逻辑udf,如:第n个step生成shape为(x,y,z,...)的数据;
(2)通过batch(…, per_batch_map=udf)将第一步定义的逻辑生效,最终得到不同Shape训练数据。
▽Callback机制让数据处理更加灵活
通过callback机制实现根据训练结果动态调整数据增强的逻辑,为数据增强过程提供更灵活的操作。

MindSpore支持用户基于数据处理提供的DSCallback(包含epoch开始、step开始、step结束、epoch结束等)实现自己的数据增强逻辑UDF,并将其添加至map操作中,以实现更灵活的数据增强操作。
3.4 端云统一架构
▽数据图与计算图的统一
MindIR是MindSpore基于图表示的函数式IR,其最核心的目的是服务于自动微分变换。自动微分采用的是基于函数式编程框架的变换方法,因此IR采用了接近于ANF函数式的语义。
推理数据图典型的场景为:数据集样本大小缩放、中间截图、归一化、通道变换。

我们将推理数据图以子图的方式保存至生成的模型文件(MindIR)中,那么在推理时,可以通过统一的接口加载模型中数据处理流程,自动进行数据处理得到模型需要的输入数据,简化用户的操作,提升易用性。

▽轻量化的数据处理
云侧训练时,可以被使用的资源往往比较充裕,数据处理Pipeline在运行过程中是会占用比较多系统资源(CPU和内存),以ImageNet为例,训练过程中CPU占用20%,内存占用30-50G,这显然在端侧是不可被接收的,并且数据处理Pipeline在初始化时启动会慢些,这也不适用于端侧需要快速启动、多次训练/推理的前提条件。故:MindSpore基于现有数据处理算子,提供一套更轻量化、更适用于端侧的API,解决云化场景数据处理Pipeline不适用于端侧的问题。

MindSpore基于Pipeline调整架构,支持数据处理单算子独立使用(Eager Mode),支持各种场景推理,提供给AI开发人员更大的灵活性;同时,将Pipeline轻量化,实现基于Pull Base的轻量化pipeline,减少资源占用并且处理速度快。
通过上述两种方法,MindSpore保证了统一的数据处理架构支撑多种不同的应用场景。
04
未来计划
在未来,MindSpore将继续完善数据处理的易用性,提供更丰富的算子和内置数据集。与此同时,探索大规模数据处理的加速技术,包括:
资源自适应分配
当前各数据增强算子使用的处理线程数目由用户手工配置,对用户的调优经验要求极高。通过自适应判断Pipeline瓶颈,由框架给各个数据增强算子合理分配CPU资源,可以在训练过程中动态优化数据处理性能,免去用户繁琐的调优过程。
异构硬件加速
当前的数据处理Pipeline操作在CPU执行,一旦出现瓶颈,带来AI芯片/GPU等待空闲,用户无法充分利用所有硬件的计算能力。MindSpore期望构建用户无感知的异构硬件资源调度能力:通过监测硬件资源使用,完善Ascend/GPU上的数据处理算子,采用代价模型自适应地将数据处理任务调度至合适的资源,实现异构硬件的充分利用。
分布式缓存
当前如GPT-3等网络的训练需要使用超大规模数据集,这些数据难以在本地存储,直接从OBS读取会受网络IO限制而影响性能。与此同时,在AutoML场景下,用户经常在集群中运行同一类模型的多个作业(只是超参设置不同),每个作业独立进行数据加载和处理效率极低。MindSpore期望构建分布式缓存能力,加速这些场景下的数据处理。

MindSpore官方资料
官方QQ群 : 486831414
官网:https://www.mindspore.cn/
Gitee : https : //gitee.com/mindspore/mindspore
GitHub : https://github.com/mindspore-ai/mindspore
论坛:https://bbs.huaweicloud.com/forum/forum-1076-1.html
边栏推荐
猜你喜欢

RestClient操作索引库-初始化RestClient

@Transactional transaction methods contain multiple transaction methods of the same kind. These transaction methods themselves are set to fail. There are two solutions

The boss asked me to do an IP territorial function and an open source library!

SLAAC 无状态地址自动配置

matlab simulink 磷酸铁锂电池仿真

MPLS VPN 跨域-optionB
![[original dry goods] found a useful tool for data analysis](/img/18/da21520efa77f29d3c2b4890db158d.png)
[original dry goods] found a useful tool for data analysis

matlab声音信号处理 频率图 信号过滤和播放声音
![[record of question brushing] 18. Sum of four numbers](/img/51/1be89efe609572a8b71f2f7c386711.png)
[record of question brushing] 18. Sum of four numbers

Amazon's zoox passed the safety test and applied for a test drive in California
随机推荐
Three effective strategies for driving page performance optimization
Dispersion tensor analysis open source software DSI studio simplified Chinese version can be downloaded
php数组下标是不是只能从0开始
networkx 对图进行可视化
Qt+vtk+pcl pictures are converted to grayscale images and displayed with grayscale as the Y axis
Can PHP array subscripts only start from 0
scala idea提示函数参数
实验三 LZW
php可不可以拆分数组
2022年中国软件产品全国巡回展即将启航
二冲程发动机均值模型仿真
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat
21 -- product of arrays other than itself
大咖訪談 | 開源社區裏各種奇怪的現狀——夜天之書陳梓立tison
Experiment 5 JPEG
使用Hystrix实现容错处理
Can PHP split arrays
[day 31] given an integer n, find the base and exponent of each prime factor | basic theorem of arithmetic
Expérience II Yuv
Mysql A left(right) join B on A.id=B. ID and a.age=1 and a left (right) join b on a.id=b id where A.age=1