机器学习预测模型的性能取决于您的数据,而您的数据性能又取决于您为建模准备数据的方式。
最常见的数据准备方法是研究数据集并回顾机器学习算法的预期,然后仔细选择最合适的数据准备技术来转换原始数据,以最好地满足算法的预期。这既缓慢又昂贵,并且需要大量的专业知识。
数据准备的另一种方法是,并行地将一套常用且有用的数据准备技术应用于原始数据,并将所有转换的结果组合成一个大型数据集,然后可以从该数据集中拟合和评估模型。
这是数据准备的另一种理念,它将数据转换视为一种从原始数据中提取显著特征的方法,以将问题的结构暴露给学习算法。它需要可扩展的加权输入特征的学习算法,并使用与预测目标最相关的输入特征。
这种方法所需的专业知识较少,与对数据准备方法进行全面网格搜索相比,计算效率更高,并且可以帮助发现非直观的数据准备解决方案,从而为给定的预测建模问题实现良好或最佳性能。
在本教程中,您将了解如何使用特征提取进行表格数据的数据准备。
完成本教程后,您将了解:
- 特征提取为表格数据的数据准备提供了一种替代方法,其中所有数据转换都并行应用于原始输入数据并组合在一起以创建一个大型数据集。
- 如何使用特征提取方法进行数据准备,以在标准分类数据集上提高模型性能超过基线。
- 如何将特征选择添加到特征提取建模管道中,以在标准数据集上进一步提升建模性能。
通过我的新书《机器学习数据准备》**启动您的项目**,其中包括**分步教程**和所有示例的**Python源代码**文件。
让我们开始吧。

