一旦我们成功地将数据加载(或提取)到一个有效的特征存储系统中,大多数数据科学家或建模师会通过一系列常见的操作,使数据转换为能够进行训练的数据。这些操作(验证、清洗和确保数据一致性,以及丰富和扩展)将在接下来的内容中详述。
验证
无论我们的机器学习模型有多高效强大,它们都无法根据糟糕的数据完成预测。在生产中,数据出错的一个常见原因是最开始收集数据的代码存在错误。即使每个数据源都有一个定义好的模式,从外部提取的数据仍可能会有很多错误(例如,整型字段有一个浮点值)。因此,验证传入的数据是非常重要的,特别是当有一个确定模式或有能力与最后已知的有效数据进行比较时。
验证是根据字段的通用定义来进行的——它是否是我们期望的那样?为了进行这种验证,我们需要预先存储并能够引用这些标准的定义。使用一个全面的元数据系统来管理字段的一致性并跟踪定义,对于保持数据的准确性至关重要。这一话题将在第4章进行详细介绍。
清洗和确保数据一致性
即使有一个全面的验证框架,大多数数据仍然是混乱的。可能有缺失的字段、重复的数据以及错误的分类,甚至是编码错误。我们拥有的数据越多,数据清洗与保持数据一致性就越有可能成为处理工作的重点。
这可能看起来很令人沮丧且没有必要:建立整个系统只是为了检查数据,对许多第一次这样做的人来说,听起来有点夸张了。但现实情况是,我们的机器学习管道肯定会有用于清洗数据的代码。我们可以把这些代码与其他代码分隔开来,在那里它可以被审查并加以改进,或者把它的各个方面放在整个训练管道中。第二种策略使管道变得非常脆弱,因为随着对数据正确性的假设越来越多,我们确保满足这些假设的能力却没有提升。此外,当我们改进一些用于验证和改正数据的代码时,我们可能忽略了在其他正在进行这项工作的地方实施这些改进。或者更糟的是,我们可能会适得其反。例如,我们可能多次“改正”相同的数据,导致数据中的原始信息被消除。也可能存在潜在的竞态条件,即流程的不同部分会以不同的方式清洗数据或保证数据一致性。
在这一环节,另一组数据一致性的任务是数据的归一化。 归一化 一般指的是一组用于将输入数据转换为同样尺度的技术,这对于像深度学习这样依赖梯度下降或类似数值优化方法进行训练的算法是非常有用的。关于归一化的一些标准技术如图2-4所示,主要包括:
缩放到一个范围
将数据的所有 X 值映射到一个固定范围,通常是0到1,但有时(对于像身高或年龄这样的东西)会有其他值来表示常见的最大、最小值。
裁剪
除去数据的极端值。当数据集有少量的极端值时,这种方法很有效。
对数缩放
x '=log( x )。当数据符合幂次分布时,会有少量非常大的数值和大量非常小的数值,这种方法很有用。
Z值标准化
将变量映射为平均值的标准差的个数。
值得注意的是,如果这些技术中的任何取值范围、分布或平均值是在一组测试数据上计算的,而这些数据的属性与后来应用的数据集不同,那么这些方法会造成风险。
最后一个常见的相关技术是将数据放入 储存桶 中:我们将一定范围内的数据映射到一个更小的代表相同范围的组中。例如,我们可以用年来衡量年龄,但在训练时,我们可以把数据放在按10年分开的桶里,这样,所有30到39岁的人都被放入“30岁”的桶里。但分桶可能是许多难以察觉的错误的来源。例如,想象一下,一个系统以10年为界限对年龄进行分类,另一个系统以5年为界限进行分类。当我们对数据进行分桶时,必须认真考虑将现有的数据保存,并将每条数据转换为一个新的、格式正确的数据。如果(什么时候?)我们改变了分桶策略,这样做会很棒;否则,就不能转换。
丰富和扩展
在这个阶段,我们会将自己的数据与其他来源的数据相结合。扩展数据的最常见和最基本的方式是 打标签 。这个过程通过引入外部数据源(有时是人工参与)的信息来识别一个特定的事件或记录。带标签的数据是所有监督式机器学习的关键驱动力,而且往往是整个机器学习过程中最具挑战性和最昂贵的部分之一。如果没有足够数量的高质量标签数据,监督学习就不会成功。(标签和标签系统将在第4章详细介绍。)
图2-4:“Google Developers Data Prep”课程中介绍的归一化技术( https://oreil.ly/0cgBm )
但打标签只是扩展数据的一种方式。我们可能会使用许多外部数据源来扩展我们的训练数据。比方说,出于某种原因我们相信根据人们所在地的温度能预测他们将买什么
。我们可以利用
yarnit.ai
网站上的搜索日志,添加用户在访问网页时的大致地理位置的温度。这可以通过创建或找一个记录历史温度的服务或数据集来达成。这会使我们能够将搜索所在地的温度作为一个特征来训练一个模型,看看我们能用它做出什么样的预测。这有可能是一个糟糕的想法,但并不是完全不切实际的。