在实现以深度学习为主的人工智能任务的过程中,有三大基本要素是缺一不可的,那就是算力、算法、数据(点击查看:实现人工智能的三要素)。
其中算力的大小和硬件直接相关,比如GPU、DPU、NPU、TPU等等(点击查看:CPU、GPU、DPU、TPU、NPU...傻傻分不清楚?实力扫盲——安排)。
而算法的优劣基本都是和网络模型结构、激活函数、损失函数、优化函数等相关,工业界常用的算法基本都是开源的,除非一些特殊任务需要专用的算法来实现,其他大部分任务都是基于开源算法而实现的。
在算力和算法都基本已经确定的前提下,数据在实现一般的深度学习任务的过程中,可以说起到了决定性的作用,可以认为数据对深度学习任务最终效果的影响,其下限很低、上限很高,也就是说,如果数据质量有问题,可以让一个好的模型变宝为废,而如果数据的质量非常高的话,也可以使得一个平庸的算法模型发挥出超常的效果。
近几年,随着硬件算力设备和算法模型逐渐在标准化、模块化发展的趋势下,数据成为了最不可控的变量。从算力、算法、数据三大基本要素来看,算力是最容易作为标准化来衡量的,而且通用性最高,可以在任何深度学习任务中都能够使用,比如使用Tesla V100可以做一般的检测分类任务、分割任务、生成任务,也可以做普通的语言模型任务、强化学习模型任务等。
其次是算法,算法虽然没有像算力一样有那么高的标准化发展,但是常用的算法模型也基本能够解决大部分相似的任务,比如做检测识别的YOLO系列、做图像分割的UNet系列、做图像生成的GAN系列、做语言生成模型的GPT系列等等,这些算法模型不会随着具体的任务数据变化而变化,比如对动物进行分类和对植物进行分类,都可以使用YOLO模型。
数据作为三者之中不容易用标准化的元素来说,其不可控的原因主要是由于不同的任务要使用不同的数据集,所以很难对数据做到真正的标准化和模块化,无法像算法模型一样直接对其调用。在学术界,真正通用的数据就那么几个,比如COCO数据集,VOC数据集,ImageNet数据集,都是用来发表论文时使用的,在工业界,大多数任务都是指定的数据,无法直接使用这类数据集的,最多也就是使用其数据作为预训练的模型。比如很多知名的神经网络模型,像早期的ResNet,后来的Efficientnet,以及YOLO系列近期发出的最强的版本YOLOX,都是在COCO数据集上作比较。而工业界都是根据各自的任务来选取或者采集相关的数据的。
数据对于深度学习任务结果的影响,主要体现在数据的数量和质量,数据的数量比较容易理解,简单来说就是加大数据量。而要把控数据的质量就比较复杂了,因为在整个数据的处理过程当中,每一个环节都有可能会对数据的质量造成影响,而数据上轻微的影响有可能会造成最终结果上的差距。连全球人工智能著名学者吴恩达都说人工智能=80%数据+20%算法。
在人工智能项目的研发过程中,基本上80%的工作量都花在了数据处理上。
一般来说,数据处理(data processing)是对数据的采集、存储、查找、加工、变换和传输。根据处理设备的结构方式、工作方式,以及数据的时间空间分布方式的不同,数据处理有不同的方式。不同的处理方式要求不同的处理工具。每种处理方式都有自己的特点,应当根据应用问题的实际环境选择合适的处理方式。
数据处理的基本目的是从大量的、可能是杂乱无章的、难以理解的数据中抽取并推导出对于某些特定的人们来说是有价值、有意义的数据。
数据处理是系统工程和自动控制的基本环节。数据处理贯穿于社会生产和社会生活的各个领域。数据处理技术的发展及其应用的广度和深度,极大地影响了人类社会发展的进程。
现实生活中很多原始数据都是杂乱的、非结构化的数据,无法直接拿来使用,需要按照使用要求对原始数据进行一定的处理,比如删除无用信息、对数据结构重新排列组合、对不同的数据指定对应标签、增强或减弱某些数据的特征,甚至从头开始采集或生成一些需要的数据。
利用好非标注数据或者数据标注自动化是降低成本和时间的有效思路。
在以深度学习为主的人工智能应用中,数据处理几乎贯穿了模型的训练和使用过程,在模型的训练开始前,需要对原始数据进行一定的处理,一方面要去除原始数据中重复的数据和错误的数据,另一方面也要让数据的形状和类型能够适应模型的输入格式;
在训练过程中,需要对模型每一层输出的特征数据都要进行标准化处理,让其保持在一定的量纲范围内,从而来保持模型良好的梯度和收敛性;
在模型使用的过程中,需要对输入的数据进行预处理,比如对图像数据去噪、直方图均衡化等操作(点击查看:CV任务中如何解决图像光照度不均匀的问题),让其噪声能够降得更低,光照色彩等更均匀,更好的适应模型的特征预测。
有的时候,当原始数据不够丰富的时候,还需要对原始数据进行增强处理,也就是换一种方式来增加数据的数量和多样性,能够让模型学习更多的数据特征,比如对数据随机裁剪、偏移、缩放、旋转、扭曲,以及光照色彩等方面的变化,甚至还会对图像增加一些噪声、遮挡等操作,其目的都是为了增加数据的数量和多样性。
在以深度学习为主的人工智能任务流程中,一开始要做的就是数据的处理,因为有了数据,网络模型才能够训练,数据处理的步骤主要有以下几个环节:
要做数据的采集,首先要明白什么是数据。按照标准的解释,数据(data)是事实或观察的结果,是对客观事物的逻辑归纳,是用于表示客观事物的未经加工的原始素材。
数据可以是连续的值,比如声音、图像,称为模拟数据;也可以是离散的,如符号、文字,称为数字数据。
在计算机科学中,数据是指所有能输入计算机并被计算机程序处理的符号的介质的总称,是用于输入电子计算机进行处理,具有一定意义的数字、字母、符号和模拟量等的通称。计算机存储和处理的对象十分广泛,表示这些对象的数据也随之变得越来越复杂。
在深度学习中所使用的数据,其本身是存在于现实世界的,是杂乱的、随机的、数量是无法确定的,因为现实世界中无时无刻都在产生各种不同的新数据。而我们要使用的数据一般是结构化的、有规律的、确定数量的数据,所以一般数据采集就是从现实世界的数据中进行采样,这一过程就是完成从现实世界把数据转移到我们当前任务环境中的过程,值得注意的是,在采样过程中,要保证采样的数据分布规律和现实世界中的数据分布规律一样,因为只有这样,采样得到的数据在一定程度上才能能够代替现实世界中的数据。
采集数据的终极目标是为了让网络模型训练数据,获取数据中的特征,能够对具有同类目标的图像数据进行预测。所以实际要采集什么样的数据,要看所对应的任务是什么,比如要解决的任务是猫狗分类,那么采集的数据就是带有猫和狗的图像数据,采集了带有猫狗的图像数据后,就可以训练模型,训练结束后,该模型就具有了预测猫和狗的能力。
由于现实环境是变化的,所以采集数据要适应环境的变化,比如要采集不同季节中的户外环境中的数据、同一天中不同时间点的数据,同一目标出现在不同地点的数据,总之要适应光照变化、颜色变化、对比度变化、几何形状变化、遮挡变化等因素。所采集数据的环境越丰富,说明采集到的数据越接近于现实环境,训练出的模型对现实环境的数据模拟泛化性能也越好。
数据的采集方法有很多,其中主要的采集方法有人工收集、系统采集、网络爬取、虚拟仿真、对抗生成、开源数据等。
人工收集就是让相关工作人员到实际的生产环境中去采集,比如拍摄图像视频数据、截取信号数据等;系统采集是指某些专业的数据采集,其本身的主要功能就是在各种环境下采集并保存上传数据,这样就可以避免人工采取了;网络爬取就是使用网络爬虫工具爬取网络上的数据,一般来说网络上的数据噪声较大,爬取后还需要人工检查一遍;虚拟仿真是指在虚拟的工作环境中生成所需的数据,比如车牌生成器就是一个虚拟仿真工具;对抗生成是使用生成式对抗神经网络(GAN)来生成数据;开源数据一般是学术研究机构或者一些AI大企业收集后开放出来的数据,我们一般在学习期间所使用的一些数据基本都是开源数据,比如MNIST数据集、COCO数据集、VOC数据集等。
数据采集的操作相对来说也比较简单,但是要遵循一个原则,那就是采集的数据样本要能体现整体数据样本的分布规律,所以要科学采样,防止数据不均衡。
虽然前面说了采集数据的终极目标是训练数据获取特征,但是在这之间还是相隔了很多步骤的,其中之一就是数据标注。为什么要对数据进行标注呢?不标注的数据能不能参与训练呢?这个答案不是一定的。
一般来说在监督学习中, 数据一定要被标注才能参与训练,因为监督学习的定义是数据和标签是一对一的,也就是说,有一张猫的图片,那么就要定义一个猫的标签,告诉模型这是一只猫。
而在半监督学习中,数据不必和标签一一对应,数据中只要有部分标签即可,其他无标签的数据在学习过程中向以往学习到的数据特征来靠近,特征和以往学习到的数据的特征接近的,被认为属于同一标签下的数据。这就好比人只认识一部分品种的狗,但是遇到以前没有见过的狗种,也基本不会认错,大概率还是会判断这是一只狗,而非猫。
在无监督学习下,数据一般来说,数据不需要标签就可以直接参与训练,但是在深度学习任务中,模型的学习都是依赖于损失函数来定义误差,再通过误差进行反向传播梯度而更新参数的,所以损失函数的结果一般就是模型的输出和标签之间的误差,那么对无监督学习的损失该如何定义?
其实对于无监督学习方法,主要是说的没有人为的特意去标注标签,并不代表没有天然的标签,比如检测和识别图像中的一只狗,就需要人为的定义图像中狗的位置和类别,而在自编码模型中,就不需要认为的定义任何标签,因为模型学习的目标就是图像本身,而非图像中的目标位置和类别,比如生成数字的案例中,输入是一张数字图像,最终模型输出是经过一定方差扰动的数字图像,本质上还是数字本身,这就和一个人写了两个数字5一样,都是5,但是字体形状的细微程度不一样。在这种自编码模型中,损失函数的值就是模型的输出图像和输入图像。
数据标注的工作一般是借助标注工具来完成的,其中图像视频数据的标注工具又占了大部分,常用的图像视频标注工具有labelme、labelbox、labelimg、精灵标注助手等工具,值得一提的是精灵标注助手是一款非常强大的免费标注工具,标注类型涵盖了图像数据、视频数据、语音数据、文本数据、3D点云数据,而且适应目前主流的操作系统。
数据标注的类型包括了图像数据标注、视频数据标注、语音数据标注、文本数据标注、3D点云数据标注。标注的方式有人工标注、半自动标注、自动标注、众包等。具体选用哪种方式标注数据,要看数据量和数据的类型,有些通用数据是开源采样自动标注方法的,比如使用训练好的人脸检测模型来标注人脸框的位置,而有些特殊数据只能使用人工标注的方法。
数据增样一般也称为数据增强,如果数据在采样过程中就已经包括了各种复杂环境下的数据,那么可以不用进行数据增强,但是现实情况是,我们大部分数据都是不够完善的,也就是不足以表达真实环境中的数据分布情况,这个时候重新采集数据又比较困难,于是就有了数据增强,所以数据增强的本质原因是由于原始数据无论是从数量还是质量上来说都不够丰富。
值得说明的是,无论我们采集到的数据有多丰富,大部分模型在做了数据增强后,在最终的效果上还是有很大的提升的,这是因为数据增强的方法中经常会加入一些极端情况下的数据,而这种极端情况下的数据在现实环境中一般很难采集得到。但是也有一些小模型在做了扰动过大的数据增强后,在最终识别效果反而会下降,这一点在YOLOX中就有体现。这是因为小模型对于复杂数据处理的能力并不强,增加了数据的复杂度反而会扰乱模型原来的梯度策略,这就好比对于一个认知并不高的人讲一些过于高深的理论,最终可能会让其现有的认知崩塌。
数据增强方法一般分为光照变换、几何变换、遮挡变换、混合变换等。
其中光照变换包括了随机亮度变换、对比度变换、色彩度变换、饱和度变换、噪声变换。
几何变换包括了随机缩放、裁剪、翻转、旋转、平移等变换。
遮挡变换包括了图像马赛克、随机图块删除等。主要方法有以下几种:Random erase
(随机删除,在图上随机遮挡某一部分的像素)、Cutout(裁剪,按照一定的间隔遮挡N*N像素大小的小格子,是具有规律的,一般是等距间隔的小格子,N一般取2或4很小的值,类似于给图片加噪声)、hide and seek(裁剪,按照更大的间隔遮挡N*N像素大小的小格子,是具有规律的,一般是等距间隔的小格子,N一般取值更大一些)、Grid Mask
(网格掩码,是有策略的遮挡,而非随机遮挡,采用的方法是先把图像进行分成不同的格子,然后按照一定的方法去挑选遮挡某些格子。遮挡的效果取决于格子的大小和被遮挡的格子数量。类似于增加正样本的权重)、Dropblock(对图像数据使用dropout,然后再将多个dropout之间连成块,以此达到遮挡的目的)。
混合变换主要是指图像融合操作,一般是将两张不同的图像融合成一张图像,以此来增加数据的多样性。
也可以通过分割模型background matting来替换图像背景完成数据增样的目的。
数据清洗,顾名思义,就是清洗掉无用的噪声数据,留下有效的数据。那么我们的主要工作就是如何区分噪声数据和有效数据,在数据世界中,有一个常识必须要搞清楚,那就是无论任何数据,都包括了有效数据和噪声数据,只是有的数据中的有效数据多,有的数据中的噪声数据多。
所以要明白真实数据≠理想数据,理想数据=有效数据,而真实数据=有效数据+噪声数据,噪声数据就是影响最终结果的冗余数据,数据清洗的目的就是清洗掉这部分数据。
数据清洗方法主要有数据去噪、脱敏、缺失处理、查重、删除错误数据等。
其中删除错误数据可以通过代码工具来实现,也可以人工实现,无论是数据本身选择错误,还是标签标注错误,都可以通过工具或人工的方法删除错误数据,或者重新标注。一般来说,如果被清洗的数据本身是比较常见的数据,比如人脸数据或者常见物体数据,可以使用现有的成熟模型直接预测判断删选,如果是不常见的数据,就需要人工删选数据了。
数据查重是指数据集中存在着同一条数据,比如同一张图像,同一条文本、语音等。对于数据的查重,其方法相对来说比较简单,最简单的方法就是统计一下每条数据的均值方差,如果有均值方差相同的数据,就认为是同一条数据,可以直接删除。
数据的缺失处理是指在某些缺失的数据中补全缺失的部分,一般对于缺失数据的补全,可以使用插值的方法来补全,具体插值方法有临近插值、中值插值、均值插值、众数插值、最大最小值插值等,具体方法根据实际任务而定,除了插值方法来补全数据,还可以通过生成模型来生成新的数据来补全数据,比如对于图像缺失部分的补全,使用生成模型也是比较好的选择。除了插值补全方法,还有最小二乘法补全方法,这是基于最小二乘法的原理,补全数据,使补全后的数据整体的离差平方和最小,这一般是方差分析中处理缺失值的一般方法。也有基于REML的方法估计,REML混线性模型本身可以处理非平衡数据,它也可以作为估计缺失值的一种,它估计出来的缺失值比最小二乘法要准确,应用比较广泛。
数据脱敏是指将原数据中对模型训练无用的某些敏感的信息去除,从而能够安全的让训练人员的使用数据,比如医疗数据中的患者的信息就属于敏感信息,而这部分敏感信息又对模型的训练没有任何帮助,就可以去除这部分数据信息,从而让更多的人能够使用数据。
数据去噪是数据清洗过程中最复杂的一项,其主要因素就是如何定义噪声,也就是如何区分模型真正需要数据信息和其他冗余信息。一般来说,广义上的数据去噪就是数据清洗,对于错误数据、缺失数据、重复数据等都可以看作是噪声数据。我们这里所说的数据去噪是狭义的概念,也就是真正的数据噪点,比如高斯噪声、椒盐噪声等,对于这类数据的噪声,一般是平滑滤波去除掉噪声部分,一般噪声部分的梯度要高于其他部分的梯度,去除了噪声,在模型的预测过程中,会让预测精度又更高的提升。
一般在深度学习任务中,在模型训练阶段,我们对于一些非常干净的数据,经常通过增加噪声的方法来增强数据的多样性,这是因为在模型实际的使用过程中,我们获取的真实数据不会太过于理想化,也就是不可能太过于干净,经常会包括各种噪声,所以在模型训练期间增加噪声是为了让模型的泛化性能更好,在模型预测使用期间,对输入数据去噪是为了让真实数据的噪声更小,从而让模型能更好的拟合数据。
数据标准化就是统一数据的量纲,让不同维度的数据都能够适应某一规则的约束。比如在预测某一地区的房价的时候,模型输入的数据是房子的面积和房子的房间数量,输出是对房子预测的价格。我们会发现输入的房子面积范围可选择性很大,基本从10㎡到1000㎡都可以,而房子的房间数量范围一般不会太大,比如是1-20间左右。
如果我们直接把这些数据输入模型会发现,面积的数据取值范围过大,而房间数量的数据取值范围太小,到最后模型学习到关于房间个数的权重要比房子面积的权重更大,会让模型优先拟合房间个数的特征,而实际上我们在训练模型的时候对这两者之间并没有分配各自的权重比例,也就是二者应该是同等的。
这个时候我们就需要将面积数据和房间数量的数据统一在同一量纲下,这个量纲大家可以理解为衡量物体的单位,但并不是所有量纲都是基本有单位的,比如上例子中的㎡、间数就是基本单位,而表示速度的m/s就不是基本单位,是有m和s两个基本单位组成的组合单位或者叫导出单位。
数据标准化后,不仅能够更好统一表达各种不同量纲下的数据,还能消除奇异数据,减小数据中的离群点对模型训练的影响;也能让模型的收敛更加稳定。
数据标准化不只是发生在数据出入网络模型之前,更多的是在网络模型中对数据进行标准化操作。一般来说在数据输入网络模型之前,对数据进行标准化处理是为了统一原始数据的量纲,减小异常数据对于模型训练的影响,更好的获取数据中有效的特征。
在网络模型训练过程中,对网络层中的特征数据进行标准化是为了防止模型在训练过程中出现梯度爆炸、梯度弥散等情况的发生,也能在一定程度上防止模型的过拟合。在训练过程中做了数据标准化后还会加快模型的训练速度。
神经网络学习过程的本质就是为了学习数据分布,如果我们没有做归一化处理,那么每一批次训练数据的分布不一样,从大的方向上看,神经网络则需要在这多个分布中找到平衡点,从小的方向上看,由于每层网络输入数据分布在不断变化,这也会导致每层网络在找平衡点,显然,神经网络就很难收敛了。
如果我们只是对输入的数据进行归一化处理(比如将输入的图像除以255,将其归到0到1之间),只能保证输入层数据分布是一样的,并不能保证每层网络输入数据分布是一样的,所以也需要在神经网络的中间层加入归一化处理。
根据损失函数(out-y)² 来看,如果想要损失下降的更快,最好将输出和标签数据处理到一定范围内会更好。所以,这样就形成了数据从输入之前要做标准化,以及网络中间层做标准化,一直到输出时根据标签限制输出范围。就形成了一个完整的标准化流程。输出的标准化范围应该和标签的标准化范围一致。
在数据的标准化方法中,常用的有Batch Norm、Layer Norm、Instance Norm、Group Norm
除此以外还有不太常用的Switchable Normalization、Filter Response Normalization
关于各种数据标准化的具体过程不再赘述,后期我们会发布专门针对数据标准化处理的文章,来详细介绍各种数据标准化的过程细节。
按照深度学习任务的项目流程,我们一般会将数据划分为训练阶段使用的训练集、验证阶段的验证集、测试阶段的测试集。
一般在拿到处理过的数据后,会对数据进行切分,按照模型训练和使用的流程,我们一般会按照训练集、验证集、测试集的需求将数据分割为6:2:2到8:1:1之间的比例,根据具体需求也会有其他比例的分割,各类数据之间是没有交集的,分割的目的是为了更好利用数据,让模型能够学习到更多的数据特征,同时又能验证模型的性能,测试模型在实际环境中使用情况。
训练集一般是需要经过模型反向传播算法更新梯度来学习数据特征的,而验证集只需要经过前向模型输出结果即可,目的就是验证训练的结果是否达标,而测试集就是就是在模型经过验证合格后再进行的最后测试。这就好比我们平时上课学习知识就是在训练我们自己,而课后作业和阶段测试就相当于验证平时学习的成果,期末考试就是最终测试一样,需要拿出最后的结果。
如果参与训练的数据本来就少,可以采用交叉验证的方法。交叉验证,顾名思义就是把训练数据和验证数据交叉使用,从而来提高数据的利用率。比如将数据切割成10份,让模型训练十次,第一次训练时先拿出前9份参与训练,第10份用来验证,获得一个验证分数;第二次训练拿出前8份和第10份来参与训练,第9份用来验证,获得第二个验证分数,以此类推,在训练集和验证集数据不重合的前提下,所有数据都能参与训练和验证,从而获取10次验证的分数,最后将获取的10次验证分数做平均,拿到最终的验证分数,这样在利用小数据的情况下也能做到比较精准的验证分数。
后记:数据处理在实现人工智能的过程当中越来越重要,一个好的AI应用,除了硬件的优势和算法的优势之外,剩下的就是看数据对于AI模型应用的影响了,无论是比赛项目,还是发表论文,亦或者是实际工程项目,将数据的优势发挥到最大,都将是最终角逐的挑战之一。随着人工智能的发展,数据的处理也将从人工处理逐步发展到半自动处理,甚至完全由AI自动处理的过程,但是在短期内,对于数据的处理还都是将由人工来完成的。
本文内容由深度人工智能公众号原创提供,转载或摘录请联系作者注明来源!
深度人工智能是成都深度智谷科技旗下的教育信息平台,我们会为人工智能学习者呈现最实用的干货技能,也会为人工智能从业者考取人工智能相关的证书提供报考服务,有意者可以联系我们。
中国人工智能学会部分证书样本:
工信部人工智能证书样本:
文中所使用的部分图片来自网络素材,如果有侵权,请第一时间联系我们删除!