如何在表格数据上使用特征提取进行数据准备
照片来源:Nicolas Valdes,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 数据准备的特征提取技术
- 数据集和性能基线
- 葡萄酒分类数据集
- 基线模型性能
- 数据准备的特征提取方法
数据准备的特征提取技术
数据准备可能具有挑战性。
最常规定和遵循的方法是分析数据集,审查算法的要求,并转换原始数据以最好地满足算法的预期。
这可能有效,但也很慢,并且可能需要数据分析和机器学习算法方面的深厚专业知识。
另一种方法是将输入变量的准备视为建模管道的超参数,并将其与算法选择和算法配置一起进行调整。
这也可以是一种有效的方法,可以揭示非直观的解决方案,并且只需要很少的专业知识,尽管它的计算成本可能很高。
在数据准备的这两种方法之间寻求中间立场的方法是将输入数据的转换视为一种**特征工程**或**特征提取**过程。这涉及将一套常用或普遍有用的数据准备技术应用于原始数据,然后将所有特征聚合在一起以创建一个大型数据集,然后在此数据上拟合和评估模型。
该方法的理念是将每种数据准备技术视为一种转换,从原始数据中提取显著特征以呈现给学习算法。理想情况下,此类转换可以解开复杂的关系并复合输入变量,从而允许使用更简单的建模算法,例如线性机器学习技术。
为了避免更好的名称,我们将此称为“**特征工程方法**”或“**特征提取方法**”,用于配置预测建模项目的数据准备。
它允许在选择数据准备方法时使用数据分析和算法专业知识,并且可以发现非直观的解决方案,但计算成本要低得多。
输入特征数量的排除也可以通过使用特征选择技术来明确解决,这些技术试图对大量提取特征的重要性或价值进行排序,并且只选择与预测目标变量最相关的一小部分。
我们可以通过一个实际例子来探索这种数据准备方法。
在深入研究一个实际示例之前,我们首先选择一个标准数据集并开发一个性能基线。
想开始学习数据准备吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
数据集和性能基线
在本节中,我们将首先选择一个标准机器学习数据集,并在此数据集上建立一个性能基线。这将为下一节中探索特征提取数据准备方法提供背景。
葡萄酒分类数据集
我们将使用葡萄酒分类数据集。
此数据集有13个输入变量,描述了葡萄酒样本的化学成分,需要将葡萄酒分类为三种类型之一。
你可以在此处了解更多关于此数据集的信息:
无需下载数据集,因为我们将在实际示例中自动下载。
打开数据集并查看原始数据。以下列出了数据的前几行。
我们可以看到这是一个多类分类预测建模问题,其数值输入变量的比例各不相同。
1 2 3 4 5 6 |
14.23,1.71,2.43,15.6,127,2.8,3.06,.28,2.29,5.64,1.04,3.92,1065,1 13.2,1.78,2.14,11.2,100,2.65,2.76,.26,1.28,4.38,1.05,3.4,1050,1 13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185,1 14.37,1.95,2.5,16.8,113,3.85,3.49,.24,2.18,7.8,.86,3.45,1480,1 13.24,2.59,2.87,21,118,2.8,2.69,.39,1.82,4.32,1.04,2.93,735,1 ... |
该示例加载数据集并将其分为输入和输出列,然后总结数据数组。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 加载和总结葡萄酒数据集的示例 from pandas import read_csv # 定义数据集位置 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/wine.csv' # 将数据集加载为数据帧 df = read_csv(url, header=None) # 检索 numpy 数组 data = df.values # 将列分为输入和输出变量 X, y = data[:, :-1], data[:, -1] # 总结加载数据的形状 print(X.shape, y.shape) |
运行示例,我们可以看到数据集已正确加载,并且有179行数据,其中包含13个输入变量和一个目标变量。
1 |
(178, 13) (178,) |
接下来,让我们评估此数据集上的模型并建立性能基线。
基线模型性能
我们可以通过评估原始输入数据上的模型来建立葡萄酒分类任务的性能基线。
在这种情况下,我们将评估一个逻辑回归模型。
首先,我们可以通过确保输入变量是数值型的,并且目标变量是标签编码的(正如scikit-learn库所期望的),来执行最小数据准备。
1 2 3 4 |
... # 最少地准备数据集 X = X.astype('float') y = LabelEncoder().fit_transform(y.astype('str')) |
接下来,我们可以定义我们的预测模型。
1 2 3 |
... # 定义模型 model = LogisticRegression(solver='liblinear') |
我们将使用10折和3次重复的重复分层k折交叉验证这一黄金标准来评估模型。
模型性能将使用分类准确度进行评估。
1 2 3 4 5 6 |
... model = LogisticRegression(solver='liblinear') # 定义交叉验证过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) |
运行结束时,我们将报告在所有重复和评估折叠中收集到的准确度分数的平均值和标准差。
1 2 3 |
... # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores))) |
总而言之,下面列出了在原始葡萄酒分类数据集上评估逻辑回归模型的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# 葡萄酒数据集上的基线模型性能 from numpy import mean from numpy import std from pandas import read_csv from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import cross_val_score 从 sklearn.线性模型 导入 LogisticRegression # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/wine.csv' df = read_csv(url, header=None) data = df.values X, y = data[:, :-1], data[:, -1] # 最少地准备数据集 X = X.astype('float') y = LabelEncoder().fit_transform(y.astype('str')) # 定义模型 model = LogisticRegression(solver='liblinear') # 定义交叉验证过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores))) |
运行该示例将评估模型性能并报告平均值和标准差分类准确度。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到在原始输入数据上拟合的逻辑回归模型实现了大约95.3%的平均分类准确度,提供了性能基线。
1 |
准确度:0.953 (0.048) |
接下来,让我们探讨是否可以使用基于特征提取的数据准备方法来提高性能。
数据准备的特征提取方法
在本节中,我们将探讨是否可以使用特征提取方法进行数据准备来提高性能。
第一步是选择一套常用且有用的数据准备技术。
在这种情况下,鉴于输入变量是数值型的,我们将使用一系列转换来改变输入变量的比例,例如MinMaxScaler、StandardScaler和RobustScaler,以及用于改变输入变量分布的转换,例如QuantileTransformer和KBinsDiscretizer。最后,我们还将使用消除输入变量之间线性依赖关系的转换,例如PCA和TruncatedSVD。
FeatureUnion类可用于定义要执行的转换列表,其结果将被聚合(即联合)。这将创建一个具有大量列的新数据集。
列数的估计值将是13个输入变量乘以5个转换,即65个,再加上PCA和SVD降维方法输出的14个列,总共约79个特征。
1 2 3 4 5 6 7 8 9 10 11 12 |
... # 用于特征联合的变换 transforms = list() transforms.append(('mms', MinMaxScaler())) transforms.append(('ss', StandardScaler())) transforms.append(('rs', RobustScaler())) transforms.append(('qt', QuantileTransformer(n_quantiles=100, output_distribution='normal'))) transforms.append(('kbd', KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform'))) transforms.append(('pca', PCA(n_components=7))) transforms.append(('svd', TruncatedSVD(n_components=7))) # 创建特征联合 fu = FeatureUnion(transforms) |
然后,我们可以使用 FeatureUnion 作为第一步,逻辑回归模型作为最后一步来创建建模Pipeline。
1 2 3 4 5 6 7 8 |
... # 定义模型 model = LogisticRegression(solver='liblinear') # 定义管道 steps = list() steps.append(('fu', fu)) steps.append(('m', model)) pipeline = Pipeline(steps=steps) |
然后,可以像以前一样使用重复分层 k 折交叉验证来评估管道。
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# 葡萄酒数据集的特征工程数据准备 from numpy import mean from numpy import std from pandas import read_csv from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline from sklearn.pipeline import FeatureUnion from sklearn.preprocessing import LabelEncoder 从 sklearn.预处理 导入 MinMaxScaler from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import RobustScaler from sklearn.preprocessing import QuantileTransformer from sklearn.preprocessing import KBinsDiscretizer 从 sklearn.分解 导入 PCA from sklearn.decomposition import TruncatedSVD # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/wine.csv' df = read_csv(url, header=None) data = df.values X, y = data[:, :-1], data[:, -1] # 最少地准备数据集 X = X.astype('float') y = LabelEncoder().fit_transform(y.astype('str')) # 用于特征联合的变换 transforms = list() transforms.append(('mms', MinMaxScaler())) transforms.append(('ss', StandardScaler())) transforms.append(('rs', RobustScaler())) transforms.append(('qt', QuantileTransformer(n_quantiles=100, output_distribution='normal'))) transforms.append(('kbd', KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform'))) transforms.append(('pca', PCA(n_components=7))) transforms.append(('svd', TruncatedSVD(n_components=7))) # 创建特征联合 fu = FeatureUnion(transforms) # 定义模型 model = LogisticRegression(solver='liblinear') # 定义管道 steps = list() steps.append(('fu', fu)) steps.append(('m', model)) pipeline = Pipeline(steps=steps) # 定义交叉验证过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores))) |
运行该示例将评估模型性能并报告平均值和标准差分类准确度。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到性能比基线性能有所提升,平均分类准确度约为96.8%,而上一节中为95.3%。
1 |
准确度:0.968 (0.037) |
尝试向 FeatureUnion 添加更多数据准备方法,看看是否可以提高性能。
你能得到更好的结果吗?
请在下面的评论中告诉我您的发现。
我们还可以使用特征选择将大约80个提取的特征减少到与模型最相关的一个子集。除了降低模型的复杂性外,它还可以通过删除不相关和冗余的输入特征来提高性能。
在这种情况下,我们将使用递归特征消除 (RFE) 技术进行特征选择,并将其配置为选择15个最相关的特征。
1 2 3 |
... # 定义特征选择 rfe = RFE(estimator=LogisticRegression(solver='liblinear'), n_features_to_select=15) |
然后,我们可以将 RFE 特征选择添加到建模管道中,置于 *FeatureUnion* 之后和 *LogisticRegression* 算法之前。
1 2 3 4 5 6 7 |
... # 定义管道 steps = list() steps.append(('fu', fu)) steps.append(('rfe', rfe)) steps.append(('m', model)) pipeline = Pipeline(steps=steps) |
总而言之,下面列出了带有特征选择的特征选择数据准备方法的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# 具有特征选择的葡萄酒数据集的特征工程数据准备 from numpy import mean from numpy import std from pandas import read_csv from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline from sklearn.pipeline import FeatureUnion from sklearn.preprocessing import LabelEncoder 从 sklearn.预处理 导入 MinMaxScaler from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import RobustScaler from sklearn.preprocessing import QuantileTransformer from sklearn.preprocessing import KBinsDiscretizer 从 sklearn.特征选择 导入 RFE 从 sklearn.分解 导入 PCA from sklearn.decomposition import TruncatedSVD # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/wine.csv' df = read_csv(url, header=None) data = df.values X, y = data[:, :-1], data[:, -1] # 最少地准备数据集 X = X.astype('float') y = LabelEncoder().fit_transform(y.astype('str')) # 用于特征联合的变换 transforms = list() transforms.append(('mms', MinMaxScaler())) transforms.append(('ss', StandardScaler())) transforms.append(('rs', RobustScaler())) transforms.append(('qt', QuantileTransformer(n_quantiles=100, output_distribution='normal'))) transforms.append(('kbd', KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform'))) transforms.append(('pca', PCA(n_components=7))) transforms.append(('svd', TruncatedSVD(n_components=7))) # 创建特征联合 fu = FeatureUnion(transforms) # 定义特征选择 rfe = RFE(estimator=LogisticRegression(solver='liblinear'), n_features_to_select=15) # 定义模型 model = LogisticRegression(solver='liblinear') # 定义管道 steps = list() steps.append(('fu', fu)) steps.append(('rfe', rfe)) steps.append(('m', model)) pipeline = Pipeline(steps=steps) # 定义交叉验证过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores))) |
运行该示例将评估模型性能并报告平均值和标准差分类准确度。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
同样,我们可以看到性能从所有提取特征的96.8%进一步提升到建模前使用特征选择的约98.9%。
1 |
准确度:0.989 (0.022) |
您可以使用不同的特征选择技术或更多或更少的选定特征来获得更好的性能吗?
请在下面的评论中告诉我您的发现。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
相关教程
书籍
API
总结
在本教程中,您学习了如何使用特征提取进行表格数据的数据准备。
具体来说,你学到了:
- 特征提取为表格数据的数据准备提供了一种替代方法,其中所有数据转换都并行应用于原始输入数据并组合在一起以创建一个大型数据集。
- 如何使用特征提取方法进行数据准备,以在标准分类数据集上提高模型性能超过基线。
- 如何将特征选择添加到特征提取建模管道中,以在标准数据集上进一步提升建模性能。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,杰森!我是你的忠实粉丝。
感谢这篇文章。我从中学习了一些新的库。我有一个问题,与其同时进行特征提取和选择,有没有办法在一开始就通过查看数据或一些统计数据来了解应该使用什么?
我能否单独使用特征选择,还是需要与特征提取方法创建的大型数据集一起使用?如何理解这一点?
谢谢!
是的,有时查看数据可以提示要使用的方法,请参阅此处:
https://machinelearning.org.cn/what-is-data-preparation-in-machine-learning/
是的,您可以单独使用特征选择
https://machinelearning.org.cn/feature-selection-with-real-and-categorical-data/
好棒。谢谢你,杰森。有没有一个函数也可以选择列的交互作用?或者你必须先创建所有这些新列?例如,通过将特征相乘来生成交互特征,从而得到一个新的特征。考虑到可能存在多少相关的组合,如果有一个函数可以自动化这个过程,那就太好了。
解释得很好。我们一直在使用卷积神经网络和自动编码器。我们能将这种特征提取嵌入到深度学习中吗?
当然可以。
你需要创建集成特征然后进行选择,这可以帮助你创建它们
https://machinelearning.org.cn/polynomial-features-transforms-for-machine-learning/
嗨,杰森,干得好!
我想知道您对tsfresh模块有什么看法?
我没用过,抱歉。
Hatta,谢谢您提醒我tsfresh模块。看起来非常有用。
又一篇精彩的帖子——非常感谢。我只想补充一点,检查选定的特征对您来说是否确实有意义。有时它可以帮助您发现代码中的错误,有时可以帮助您了解有关数据的新知识
谢谢。
好建议!
很棒的文章。
假设我一开始就将数据分为训练/测试集。
您将如何在新数据上进行预测?
您如何使用所有这些步骤和管道来创建模型?
非常感谢!
您可以在所有数据上拟合管道,然后调用 pipleine.predict() 以在新数据上进行预测。
杰森,如果你想使用相同的特征和预处理步骤运行多个模型,比如逻辑回归和随机森林,你会怎么做?
您有示例吗?
提前感谢,
也许投票
https://machinelearning.org.cn/voting-ensembles-with-python/
或者,也许是一个堆叠模型
https://machinelearning.org.cn/stacking-ensemble-machine-learning-with-python/
杰森,抱歉。
我的意思是除了逻辑回归之外,还尝试其他分类器。
您对 RL 进行了交叉验证,是否可以再添加几行代码来尝试其他一些模型,看看它们是否能做出更好的预测?
不是堆叠它们,而是检查哪个是最好的。
谢谢
是的,您可以将模型更改为您喜欢的任何模型。
您好,我是机器学习的新手,我想学习并对研究感兴趣。入门有什么要求?谢谢
除了作为开发人员之外没有其他要求,从这里开始
https://machinelearning.org.cn/start-here/#getstarted
我很好奇,为什么我们需要对目标变量进行标签编码,因为它已经是数值型(值为1、2和3)?
也许这是一个很好的默认做法。此外,确保整数值从零开始,以防它们不是。
Jason,
很棒的书,《机器学习数据准备》。我一天之内读完了整本书——爱不释手!请问,您能给我一个简单的例子,说明如何同时使用 FeatureUnion、ColumnTransformer 和 TransformedTargetRegressor 吗?我假设 TransformedTargetRegressor 只对目标变量进行操作,而不是特征本身,所以在那之前我需要这样做?有没有一种方法可以发现最终选定的 RFE?
太厉害了!
您可以单独使用RFE并报告该方法找到的特征。不过,那将是一团糟。
一篇优秀的帖子——非常感谢您的文章。
实际上,我想知道在同一数据集上使用“MinMaxScaler”和“StandarScaler”两种归一化技术的兴趣何在?
谢谢!
好问题,可能具有高斯变量的变量对标准化的响应比对归一化的响应更好,但您可能认为一种缩放方法就足够了。
谢谢你的答复。
在这种情况下,对变量进行统计假设检验以确定具有高斯分布的变量并对这些变量应用标准化,是否会更严谨?
有时,有时当我们打破规则/期望时会得到更好的结果。
我想这篇教程可能会引起您的兴趣
https://machinelearning.org.cn/selectively-scale-numerical-input-variables-for-machine-learning/
谢谢
我完全同意你的看法,打破规则会得到更好的结果。
你的“选择性缩放”文章太棒了!!!再次感谢杰森。
谢谢!
先生,我们在测试时将GAN(生成对抗网络)数据增强应用于预训练的AlexNet吗?
如果你愿意,你可以。
哪种特征选择方法最适合分析网络日志数据
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/what-feature-selection-method-should-i-use