为机器学习准备数据
在创建机器学习模型之前,需要准备用于训练和评估的数据。 数据从源引入 Azure Databricks,通常是以数据文件的形式。 或者,可以根据数据文件创建增量表,以简化数据浏览和分析。 引入数据后,数据科学家会为机器学习准备好数据。
通常,准备数据涉及两个关键任务:
- 数据清理:识别并缓解数据中会影响其对机器学习有用性的问题。
- 特征工程和预处理:为模型训练选择和转换合适的特征。
数据清理
清理数据所需的具体步骤因项目而异,但需要解决的典型问题包括:
- 数据不完整:数据通常包括个别字段缺失的记录(通常以 NULL 值的出现为标志)。 需要识别缺失值并通过以下方法进行缓解:
- 用合适的替换值来替换它们 - 通过在序列中内插一个值、使用平均值(或中值),或者创建一些其他适当的值。
- 完全删除不完整的行(假设这为建模留下了足够合适的代表性数据)
- 错误:数据包含错误的情况并不少见,这是由于数据输入错误或上游数据处理失败导致的。 查找错误可能很困难,通常涉及使用查询和可视化效果对数据进行大量检查,以汇总数据并查找与给定字段中的大多数其他值不一致的值。
- 离群值:离群值是明显超出(高于或低于)数据统计分布的值。 有时离群值指示错误(例如,有人的值多了一个零或省略了一个小数点),有时它们是真正的值,与大多数观察值相比,它们异常地高或低。 无论是哪种情况,极端的离群值都可能会对机器学习模型的训练产生负面影响;因此,通常最好的处理方式是将它们重置为上限或下限阈值,或者从数据集中删除包含离群值的记录。
- 数据类型不正确:机器学习算法对分配给特征值的数据类型很敏感。 基于包含错误或 null 值的文本文件的数据集通常会错误地将数值字段转换为字符串数据类型,并且表示离散整数值的值通常可能会错误地转换为十进制数(反之亦然)。 应检查数据的架构,并分配最能有效地反映数据值的适当数据类型。
- 数据不均衡:如果训练数据对可能遇到的所有不同特征和标签组合具有足够的表示形式,机器学习的训练效果会达到最佳。 在不均衡的数据集中,包含特定分类值或字段组合的记录会被过度表示;这可能会影响训练算法,并在模型中引入偏差。 缓解此问题的一种常见方法是,通过包含的重复行对表示不足的值进行过采样,或对过度表示的行进行欠采样(从数据集中删除它们)。
在 Azure Databricks 上,检测和处理这类问题的最常见方法是在浏览和操作数据的笔记本中编写代码。 用于此类数据操作的主要类是 Spark 数据帧。
例如,以下代码将数据从文本文件加载到数据帧中:
df = spark.read.format("csv").option("header", "true").load("/myfolder/mydata.csv")
或者,如果数据已加载到 Azure Databricks 工作区中的增量表中,可以使用 SQL 查询将其数据加载到数据帧中:
df = spark.sql("SELECT * FROM mytable")
将数据加载到数据帧后,可以使用它的方法以及 Spark SQL 库中的其他函数来浏览和转换数据。 例如,以下代码使用 dropna 方法删除了包含 null 值的任何行,并将特定数据类型分配给数据帧中的列。
clean_data = df.dropna().select(col("column1").astype("string"),
col("column2").astype("float"))
提示
有关 Spark 数据帧功能的详细信息,请参阅 Spark 数据帧文档。
特征工程和预处理
确保数据集完整且干净后,可以开始为机器学习准备特征。 特征工程是一种迭代方法,通常涉及一些试验和错误,以确定哪些特征列具有预测价值,以及如何最好地表示特征。 常见的特征工程和预处理任务包括:
派生新特征:通常可以从现有特征派生新的、更具预测性的特征。 例如,假设一个数据集包含一个日期列,并且你怀疑完整的日期可能不是标识标签的一个重要预测因素,但星期几可能是。 可以创建一个由日期衍生出来的新 day_of_week 特征,并测试你的理论。
离散化数值特征:在某些情况下,当数值离散化为表示特定值范围的类别时,数值可能更具预测性。 例如,可以采用价格特征中的数值,并根据适当的阈值将它们分配到低、中、高三个类别。
编码分类特征:许多数据集包括由字符串值表示的分类数据。 但是,大多数机器学习算法对数字数据的效果最好。 因此,通常分配数字代码来表示类别,而不是字符串。 例如,产品详细信息数据集可能包含值为“绿色”、“红色”或“蓝色”的颜色特征。 可以使用简单的整数代码对这些值进行编码,例如 0 表示“绿色”,1 表示“红色”,2 表示“蓝色”。 或者,可以使用独热编码技术,为每个可能的类别创建一个新列,并根据每一行的情况为每一列分配值 1 或 0,如下所示:
原始颜色列 绿色 Red 蓝色 绿色 1 0 0 蓝色 0 0 1 Red 0 1 0 缩放(规范化)数值:数值数据值通常采用彼此不同的标度或度量单位。 机器学习算法会将它们全部作为绝对数值处理,值较大的特征通常会主导模型训练。 若要解决此问题,通常会缩放所有数值列,使单个列的各个值彼此保持相同的比例关系,但所有数值列都采用相似的标度。 例如,假设数据集包含以米和公斤为单位的长度和权重值。 可以将这两个特征转换为一个介于 0 和 1 之间的缩放值,如下所示:
length 重量 scaled_length scaled_weight 250.0 2.1 0.250 0.210 176.0 0.9 0.176 0.09
许多机器学习库包括可用于执行常见特征工程任务的类。 例如,Spark MLlib 库包含 StringIndexer 类,可用于对字符串值执行基于整数的简单编码。
from pyspark.ml.feature import StringIndexer
encoder = StringIndexer(inputCol="catCol", outputCol="catColCode")
encoded_data = encoder.fit(data).transform(data)
注意
这里值得更详细地解释一下 StringIndexer 代码示例。 Spark MLlib 类可以包含将特定转换操作的算法拟合到某些样本数据的计算器。 在这种情况下,StringIndexer 将编码算法拟合到“数据”数据帧中 catCol 列中的离散字符串值,以确定生成包含编码值的新 catColCode 列所需的具体计算。 计算器的输出是用来封装由计算器定义的函数的转换器,它可以将函数应用于数据,并生成新的数据帧。 在本示例中,我们将用于确定编码函数的相同数据传递给生成的转换器,以实际应用编码。
在 Spark MLLib 中,可以在管道中将一系列计算器和转换器链接在一起,执行你准备数据所需的所有特征工程和预处理步骤。 管道可以以机器学习算法结束,该算法充当计算器,确定从准备好的特征预测标签所需的操作。 管道的输出是一个机器学习模型,它实际上是一个转换器,可用于将模型函数应用于数据帧中的特征,并预测相应的标签值。