类别数据的顺序编码和单热编码
原文:https://machinelearningmastery.com/one-hot-encoding-for-categorical-data/
最后更新于 2020 年 8 月 17 日
机器学习模型要求所有的输入和输出变量都是数字。
这意味着,如果您的数据包含类别数据,您必须将其编码为数字,然后才能拟合和评估模型。
两种最流行的技术是顺序编码和单热编码。
在本教程中,您将发现如何对分类机器学习数据使用编码方案。
完成本教程后,您将知道:
- 当处理机器学习算法的类别数据时,编码是必需的预处理步骤。
- 如何对具有自然排序的分类变量使用序数编码?
- 如何对没有自然排序的分类变量使用一热编码?
用我的新书机器学习的数据准备启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
机器学习的顺序和单热编码转换
图片由费利佩·瓦尔杜加提供,保留部分权利。
教程概述
本教程分为六个部分;它们是:
- 名义变量和顺序变量
- 类别数据编码
- 序数编码
- 一次性编码
- 虚拟变量编码
- 乳腺癌数据集
- 序码变换
- OneHotEncoder 转换
- 常见问题
名义变量和顺序变量
顾名思义,数字数据包括仅由数字组成的特征,例如整数或浮点值。
类别数据是包含标签值而不是数值的变量。
可能值的数量通常限于一个固定的集合。
分类变量通常被称为名义变量。
一些例子包括:
- 一个“宠物”变量的值为:“狗”和“猫”。
- 一个“颜色”变量,值为:“红色”、“绿色”和“蓝色”。
- 一个“放置”变量的值为:“第一个”、“第二个”和“第三个”。
每个值代表不同的类别。
有些类别可能彼此有自然的关系,例如自然的排序。
上面的“ place ”变量确实有一个自然的值排序。这种类型的分类变量被称为序数变量,因为值可以排序或排序。
通过将数值变量的范围划分为若干个区间并为每个区间赋值,可以将数值变量转换为序数变量。例如,一个介于 1 和 10 之间的数字变量可以分为一个序数变量,该序数变量有 5 个具有序数关系的标签:1-2、3-4、5-6、7-8、9-10。这叫做离散化。
- 名义变量 ( 分类)。变量由一组有限的离散值组成,这些值之间没有关系。
- 序数变量。变量由一组有限的离散值组成,这些值之间具有等级排序。
有些算法可以直接处理类别数据。
例如,决策树可以直接从类别数据中学习,不需要数据转换(这取决于具体的实现)。
许多机器学习算法不能直接对标签数据进行操作。它们要求所有输入变量和输出变量都是数字。
一般来说,这主要是机器学习算法有效实现的一个限制,而不是算法本身的硬性限制。
机器学习算法的一些实现要求所有数据都是数字的。比如 Sklearn 就有这个要求。
这意味着类别数据必须转换成数字形式。如果分类变量是输出变量,您可能还希望将模型的预测转换回分类形式,以便在某些应用中呈现或使用它们。
类别数据编码
有三种常见的方法将序数和分类变量转换为数值。它们是:
- 序数编码
- 一次性编码
- 虚拟变量编码
让我们依次仔细看看每一个。
序数编码
在序数编码中,每个唯一的类别值都被赋予一个整数值。
例如“红色为 1,“绿色为 2,蓝色为 3。
这被称为序数编码或整数编码,并且很容易可逆。通常,使用从零开始的整数值。
对于某些变量,序数编码可能就足够了。整数值之间具有自然的有序关系,机器学习算法可能能够理解和利用这种关系。
它是序数变量的自然编码。对于分类变量,它强加了一种序数关系,而这种关系可能不存在。这可能会导致问题,可以使用一个热编码来代替。
这种序数编码转换可以通过序数编码器类在 Sklearn Python 机器学习库中获得。
默认情况下,它将按照数据中观察到的顺序为标签分配整数。如果需要特定的顺序,可以通过“类别”参数将其指定为具有所有预期标签的等级顺序的列表。
我们可以通过将颜色类别“红色”、“绿色”和“蓝色”转换为整数来演示这个类的用法。首先对类别进行排序,然后应用数字。对于字符串,这意味着标签按字母顺序排序,蓝色=0,绿色=1,红色=2。
下面列出了完整的示例。
# example of a ordinal encoding
from numpy import asarray
from sklearn.preprocessing import OrdinalEncoder
# define data
data = asarray([['red'], ['green'], ['blue']])
print(data)
# define ordinal encoding
encoder = OrdinalEncoder()
# transform data
result = encoder.fit_transform(data)
print(result)
运行该示例首先报告 3 行标签数据,然后报告序号编码。
我们可以看到,这些数字是按照我们的预期分配给标签的。
[['red']
['green']
['blue']]
[[2.]
[1.]
[0.]]
这个序数编码器类用于输入变量,这些变量被组织成行和列,例如矩阵。
如果分类预测建模问题需要对分类目标变量进行编码,那么可以使用标签编码器类。它做的事情与 OrdinalEncoder 相同,尽管它期望对单个目标变量进行一维输入。
一次性编码
对于不存在序数关系的分类变量,整数编码充其量可能不够,最坏可能会误导模型。
通过序数编码强制序数关系,并允许模型假设类别之间的自然排序,可能会导致较差的表现或意外的结果(类别之间的预测)。
在这种情况下,一个热编码可以应用于序数表示。这是删除整数编码变量,并为变量中的每个唯一整数值添加一个新的二进制变量的地方。
每一位代表一个可能的类别。如果变量不能同时属于多个类别,那么组中只有一位可以是“开”这被称为一热编码…
—第 78 页,机器学习的特征工程,2018。
在“ color ”变量示例中,有三个类别,因此需要三个二元变量。颜色的二进制变量中有一个“1”值,其他颜色的二进制变量中有“0”值。
通过 OneHotEncoder 类,在 Sklearn Python 机器学习库中可以获得这种一次性编码转换。
我们可以演示 OneHotEncoder 在颜色类别上的用法。首先对类别进行排序,在这种情况下是按字母顺序排序,因为它们是字符串,然后依次为每个类别创建二进制变量。这意味着对于第一个二进制变量,蓝色将表示为[1,0,0],然后是绿色,最后是红色。
下面列出了完整的示例。
# example of a one hot encoding
from numpy import asarray
from sklearn.preprocessing import OneHotEncoder
# define data
data = asarray([['red'], ['green'], ['blue']])
print(data)
# define one hot encoding
encoder = OneHotEncoder(sparse=False)
# transform data
onehot = encoder.fit_transform(data)
print(onehot)
运行该示例首先列出了三行标签数据,然后是一个热编码,与我们对 3 个二进制变量的期望相匹配,顺序为“蓝色”、“绿色”和“红色”。
[['red']
['green']
['blue']]
[[0\. 0\. 1.]
[0\. 1\. 0.]
[1\. 0\. 0.]]
如果您知道数据中预期的所有标签,则可以通过列表形式的“类别”参数来指定它们。
编码器适合训练数据集,如果不指定标签列表,该数据集可能至少包含每个分类变量的所有预期标签的一个示例。如果新数据包含训练数据集中未出现的类别,可以将“ handle_unknown ”参数设置为“ ignore ”以不引发错误,这将导致每个标签的值为零。
虚拟变量编码
单一热编码为每个类别创建一个二进制变量。
问题是,这种表示包括冗余。例如,如果我们知道[1,0,0]代表“蓝色”,[ 0,1,0]代表“绿色”,我们不需要另一个二进制变量来代表“红色”,相反,我们可以单独为“蓝色”和“绿色”使用 0 值,例如[0,0]。
这被称为虚拟变量编码,并且总是用 C-1 二进制变量表示 C 类。
当预测值有 C 个可能值,且仅使用 C–1 个虚拟变量时,可以计算矩阵求逆,对比方法称为全秩参数化
—第 95 页,特征工程与选择,2019 年。
除了稍微减少冗余之外,一些模型还需要虚拟变量表示。
例如,在线性回归模型(以及具有偏差项的其他回归模型)的情况下,一次热编码将使输入数据的矩阵变成奇异的,这意味着它不能被反转,并且不能使用线性代数来计算线性回归系数。对于这些类型的模型,必须使用虚拟变量编码来代替。
如果模型包含一个截距并包含虚拟变量[…],那么[…]列将与截距相加(按行),这种线性组合将阻止矩阵求逆的计算(因为它是奇异的)。
—第 95 页,特征工程与选择,2019 年。
在评估机器学习算法时,我们在实践中很少遇到这个问题,当然,除非我们使用线性回归。
…有时一整套虚拟变量是有用的。例如,当虚拟变量编码预测器的所有信息时,基于树的模型中的拆分更容易解释。我们建议在使用基于树的模型时使用完整的 if 虚拟变量集。
—第 56 页,应用预测建模,2013 年。
我们可以使用 OneHotEncoder 类来实现一个虚拟编码和一个热编码。
可以设置“ drop ”参数来指示哪个类别将被分配所有零值,称为“基线”。我们可以先将此设置为“”,这样就可以使用第一个类别。当标签按字母顺序排序时,第一个“蓝色”标签将是第一个,并将成为基线。
*> 虚拟变量总是比级别数少一个。没有虚拟变量[…]的水平称为基线。
—第 86 页,R,2014 年《统计学习与应用导论》。
我们可以用我们的颜色类别来证明这一点。下面列出了完整的示例。
# example of a dummy variable encoding
from numpy import asarray
from sklearn.preprocessing import OneHotEncoder
# define data
data = asarray([['red'], ['green'], ['blue']])
print(data)
# define one hot encoding
encoder = OneHotEncoder(drop='first', sparse=False)
# transform data
onehot = encoder.fit_transform(data)
print(onehot)
运行该示例首先列出了分类变量的三行,然后是虚拟变量编码,显示绿色编码为[1,0],红色编码为[0,1],蓝色编码为[0,0]。
[['red']
['green']
['blue']]
[[0\. 1.]
[1\. 0.]
[0\. 0.]]
现在我们已经熟悉了编码分类变量的三种方法,让我们来看看一个包含分类变量的数据集。
乳腺癌数据集
作为本教程的基础,我们将使用自 20 世纪 80 年代以来在机器学习中广泛研究的“乳腺癌”数据集。
数据集将乳腺癌患者数据分类为癌症复发或不复发。有 286 个例子和 9 个输入变量。这是一个二分类问题。
该数据集上合理的分类准确度分数在 68%到 73%之间。我们将针对这个区域,但请注意,本教程中的模型并未优化:它们旨在演示编码方案。
不需要下载数据集,因为我们将直接从代码示例中访问它。
查看数据,我们可以看到所有九个输入变量都是绝对的。
具体来说,所有变量都是带引号的字符串。有些变量显示了一个明显的数值范围的序数关系(如年龄范围),有些则没有。
'40-49','premeno','15-19','0-2','yes','3','right','left_up','no','recurrence-events'
'50-59','ge40','15-19','0-2','no','1','right','central','no','no-recurrence-events'
'50-59','ge40','35-39','0-2','no','2','left','left_low','no','recurrence-events'
'40-49','premeno','35-39','0-2','yes','3','right','left_low','yes','no-recurrence-events'
'40-49','premeno','30-34','3-5','yes','2','left','right_up','no','recurrence-events'
...
请注意,该数据集缺少标有“ nan 值的值。
在本教程中,我们将保持这些值不变,并使用编码方案将“nan”编码为另一个值。这是处理分类变量缺失值的一种可能且非常合理的方法。
我们可以使用熊猫库将这个数据集加载到内存中。
...
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
加载后,我们可以将列拆分为输入(X)和输出(y)进行建模。
...
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
利用这个函数,下面列出了加载和汇总原始类别数据集的完整示例。
# load and summarize the dataset
from pandas import read_csv
# define the location of the dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/breast-cancer.csv"
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
# summarize
print('Input', X.shape)
print('Output', y.shape)
运行该示例会报告数据集的输入和输出元素的大小。
我们可以看到我们有 286 个例子和 9 个输入变量。
Input (286, 9)
Output (286,)
现在我们已经熟悉了数据集,让我们看看如何对它进行编码以进行建模。
序码变换
序数编码包括将每个唯一标签映射到一个整数值。
只有当类别之间存在已知的关系时,这种类型的编码才是真正合适的。对于我们数据集中的一些变量,这种关系确实存在,理想情况下,在准备数据时应该利用这种关系。
在这种情况下,我们将忽略任何可能存在的序数关系,并假设所有变量都是分类的。使用序数编码仍然是有帮助的,至少作为其他编码方案的参考点。
我们可以使用 scikit 中的序数编码器-学会将每个变量编码成整数。这是一个灵活的类,如果已知任何这样的顺序,它确实允许将类别的顺序指定为参数。
注意:我将把它作为一个练习留给您来更新下面的示例,以尝试为那些具有自然顺序的变量指定顺序,并查看它是否对模型表现有影响。
一旦定义,我们就可以调用 fit_transform() 函数,并将其传递给我们的数据集,以创建数据集的分位数转换版本。
...
# ordinal encode input variables
ordinal = OrdinalEncoder()
X = ordinal.fit_transform(X)
我们也可以用同样的方式准备目标。
...
# ordinal encode target variable
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
让我们在乳腺癌数据集上尝试一下。
下面列出了创建乳腺癌数据集的序数编码转换并总结结果的完整示例。
# ordinal encode the breast cancer dataset
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OrdinalEncoder
# define the location of the dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/breast-cancer.csv"
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
# ordinal encode input variables
ordinal_encoder = OrdinalEncoder()
X = ordinal_encoder.fit_transform(X)
# ordinal encode target variable
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# summarize the transformed data
print('Input', X.shape)
print(X[:5, :])
print('Output', y.shape)
print(y[:5])
运行该示例会转换数据集并报告结果数据集的形状。
除了所有字符串值现在都是整数值之外,我们希望行数(在本例中是列数)保持不变。
不出所料,在这种情况下,我们可以看到变量的数量没有变化,但是所有的值现在都是序数编码的整数。
Input (286, 9)
[[2\. 2\. 2\. 0\. 1\. 2\. 1\. 2\. 0.]
[3\. 0\. 2\. 0\. 0\. 0\. 1\. 0\. 0.]
[3\. 0\. 6\. 0\. 0\. 1\. 0\. 1\. 0.]
[2\. 2\. 6\. 0\. 1\. 2\. 1\. 1\. 1.]
[2\. 2\. 5\. 4\. 1\. 1\. 0\. 4\. 0.]]
Output (286,)
[1 0 1 0 1]
接下来,让我们用这种编码在这个数据集上评估机器学习。
对变量进行编码的最佳实践是在训练数据集上进行编码,然后将其应用于训练和测试数据集。
我们将首先分割数据集,然后在训练集上准备编码,并将其应用于测试集。
...
# split the dataset into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
然后,我们可以在训练数据集上拟合序数编码器,并使用它来转换训练和测试数据集。
...
# ordinal encode input variables
ordinal_encoder = OrdinalEncoder()
ordinal_encoder.fit(X_train)
X_train = ordinal_encoder.transform(X_train)
X_test = ordinal_encoder.transform(X_test)
同样的方法可以用来准备目标变量。然后,我们可以在训练数据集上拟合逻辑回归算法,并在测试数据集上对其进行评估。
下面列出了完整的示例。
# evaluate logistic regression on the breast cancer dataset with an ordinal encoding
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OrdinalEncoder
from sklearn.metrics import accuracy_score
# define the location of the dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/breast-cancer.csv"
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
# split the dataset into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# ordinal encode input variables
ordinal_encoder = OrdinalEncoder()
ordinal_encoder.fit(X_train)
X_train = ordinal_encoder.transform(X_train)
X_test = ordinal_encoder.transform(X_test)
# ordinal encode target variable
label_encoder = LabelEncoder()
label_encoder.fit(y_train)
y_train = label_encoder.transform(y_train)
y_test = label_encoder.transform(y_test)
# define the model
model = LogisticRegression()
# fit on the training set
model.fit(X_train, y_train)
# predict on test set
yhat = model.predict(X_test)
# evaluate predictions
accuracy = accuracy_score(y_test, yhat)
print('Accuracy: %.2f' % (accuracy*100))
运行该示例以正确的方式准备数据集,然后对转换后的数据进行模型拟合评估。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,该模型实现了大约 75.79%的分类准确率,这是一个合理的分数。
Accuracy: 75.79
接下来,让我们仔细看看一热编码。
OneHotEncoder 转换
单热编码适用于类别之间不存在关系的类别数据。
Sklearn 库提供了 OneHotEncoder 类来自动对一个或多个变量进行热编码。
默认情况下, OneHotEncoder 将输出具有稀疏表示的数据,这在编码表示中大多数值为 0 的情况下是有效的。我们将通过将“稀疏”参数设置为假来禁用此功能,以便我们可以查看编码的效果。
一旦定义,我们就可以调用 fit_transform() 函数,并将其传递给我们的数据集,以创建数据集的分位数转换版本。
...
# one hot encode input variables
onehot_encoder = OneHotEncoder(sparse=False)
X = onehot_encoder.fit_transform(X)
和以前一样,我们必须对目标变量进行标签编码。
下面列出了创建乳腺癌数据集的一次性编码转换并总结结果的完整示例。
# one-hot encode the breast cancer dataset
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
# define the location of the dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/breast-cancer.csv"
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
# one hot encode input variables
onehot_encoder = OneHotEncoder(sparse=False)
X = onehot_encoder.fit_transform(X)
# ordinal encode target variable
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# summarize the transformed data
print('Input', X.shape)
print(X[:5, :])
运行该示例会转换数据集并报告结果数据集的形状。
我们希望行数保持不变,但列数会急剧增加。
不出所料,在这种情况下,我们可以看到变量的数量从 9 个跃升到 43 个,现在所有的值都是二进制值 0 或 1。
Input (286, 43)
[[0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0.
0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 1\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 1\. 0.]
[0\. 0\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0.
0\. 0\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 1\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0.]
[0\. 0\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0.
0\. 0\. 0\. 1\. 0\. 0\. 0\. 1\. 0\. 1\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 1\. 0.]
[0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0.
0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 1\. 0\. 1\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1.]
[0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0.
1\. 0\. 0\. 0\. 1\. 0\. 0\. 1\. 0\. 1\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 1\. 0.]]
接下来,让我们像上一节所做的那样,用这种编码来评估这个数据集上的机器学习。
编码适合训练集,然后像以前一样应用于训练集和测试集。
...
# one-hot encode input variables
onehot_encoder = OneHotEncoder()
onehot_encoder.fit(X_train)
X_train = onehot_encoder.transform(X_train)
X_test = onehot_encoder.transform(X_test)
将这些联系在一起,完整的示例如下所示。
# evaluate logistic regression on the breast cancer dataset with an one-hot encoding
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import accuracy_score
# define the location of the dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/breast-cancer.csv"
# load the dataset
dataset = read_csv(url, header=None)
# retrieve the array of data
data = dataset.values
# separate into input and output columns
X = data[:, :-1].astype(str)
y = data[:, -1].astype(str)
# split the dataset into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# one-hot encode input variables
onehot_encoder = OneHotEncoder()
onehot_encoder.fit(X_train)
X_train = onehot_encoder.transform(X_train)
X_test = onehot_encoder.transform(X_test)
# ordinal encode target variable
label_encoder = LabelEncoder()
label_encoder.fit(y_train)
y_train = label_encoder.transform(y_train)
y_test = label_encoder.transform(y_test)
# define the model
model = LogisticRegression()
# fit on the training set
model.fit(X_train, y_train)
# predict on test set
yhat = model.predict(X_test)
# evaluate predictions
accuracy = accuracy_score(y_test, yhat)
print('Accuracy: %.2f' % (accuracy*100))
运行该示例以正确的方式准备数据集,然后对转换后的数据进行模型拟合评估。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,该模型实现了大约 70.53%的分类准确率,这比前一节中的序数编码稍差。
Accuracy: 70.53
常见问题
本节列出了编码类别数据时的一些常见问题和答案。
问:如果我有数字和类别数据的混合会怎么样?
或者,如果我有分类和顺序数据的混合呢?
您需要分别准备或编码数据集中的每个变量(列),然后将所有准备好的变量重新连接到一个数组中,以便拟合或评估模型。
或者,您可以使用列转换器有条件地将不同的数据转换应用于不同的输入变量。
问:如果我有上百个类别呢?
或者,如果我连接多个一热编码向量来创建一个多千元素的输入向量呢?
你可以使用一个热门的编码多达成千上万的类别。此外,使用大向量作为输入听起来很吓人,但是模型通常可以处理它。
问:什么编码技术最好?
这是不可知的。
使用您选择的模型在数据集上测试每种技术(以及更多),并发现最适合您的案例的技术。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
书
蜜蜂
- 硬化。预处理。OneHotEncoder API 。
- 硬化。预处理。标签编码 API 。
- 硬化。预处理。序编码器 API 。
文章
摘要
在本教程中,您发现了如何对分类机器学习数据使用编码方案。
具体来说,您了解到:
- 当处理机器学习算法的类别数据时,编码是必需的预处理步骤。
- 如何对具有自然排序的分类变量使用序数编码?
- 如何对没有自然排序的分类变量使用一热编码?
你有什么问题吗?
在下面的评论中提问,我会尽力回答。*
如何为机器学习使用多项式特征变换
原文:https://machinelearningmastery.com/polynomial-features-transforms-for-machine-learning/
最后更新于 2020 年 8 月 28 日
通常,预测建模任务的输入特征以意想不到且通常非线性的方式相互作用。
这些交互可以通过学习算法来识别和建模。另一种方法是设计暴露这些交互的新特性,看看它们是否能提高模型表现。此外,像将输入变量提升到幂这样的转换有助于更好地揭示输入变量和目标变量之间的重要关系。
这些特征被称为交互和多项式特征,并且允许使用更简单的建模算法,因为解释输入变量及其关系的一些复杂性被推回到数据准备阶段。有时,这些特性可以提高建模表现,尽管代价是增加数千甚至数百万个额外的输入变量。
在本教程中,您将发现如何将多项式特征变换用于带有数字输入变量的特征工程。
完成本教程后,您将知道:
- 一些机器学习算法更喜欢多项式输入特征或在多项式输入特征下表现更好。
- 如何使用多项式特征变换为预测建模创建新版本的输入变量。
- 多项式的次数如何影响由变换创建的输入要素的数量。
用我的新书机器学习的数据准备启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何使用多项式特征变换进行机器学习
图片由 D 库切提供,版权所有。
教程概述
本教程分为五个部分;它们是:
- 多项式特征
- 多项式特征变换
- 声纳数据集
- 多项式特征变换示例
- 多项式次数的影响
多项式特征
多项式特征是通过将现有特征提升到指数而创建的特征。
例如,如果数据集有一个输入要素 x,那么多项式要素将是一个新要素(列)的加法,其中值是通过对 x 中的值求平方来计算的,例如 X².可以对数据集中的每个输入变量重复这个过程,创建每个变量的转换版本。
因此,多项式特征是一种特征工程,例如基于现有特征创建新的输入特征。
多项式的“次”用于控制添加的特征数量,例如,3 次将为每个输入变量添加两个新变量。通常使用小度数,如 2 度或 3 度。
一般来说,使用大于 3 或 4 的 d 是不寻常的,因为对于大的 d 值,多项式曲线会变得过于灵活,并且会呈现出一些非常奇怪的形状。
—第 266 页,R中应用的统计学习介绍,2014。
添加表示特征之间交互的新变量也很常见,例如,表示一个变量乘以另一个变量的新列。这也可以对每个输入变量重复,为每对输入变量创建一个新的“交互”变量。
输入变量的平方或立方版本将改变概率分布,分离小值和大值,这种分离随着指数的大小而增加。
这种分离可以帮助一些机器学习算法做出更好的预测,并且对于回归预测建模任务和通常具有数字输入变量的任务是常见的。
典型的线性算法,如线性回归和逻辑回归,对多项式输入变量的使用反应良好。
线性回归在模型参数中是线性的,并且向模型添加多项式项可以是允许模型识别非线性模式的有效方式。
—第 11 页,特征工程与选择,2019 年。
例如,当用作线性回归算法的输入时,该方法被更广泛地称为多项式回归。
多项式回归通过添加额外的预测因子来扩展线性模型,这些预测因子是通过将每个原始预测因子的幂提高而获得的。例如,三次回归使用三个变量 X、X2 和 X3 作为预测因子。这种方法提供了一种简单的方法来提供数据的非线性拟合。
—第 265 页,R中应用的统计学习介绍,2014。
多项式特征变换
多项式特征变换可通过多项式特征类在 Sklearn Python 机器学习库中获得。
创建的功能包括:
- 偏差(值为 1.0)
- 每升一级的数值(如 x¹、x²、x³ 等)
- 所有特征对之间的相互作用(例如 x1 * x2,x1 * x3,…)
例如,如果两个输入变量的值分别为 2 和 3,度数为 2,则创建的特征将是:
- 1(偏差)
- 2¹ = 2
- 3¹ = 3
- 2² = 4
- 3² = 9
- 2 * 3 = 6
我们可以用一个例子来证明这一点:
# demonstrate the types of features created
from numpy import asarray
from sklearn.preprocessing import PolynomialFeatures
# define the dataset
data = asarray([[2,3],[2,3],[2,3]])
print(data)
# perform a polynomial features transform of the dataset
trans = PolynomialFeatures(degree=2)
data = trans.fit_transform(data)
print(data)
运行该示例首先报告包含两个要素(列)的原始数据,每个要素都有相同的值,即 2 或 3。
然后创建多项式特征,得到六个特征,与上面描述的相匹配。
[[2 3]
[2 3]
[2 3]]
[[1\. 2\. 3\. 4\. 6\. 9.]
[1\. 2\. 3\. 4\. 6\. 9.]
[1\. 2\. 3\. 4\. 6\. 9.]]
“度”参数控制创建的特征数量,默认为 2。
“ interaction_only ”参数意味着只包括原始值(1 度)和交互(相互相乘的值对),默认为 False 。
“ include_bias ”参数默认为 True 以包含偏置特征。
我们将仔细研究如何在真实数据集上使用多项式特征变换。
首先,让我们介绍一个真实的数据集。
声纳数据集
声纳数据集是用于二进制分类的标准机器学习数据集。
它涉及 60 个实值输入和一个两类目标变量。数据集中有 208 个示例,类别相当均衡。
使用重复的分层 10 倍交叉验证,基线分类算法可以达到大约 53.4%的分类准确率。使用重复的分层 10 倍交叉验证,该数据集的最高表现约为 88%。
该数据集描述了岩石或模拟地雷的雷达回波。
您可以从这里了解有关数据集的更多信息:
不需要下载数据集;我们将从我们的工作示例中自动下载它。
首先,让我们加载并总结数据集。下面列出了完整的示例。
# load and summarize the sonar dataset
from pandas import read_csv
from pandas.plotting import scatter_matrix
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# summarize the shape of the dataset
print(dataset.shape)
# summarize each variable
print(dataset.describe())
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例首先总结加载数据集的形状。
这确认了 60 个输入变量、一个输出变量和 208 行数据。
提供了输入变量的统计摘要,显示值是数值,范围大约从 0 到 1。
(208, 61)
0 1 2 ... 57 58 59
count 208.000000 208.000000 208.000000 ... 208.000000 208.000000 208.000000
mean 0.029164 0.038437 0.043832 ... 0.007949 0.007941 0.006507
std 0.022991 0.032960 0.038428 ... 0.006470 0.006181 0.005031
min 0.001500 0.000600 0.001500 ... 0.000300 0.000100 0.000600
25% 0.013350 0.016450 0.018950 ... 0.003600 0.003675 0.003100
50% 0.022800 0.030800 0.034300 ... 0.005800 0.006400 0.005300
75% 0.035550 0.047950 0.057950 ... 0.010350 0.010325 0.008525
max 0.137100 0.233900 0.305900 ... 0.044000 0.036400 0.043900
[8 rows x 60 columns]
最后,为每个输入变量创建一个直方图。
如果我们忽略图中杂乱的东西,专注于直方图本身,我们可以看到许多变量都有一个偏斜的分布。
声纳二进制类别数据集输入变量的直方图
接下来,让我们在原始数据集上拟合和评估一个机器学习模型。
我们将使用带有默认超参数的 k 近邻算法,并使用重复的分层 K 折交叉验证对其进行评估。下面列出了完整的示例。
# evaluate knn on the raw sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define and configure the model
model = KNeighborsClassifier()
# evaluate the model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report model performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会评估原始声纳数据集上的 KNN 模型。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,该模型实现了大约 79.7%的平均分类准确率,表明它具有技巧性(优于 53.4%),并且处于良好表现的球园区(88%)。
Accuracy: 0.797 (0.073)
接下来,让我们探索数据集的多项式特征变换。
多项式特征变换示例
我们可以将多项式特征变换直接应用于声纳数据集。
在这种情况下,我们将使用 3 度。
...
# perform a polynomial features transform of the dataset
trans = PolynomialFeatures(degree=3)
data = trans.fit_transform(data)
让我们在声纳数据集上试试。
下面是创建声纳数据集的多项式特征变换并总结创建的特征的完整示例。
# visualize a polynomial features transform of the sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import PolynomialFeatures
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a polynomial features transform of the dataset
trans = PolynomialFeatures(degree=3)
data = trans.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# summarize
print(dataset.shape)
运行该示例会对声纳数据集执行多项式特征变换。
我们可以看到,我们的要素从原始数据集的 61 个(60 个输入要素)增加到 39,711 个(39,710 个输入要素)。
(208, 39711)
接下来,让我们评估与上一节相同的 KNN 模型,但在这种情况下是数据集的多项式特征变换。
下面列出了完整的示例。
# evaluate knn on the sonar dataset with polynomial features transform
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
trans = PolynomialFeatures(degree=3)
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('t', trans), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到多项式特征变换将表现从没有变换时的 79.7%提升到有变换时的 80.0%。
Accuracy: 0.800 (0.077)
接下来,让我们探索不同缩放范围的效果。
多项式次数的影响
多项式的次数极大地增加了输入特征的数量。
为了了解这对要素数量的影响,我们可以在不同程度上执行转换,并比较数据集中的要素数量。
下面列出了完整的示例。
# compare the effect of the degree on the number of created features
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import PolynomialFeatures
from matplotlib import pyplot
# get the dataset
def get_dataset():
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
return X, y
# define dataset
X, y = get_dataset()
# calculate change in number of features
num_features = list()
degress = [i for i in range(1, 6)]
for d in degress:
# create transform
trans = PolynomialFeatures(degree=d)
# fit and transform
data = trans.fit_transform(X)
# record number of features
num_features.append(data.shape[1])
# summarize
print('Degree: %d, Features: %d' % (d, data.shape[1]))
# plot degree vs number of features
pyplot.plot(degress, num_features)
pyplot.show()
运行该示例首先报告从 1 到 5 的度数以及数据集中的要素数量。
我们可以看到,1 度没有影响,特征的数量从 2 到 5 急剧增加。
这强调了对于除了非常小的数据集之外的任何数据集,应该使用 2 或 3 度来避免输入变量的急剧增加。
Degree: 1, Features: 61
Degree: 2, Features: 1891
Degree: 3, Features: 39711
Degree: 4, Features: 635376
Degree: 5, Features: 8259888
多项式特征变换的度与输入特征数的线图
更多的特征可能会导致更多的过拟合,进而导致更差的结果。
将多项式特征变换的次数视为超参数并测试数据集的不同值可能是一个好主意。
下面的示例探索了从 1 到 4 的度值,并评估了它们对所选模型的分类准确率的影响。
# explore the effect of degree on accuracy for the polynomial features transform
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# get the dataset
def get_dataset():
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
for d in range(1,5):
# define the pipeline
trans = PolynomialFeatures(degree=d)
model = KNeighborsClassifier()
models[str(d)] = Pipeline(steps=[('t', trans), ('m', model)])
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
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, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例会报告每个多项式次数的平均分类准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到,除了 3 级之外,表现通常比没有转换(1 级)差。
探索在执行转换之前或之后扩展数据,看看它如何影响模型表现,可能会很有趣。
>1 0.797 (0.073)
>2 0.793 (0.085)
>3 0.800 (0.077)
>4 0.795 (0.079)
创建方框图和触须图来总结每个多项式次数的分类准确度分数。
我们可以看到,表现保持平稳,也许有过拟合度为 4 的初步迹象。
声纳数据集上多项式特征变换的次数与 KNN 分类准确率的箱线图
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
书
蜜蜂
文章
摘要
在本教程中,您发现了如何将多项式特征变换用于带有数字输入变量的特征工程。
具体来说,您了解到:
- 一些机器学习算法更喜欢多项式输入特征或在多项式输入特征下表现更好。
- 如何使用多项式特征变换为预测建模创建新版本的输入变量。
- 多项式的次数如何影响由变换创建的输入要素的数量。
你有什么问题吗?
在下面的评论中提问,我会尽力回答。
如何为机器学习使用幂变换
原文:https://machinelearningmastery.com/power-transforms-with-Sklearn/
最后更新于 2020 年 8 月 28 日
像线性回归和高斯朴素贝叶斯这样的机器学习算法假设数值变量具有高斯概率分布。
您的数据可能没有高斯分布,而是可能有类似高斯的分布(例如接近高斯但有异常值或偏斜)或完全不同的分布(例如指数分布)。
因此,通过将输入和/或输出变量转换为高斯或多高斯分布,您可能能够在各种机器学习算法上获得更好的表现。像 Box-Cox 变换和 Yeo-Johnson 变换这样的幂变换提供了一种对数据执行这些变换的自动方法,并且在 Sklearn Python 机器学习库中提供。
在本教程中,您将发现如何在 scikit 中使用幂变换-学习如何使变量更高斯化以进行建模。
完成本教程后,您将知道:
- 当数值变量具有高斯概率分布时,许多机器学习算法更喜欢或表现得更好。
- 幂变换是一种将数值输入或输出变量变换为高斯或更似高斯的概率分布的技术。
- 如何在 scikit 中使用 PowerTransform 学习在为预测建模准备数据时使用 Box-Cox 和 Yeo-Johnson 转换。
用我的新书机器学习的数据准备启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何使用 scikit 进行电源转换-学习
图片由伊恩·d·基廷提供,版权所有。
教程概述
本教程分为五个部分;它们是:
- 让数据更高斯化
- 动力转换
- 声纳数据集
- Box-Cox 变换
- 约-约翰逊变换
让数据更高斯化
当变量分布为高斯分布时,许多机器学习算法的表现更好。
回想一下,每个变量的观测值可能被认为是从概率分布中得出的。高斯分布是常见的钟形分布。常见到经常被称为“正态分布。
有关高斯概率分布的更多信息,请参见教程:
一些算法,如线性回归和逻辑回归,明确假设实值变量具有高斯分布。其他非线性算法可能没有这种假设,但当变量具有高斯分布时,往往表现更好。
这既适用于分类和回归任务中的实值输入变量,也适用于回归任务中的实值目标变量。
有一些数据准备技术可以用来转换每个变量,使分布为高斯分布,或者如果不是高斯分布,则更像高斯分布。
当数据分布开始时几乎是高斯分布,并且受到偏斜或异常值的影响时,这些变换最有效。
转换的另一个常见原因是消除分布偏斜度。非偏斜分布是一种大致对称的分布。这意味着落在分布均值两侧的概率大致相等
—第 31 页,应用预测建模,2013 年。
幂变换指的是一类使用幂函数(如对数或指数)来使变量的概率分布为高斯或类高斯分布的技术。
有关使变量高斯化的更多信息,请参见教程:
动力转换
一个幂变换会让一个变量的概率分布更高斯。
这通常被描述为消除分布中的偏斜,尽管更一般地被描述为稳定分布的方差。
对数变换是称为幂变换的变换族的一个具体例子。用统计学术语来说,这些是稳定方差的变换。
—第 23 页,机器学习的特征工程,2018。
我们可以通过计算变量的对数或平方根来直接应用幂变换,尽管这可能是也可能不是给定变量的最佳幂变换。
用对数、平方根或倒数替换数据可能有助于消除偏差。
—第 31 页,应用预测建模,2013 年。
相反,我们可以使用广义版本的变换,它找到一个参数( lambda )来最好地将变量变换为高斯概率分布。
这种自动功率变换有两种流行的方法;它们是:
- Box-Cox 变换
- 约-约翰逊变换
然后,转换后的训练数据集可以被馈送到机器学习模型,以学习预测建模任务。
超参数,通常称为λ,用于控制变换的性质。
…统计方法可用于根据经验确定适当的转换。Box 和 Cox (1964)提出了一系列由参数索引的转换,表示为 lambda
—第 32 页,应用预测建模,2013 年。
以下是一些常见的λ值
- λ=-1。是一种相互转换。
- λ=-0.5 是倒数平方根变换。
- λ= 0.0 是对数变换。
- λ= 0.5 是平方根变换。
- λ= 1.0 为无变换。
在每个变量的转换中使用的这个超参数的最优值可以被存储和重用,以便将来以相同的方式转换新数据,例如测试数据集或将来的新数据。
这些电源转换可通过电源转换器类在 Sklearn Python 机器学习库中获得。
该类采用名为“方法的参数,该参数可以设置为“约-约翰逊或“ box-cox ”作为首选方法。它还将在转换后自动标准化数据,这意味着每个变量都将具有零均值和单位方差。这可以通过将“标准化”参数设置为假来关闭。
我们可以用一个小的工作示例来演示电力变压器。我们可以生成随机高斯数的样本,并通过计算指数对分布施加偏斜。然后,电力变压器可用于自动消除数据偏差。
下面列出了完整的示例。
# demonstration of the power transform on data with a skew
from numpy import exp
from numpy.random import randn
from sklearn.preprocessing import PowerTransformer
from matplotlib import pyplot
# generate gaussian data sample
data = randn(1000)
# add a skew to the data distribution
data = exp(data)
# histogram of the raw data with a skew
pyplot.hist(data, bins=25)
pyplot.show()
# reshape data to have rows and columns
data = data.reshape((len(data),1))
# power transform the raw data
power = PowerTransformer(method='yeo-johnson', standardize=True)
data_trans = power.fit_transform(data)
# histogram of the transformed data
pyplot.hist(data_trans, bins=25)
pyplot.show()
运行该示例首先创建一个 1,000 个随机高斯值的样本,并向数据集添加一个倾斜。
从倾斜的数据集中创建直方图,并清楚地显示被推到最左边的分布。
偏斜高斯分布直方图
然后使用电力变压器使数据分布更具高斯性,并将结果标准化,以平均值 0 和标准偏差 1.0 为中心。
创建变换数据的直方图,显示更高斯形状的数据分布。
幂变换后偏斜高斯数据的直方图
在接下来的几节中,我们将详细了解如何在真实数据集上使用这两种幂变换。
接下来,让我们介绍数据集。
声纳数据集
声纳数据集是用于二进制分类的标准机器学习数据集。
它包括 60 个实值输入和一个 2 类目标变量。数据集中有 208 个示例,类别相当均衡。
使用重复的分层 10 倍交叉验证,基线分类算法可以达到大约 53.4%的分类准确率。使用重复的分层 10 倍交叉验证,该数据集的最高表现约为 88%。
该数据集描述了岩石或模拟地雷的雷达回波。
您可以从这里了解有关数据集的更多信息:
不需要下载数据集;我们将从我们的工作示例中自动下载它。
首先,让我们加载并总结数据集。下面列出了完整的示例。
# load and summarize the sonar dataset
from pandas import read_csv
from pandas.plotting import scatter_matrix
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# summarize the shape of the dataset
print(dataset.shape)
# summarize each variable
print(dataset.describe())
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例首先总结加载数据集的形状。
这确认了 60 个输入变量、一个输出变量和 208 行数据。
提供了输入变量的统计摘要,显示值是数值,范围大约从 0 到 1。
(208, 61)
0 1 2 ... 57 58 59
count 208.000000 208.000000 208.000000 ... 208.000000 208.000000 208.000000
mean 0.029164 0.038437 0.043832 ... 0.007949 0.007941 0.006507
std 0.022991 0.032960 0.038428 ... 0.006470 0.006181 0.005031
min 0.001500 0.000600 0.001500 ... 0.000300 0.000100 0.000600
25% 0.013350 0.016450 0.018950 ... 0.003600 0.003675 0.003100
50% 0.022800 0.030800 0.034300 ... 0.005800 0.006400 0.005300
75% 0.035550 0.047950 0.057950 ... 0.010350 0.010325 0.008525
max 0.137100 0.233900 0.305900 ... 0.044000 0.036400 0.043900
[8 rows x 60 columns]
最后,为每个输入变量创建一个直方图。
如果我们忽略图中杂乱的东西,专注于直方图本身,我们可以看到许多变量都有一个偏斜的分布。
数据集为使用幂变换使变量更具高斯性提供了一个很好的候选对象。
声纳二进制类别数据集输入变量的直方图
接下来,让我们在原始数据集上拟合和评估一个机器学习模型。
我们将使用带有默认超参数的 k 最近邻算法,并使用重复的分层 K 折交叉验证对其进行评估。下面列出了完整的示例。
# evaluate knn on the raw sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define and configure the model
model = KNeighborsClassifier()
# evaluate the model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report model performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会评估原始声纳数据集上的 KNN 模型。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,该模型实现了大约 79.7%的平均分类准确率,表明它具有技巧性(优于 53.4%),并且处于良好表现的球园区(88%)。
Accuracy: 0.797 (0.073)
接下来,让我们探索数据集的 Box-Cox 幂变换。
Box-Cox 变换
Box-Cox 变换以该方法的两位作者的名字命名。
这是一种幂变换,假设它所应用的输入变量的值为严格正。这意味着不支持 0 和负值。
需要注意的是,Box-Cox 程序只能应用于严格正的数据。
—第 123 页,特征工程与选择,2019。
我们可以使用 PowerTransformer 类应用 Box-Cox 变换,并将“方法参数设置为“ box-cox ”。一旦定义,我们就可以调用 fit_transform() 函数,并将其传递给我们的数据集,以创建数据集的 Box-Cox 转换版本。
...
pt = PowerTransformer(method='box-cox')
data = pt.fit_transform(data)
我们的数据集没有负值,但可能有零值。这可能会导致问题。
我们还是试试吧。
下面列出了创建声纳数据集的 Box-Cox 变换并绘制结果直方图的完整示例。
# visualize a box-cox transform of the sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import PowerTransformer
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a box-cox transform of the dataset
pt = PowerTransformer(method='box-cox')
data = pt.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例会导致如下错误:
ValueError: The Box-Cox transformation can only be applied to strictly positive data
不出所料,我们无法对原始数据使用转换,因为它不是严格正的。
解决这个问题的一种方法是使用 MixMaxScaler 变换首先将数据缩放到正值,然后应用该变换。
我们可以使用管道对象依次应用两种变换;例如:
...
# perform a box-cox transform of the dataset
scaler = MinMaxScaler(feature_range=(1, 2))
power = PowerTransformer(method='box-cox')
pipeline = Pipeline(steps=[('s', scaler),('p', power)])
data = pipeline.fit_transform(data)
下面列出了将 Box-Cox 变换应用于缩放数据集的更新版本。
# visualize a box-cox transform of the scaled sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import PowerTransformer
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a box-cox transform of the dataset
scaler = MinMaxScaler(feature_range=(1, 2))
power = PowerTransformer(method='box-cox')
pipeline = Pipeline(steps=[('s', scaler),('p', power)])
data = pipeline.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例会转换数据集并绘制每个输入变量的直方图。
我们可以看到,每个变量的直方图形状看起来比原始数据更高斯。
声纳数据集的 Box-Cox 变换输入变量直方图
接下来,让我们评估与上一节相同的 KNN 模型,但是在这种情况下是在缩放数据集的 Box-Cox 变换上。
下面列出了完整的示例。
# evaluate knn on the box-cox sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import PowerTransformer
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
scaler = MinMaxScaler(feature_range=(1, 2))
power = PowerTransformer(method='box-cox')
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('s', scaler),('p', power), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到 Box-Cox 变换将表现从没有变换时的 79.7%提升到有变换时的 81.1%。
Accuracy: 0.811 (0.085)
接下来,让我们仔细看看杨-约翰逊变换。
约-约翰逊变换
杨-约翰逊变换也以作者的名字命名。
与 Box-Cox 变换不同,它不要求每个输入变量的值严格为正。它支持零值和负值。这意味着我们可以将其应用于数据集,而无需先对其进行缩放。
我们可以通过定义一个 PowerTransform 对象并将“方法”参数设置为“ yeo-johnson ”(默认值)来应用转换。
...
# perform a yeo-johnson transform of the dataset
pt = PowerTransformer(method='yeo-johnson')
data = pt.fit_transform(data)
下面的示例应用了约-约翰逊变换,并创建了每个变换变量的直方图。
# visualize a yeo-johnson transform of the sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import PowerTransformer
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a yeo-johnson transform of the dataset
pt = PowerTransformer(method='yeo-johnson')
data = pt.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例会转换数据集并绘制每个输入变量的直方图。
我们可以看到,每个变量的直方图形状看起来比原始数据更高斯,很像 box-cox 变换。
声纳数据集的约-约翰逊变换输入变量直方图
接下来,让我们评估与上一节相同的 KNN 模型,但在本例中是对原始数据集的 Yeo-Johnson 变换。
下面列出了完整的示例。
# evaluate knn on the yeo-johnson sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import PowerTransformer
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
power = PowerTransformer(method='yeo-johnson')
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('p', power), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到 Yeo-Johnson 变换将表现从没有变换时的 79.7%提升到有变换时的约 80.8%,低于达到约 81.1%的 Box-Cox 变换。
Accuracy: 0.808 (0.082)
有时,通过在执行约-约翰逊变换之前首先标准化原始数据集,可以提高表现。
我们可以通过添加一个标准缩放器来探索这一点,作为管道的第一步。
下面列出了完整的示例。
# evaluate knn on the yeo-johnson standardized sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import PowerTransformer
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
scaler = StandardScaler()
power = PowerTransformer(method='yeo-johnson')
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('s', scaler), ('p', power), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到,在 Yeo-Johnson 转换之前对数据进行标准化导致表现从约 80.8%小幅提升至约 81.6%,比 Box-Cox 转换的结果略有提升。
Accuracy: 0.816 (0.077)
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
书
资料组
蜜蜂
文章
摘要
在本教程中,您发现了如何在 scikit 中使用幂变换-学习使变量更高斯化以进行建模。
具体来说,您了解到:
- 当数值变量具有高斯概率分布时,许多机器学习算法更喜欢或表现得更好。
- 幂变换是一种将数值输入或输出变量变换为高斯或更似高斯的概率分布的技术。
- 如何在 scikit 中使用 PowerTransform 学习在为预测建模准备数据时使用 Box-Cox 和 Yeo-Johnson 转换。
你有什么问题吗?
在下面的评论中提问,我会尽力回答。
Python 中用于降维的主成分分析
最后更新于 2020 年 8 月 18 日
减少预测模型的输入变量的数量被称为降维。
较少的输入变量可以导致更简单的预测模型,该模型在对新数据进行预测时可能具有更好的表现。
机器学习中最流行的降维技术可能是主成分分析,简称 PCA。这是一种来自线性代数领域的技术,可以用作数据准备技术,在拟合模型之前创建数据集的投影。
在本教程中,您将发现如何在开发预测模型时使用主成分分析进行降维。
完成本教程后,您将知道:
- 降维包括减少建模数据中输入变量或列的数量。
- 主成分分析是一种来自线性代数的技术,可用于自动执行降维。
- 如何评估使用主成分分析投影作为输入的预测模型,并使用新的原始数据进行预测。
用我的新书机器学习的数据准备启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
- 2020 年 5 月更新:改进代码注释。
美国农业部林务局Python
图片降维的主成分分析,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 降维与主成分分析
- 主成分分析试剂盒-学习应用编程接口
- 用于降维的主成分分析工作示例
降维与主成分分析
降维是指减少数据集的输入变量数量。
如果您的数据是用行和列来表示的,例如在电子表格中,那么输入变量就是作为输入提供给模型以预测目标变量的列。输入变量也称为特征。
我们可以将代表维度的数据列放在 n 维特征空间中,将数据行视为该空间中的点。这是数据集的一种有用的几何解释。
在具有 k 个数字属性的数据集中,您可以将数据可视化为 k 维空间中的点云…
—第 305 页,数据挖掘:实用机器学习工具与技术,2016 年第 4 版。
特征空间中有大量的维度可能意味着该空间的体积非常大,反过来,我们在该空间中的点(数据行)通常代表一个小的且不具有代表性的样本。
这可能会极大地影响机器学习算法在具有许多输入特征的数据上的表现,通常被称为“维度诅咒””
因此,通常希望减少输入特征的数量。这减少了特征空间的维数,因此得名“降维”
一种流行的降维方法是使用来自线性代数领域的技术。这通常被称为“T2”特征投影,使用的算法被称为“T4”投影方法
投影方法寻求减少特征空间中的维数,同时保留数据中观察到的变量之间最重要的结构或关系。
当处理高维数据时,通过将数据投影到捕捉数据“本质”的低维子空间来降低维数通常是有用的。这叫做降维。
—第 11 页,机器学习:概率视角,2012。
得到的数据集,即投影,可以用作训练机器学习模型的输入。
本质上,原始特征不再存在,而新特征是从与原始数据不直接可比的可用数据构建的,例如没有列名。
未来在进行预测时,任何新数据(如测试数据集和新数据集)都必须使用相同的技术进行投影。
主成分分析可能是最流行的降维技术。
最常见的降维方法叫做主成分分析。
—第 11 页,机器学习:概率视角,2012。
它可以被认为是一种投影方法,其中具有 m 列(特征)的数据被投影到具有 m 列或更少列的子空间中,同时保留原始数据的本质。
主成分分析方法可以用线性代数的工具来描述和实现,特别是像特征分解或奇异值分解那样的矩阵分解。
主成分分析可以被定义为数据到低维线性空间(称为主子空间)的正交投影,使得投影数据的方差最大化
—第 561 页,模式识别与机器学习,2006。
有关如何详细计算主成分分析的更多信息,请参见教程:
现在我们已经熟悉了用于降维的主成分分析,让我们看看如何将这种方法用于 Sklearn 库。
主成分分析试剂盒-学习应用编程接口
我们可以使用主成分分析来计算数据集的投影,并选择投影的多个维度或主成分作为模型的输入。
Sklearn 库提供了主成分分析类,它可以适合数据集,并用于转换训练数据集和未来的任何附加数据集。
例如:
...
data = ...
# define transform
pca = PCA()
# prepare transform on dataset
pca.fit(data)
# apply transform to dataset
transformed = pca.transform(data)
主成分分析的输出可以用作训练模型的输入。
也许最好的方法是使用管道,其中第一步是主成分分析变换,下一步是将变换后的数据作为输入的学习算法。
...
# define the pipeline
steps = [('pca', PCA()), ('m', LogisticRegression())]
model = Pipeline(steps=steps)
如果输入变量具有不同的单位或比例,在执行主成分分析变换之前对数据进行归一化也是一个好主意;例如:
...
# define the pipeline
steps = [('norm', MinMaxScaler()), ('pca', PCA()), ('m', LogisticRegression())]
model = Pipeline(steps=steps)
现在我们已经熟悉了这个应用编程接口,让我们来看一个工作示例。
用于降维的主成分分析工作示例
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题,其中 15 个输入是有意义的。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在拟合逻辑回归模型的同时对该数据集进行降维。
我们将使用管道,其中第一步执行主成分分析转换,并选择 10 个最重要的维度或组件,然后在这些特征上拟合逻辑回归模型。我们不需要标准化这个数据集中的变量,因为所有的变量都有相同的设计比例。
管道将使用重复分层交叉验证进行评估,重复三次,每次重复 10 次。表现表示为平均分类准确率。
下面列出了完整的示例。
# evaluate pca with logistic regression algorithm for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# define the pipeline
steps = [('pca', PCA(n_components=10)), ('m', LogisticRegression())]
model = Pipeline(steps=steps)
# evaluate model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行示例评估模型并报告分类准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到带有逻辑回归的主成分分析变换获得了大约 81.8%的表现。
Accuracy: 0.816 (0.034)
我们如何知道将输入的 20 个维度减少到 10 个是好的还是我们能做的最好的?
我们没有;10 是一个任意的选择。
更好的方法是用不同数量的输入特征评估相同的变换和模型,并选择导致最佳平均表现的特征数量(降维量)。
下面的示例执行了该实验,并总结了每种配置的平均分类准确率。
# compare pca number of components with logistic regression algorithm for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
for i in range(1,21):
steps = [('pca', PCA(n_components=i)), ('m', LogisticRegression())]
models[str(i)] = Pipeline(steps=steps)
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
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, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.xticks(rotation=45)
pyplot.show()
运行该示例首先报告所选组件或特征的每个数量的分类准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
随着维度数量的增加,我们看到了表现提高的总体趋势。在这个数据集上,结果显示了维度数量和模型分类准确率之间的权衡。
有趣的是,我们没有看到超过 15 个组件的任何改进。这与我们对问题的定义相匹配,其中只有前 15 个组件包含关于该类的信息,其余 5 个是冗余的。
>1 0.542 (0.048)
>2 0.713 (0.048)
>3 0.720 (0.053)
>4 0.723 (0.051)
>5 0.725 (0.052)
>6 0.730 (0.046)
>7 0.805 (0.036)
>8 0.800 (0.037)
>9 0.814 (0.036)
>10 0.816 (0.034)
>11 0.819 (0.035)
>12 0.819 (0.038)
>13 0.819 (0.035)
>14 0.853 (0.029)
>15 0.865 (0.027)
>16 0.865 (0.027)
>17 0.865 (0.027)
>18 0.865 (0.027)
>19 0.865 (0.027)
>20 0.865 (0.027)
为每个配置的尺寸数量的准确率分数的分布创建一个方框和触须图。
我们可以看到分类准确率随着组件数量的增加而增加的趋势,限制在 15。
主成分分析组件数量与分类准确率的箱线图
我们可以选择使用主成分分析变换和逻辑回归模型组合作为最终模型。
这包括在所有可用数据上拟合管道,并使用管道对新数据进行预测。重要的是,必须对这个新数据执行相同的转换,这是通过管道自动处理的。
以下示例提供了在新数据上拟合和使用带有主成分分析变换的最终模型的示例。
# make predictions using pca with logistic regression
from sklearn.datasets import make_classification
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# define the model
steps = [('pca', PCA(n_components=15)), ('m', LogisticRegression())]
model = Pipeline(steps=steps)
# fit the model on the whole dataset
model.fit(X, y)
# make a single prediction
row = [[0.2929949,-4.21223056,-1.288332,-2.17849815,-0.64527665,2.58097719,0.28422388,-7.1827928,-1.91211104,2.73729512,0.81395695,3.96973717,-2.66939799,3.34692332,4.19791821,0.99990998,-0.30201875,-4.43170633,-2.82646737,0.44916808]]
yhat = model.predict(row)
print('Predicted Class: %d' % yhat[0])
运行该示例使管道适用于所有可用数据,并对新数据进行预测。
这里,变换使用了 PCA 变换中最重要的 15 个分量,正如我们在上面的测试中发现的那样。
提供具有 20 列的新数据行,并自动转换为 15 个分量,并馈送到逻辑回归模型,以便预测类别标签。
Predicted Class: 1
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
书
- 机器学习:概率视角,2012。
- 数据挖掘:实用机器学习工具与技术,第 4 版,2016。
- 模式识别与机器学习,2006。
蜜蜂
文章
摘要
在本教程中,您发现了如何在开发预测模型时使用主成分分析进行降维。
具体来说,您了解到:
- 降维包括减少建模数据中输入变量或列的数量。
- 主成分分析是一种来自线性代数的技术,可用于自动执行降维。
- 如何评估使用主成分分析投影作为输入的预测模型,并使用新的原始数据进行预测。
你有什么问题吗?
在下面的评论中提问,我会尽力回答。
如何为机器学习使用分位数变换
原文:https://machinelearningmastery.com/quantile-transforms-for-machine-learning/
最后更新于 2020 年 8 月 28 日
数值输入变量可能具有高度偏斜或非标准分布。
这可能是由数据中的异常值、多模态分布、高度指数分布等引起的。
在回归的情况下,当数值输入变量甚至输出变量具有标准概率分布,例如高斯(正态)或均匀分布时,许多机器学习算法更喜欢或表现得更好。
分位数转换提供了一种自动方式来转换数字输入变量,使其具有不同的数据分布,进而可以用作预测模型的输入。
在本教程中,您将发现如何使用分位数转换来改变机器学习中数值变量的分布。
完成本教程后,您将知道:
- 当数值变量具有高斯或标准概率分布时,许多机器学习算法更喜欢或表现得更好。
- 分位数转换是一种将数值输入或输出变量转换为高斯或均匀概率分布的技术。
- 如何利用 QuantileTransformer 改变数值变量的概率分布,提高预测模型的表现。
用我的新书机器学习的数据准备启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何使用分位数变换进行机器学习。新西兰,保留部分权利。
教程概述
本教程分为五个部分;它们是:
- 更改数据分布
- 分位数变换
- 声纳数据集
- 正规分位数变换
- 均匀分位数变换
更改数据分布
当变量分布为高斯分布时,许多机器学习算法的表现更好。
回想一下,每个变量的观测值可能被认为是从概率分布中得出的。高斯分布是常见的钟形分布。常见到经常被称为“正态分布。
有关高斯概率分布的更多信息,请参见教程:
一些算法,如线性回归和逻辑回归,明确假设实值变量具有高斯分布。其他非线性算法可能没有这种假设,但当变量具有高斯分布时,往往表现更好。
这既适用于分类和回归任务中的实值输入变量,也适用于回归任务中的实值目标变量。
一些输入变量可能具有高度偏斜的分布,例如指数分布,其中最常见的观测值聚集在一起。一些输入变量可能有异常值,导致分布高度分散。
这些问题和其他问题,如非标准分布和多模态分布,会使数据集难以用一系列机器学习模型建模。
因此,通常希望将每个输入变量转换成标准概率分布,例如高斯(正态)分布或均匀分布。
分位数变换
分位数变换将变量的概率分布映射到另一个概率分布。
回想一下分位数函数,也称为百分比点函数(PPF),是累积概率分布(CDF)的倒数。CDF 是一个函数,它返回一个值达到或低于给定值的概率。PPF 是这个函数的逆函数,在给定的概率下返回这个值。
分位数函数对观测值之间的关系进行排序或平滑,并且可以映射到其他分布上,例如均匀分布或正态分布。
该变换可以应用于训练数据集中的每个数字输入变量,然后作为输入提供给机器学习模型,以学习预测建模任务。
这个分位数转换可以通过quantilettransformer 类在 Sklearn Python 机器学习库中获得。
该类有一个“ output_distribution ”参数,可以设置为“制服”或“普通”,默认为“制服”。
它还提供了一个“n _ 分位数”,该分位数决定了数据集内观测值的映射或排序的分辨率。必须将该值设置为小于数据集中观测值数量的值,并默认为 1,000。
我们可以用一个小的工作示例来演示quantilettransformer。我们可以生成随机高斯数的样本,并通过计算指数对分布施加偏斜。然后可以使用量化转换器将数据集转换为另一个分布,在这种情况下,转换回高斯分布。
下面列出了完整的示例。
# demonstration of the quantile transform
from numpy import exp
from numpy.random import randn
from sklearn.preprocessing import QuantileTransformer
from matplotlib import pyplot
# generate gaussian data sample
data = randn(1000)
# add a skew to the data distribution
data = exp(data)
# histogram of the raw data with a skew
pyplot.hist(data, bins=25)
pyplot.show()
# reshape data to have rows and columns
data = data.reshape((len(data),1))
# quantile transform the raw data
quantile = QuantileTransformer(output_distribution='normal')
data_trans = quantile.fit_transform(data)
# histogram of the transformed data
pyplot.hist(data_trans, bins=25)
pyplot.show()
运行该示例首先创建一个 1,000 个随机高斯值的样本,并向数据集添加一个倾斜。
从倾斜的数据集中创建直方图,并清楚地显示被推到最左边的分布。
偏斜高斯分布直方图
然后使用quantilettransformer映射数据分布高斯并标准化结果,以平均值 0 和标准偏差 1.0 为中心。
创建变换数据的直方图,显示高斯形状的数据分布。
分位数变换后偏斜高斯数据的直方图
在接下来的几节中,我们将详细了解如何在真实数据集上使用分位数转换。
接下来,让我们介绍数据集。
声纳数据集
声纳数据集是用于二进制分类的标准机器学习数据集。
它涉及 60 个实值输入和一个两类目标变量。数据集中有 208 个示例,类别相当均衡。
使用重复的分层 10 倍交叉验证,基线分类算法可以达到大约 53.4%的分类准确率。使用重复的分层 10 倍交叉验证,该数据集的最高表现约为 88%。
该数据集描述了岩石或模拟地雷的声纳回波。
您可以从这里了解有关数据集的更多信息:
不需要下载数据集;我们将从我们的工作示例中自动下载它。
首先,让我们加载并总结数据集。下面列出了完整的示例。
# load and summarize the sonar dataset
from pandas import read_csv
from pandas.plotting import scatter_matrix
from matplotlib import pyplot
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# summarize the shape of the dataset
print(dataset.shape)
# summarize each variable
print(dataset.describe())
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例首先总结加载数据集的形状。
这确认了 60 个输入变量、一个输出变量和 208 行数据。
提供了输入变量的统计摘要,显示值是数值,范围大约从 0 到 1。
(208, 61)
0 1 2 ... 57 58 59
count 208.000000 208.000000 208.000000 ... 208.000000 208.000000 208.000000
mean 0.029164 0.038437 0.043832 ... 0.007949 0.007941 0.006507
std 0.022991 0.032960 0.038428 ... 0.006470 0.006181 0.005031
min 0.001500 0.000600 0.001500 ... 0.000300 0.000100 0.000600
25% 0.013350 0.016450 0.018950 ... 0.003600 0.003675 0.003100
50% 0.022800 0.030800 0.034300 ... 0.005800 0.006400 0.005300
75% 0.035550 0.047950 0.057950 ... 0.010350 0.010325 0.008525
max 0.137100 0.233900 0.305900 ... 0.044000 0.036400 0.043900
[8 rows x 60 columns]
最后为每个输入变量创建一个直方图。
如果我们忽略图中杂乱的东西,专注于直方图本身,我们可以看到许多变量都有一个偏斜的分布。
数据集为使用分位数变换使变量更具高斯性提供了一个很好的候选对象。
声纳二进制类别数据集输入变量的直方图
接下来,让我们在原始数据集上拟合和评估一个机器学习模型。
我们将使用带有默认超参数的 k 近邻算法,并使用重复分层 K 折交叉验证对其进行评估。下面列出了完整的示例。
# evaluate knn on the raw sonar dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define and configure the model
model = KNeighborsClassifier()
# evaluate the model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report model performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会评估原始声纳数据集上的 KNN 模型。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,该模型实现了大约 79.7%的平均分类准确率,表明它具有技巧性(优于 53.4%),并且处于良好表现的球园区(88%)。
Accuracy: 0.797 (0.073)
接下来,让我们探索数据集的正常分位数转换。
正规分位数变换
通常希望将输入变量转换为具有正态概率分布,以提高建模表现。
我们可以使用quantilettransformer类应用分位数转换,并将“输出 _ 分布参数设置为“正常”。我们还必须将“n _ 分位数”参数设置为小于训练数据集中观测值数量的值,在本例中为 100。
一旦定义,我们就可以调用 fit_transform() 函数,并将其传递给我们的数据集,以创建数据集的分位数转换版本。
...
# perform a normal quantile transform of the dataset
trans = QuantileTransformer(n_quantiles=100, output_distribution='normal')
data = trans.fit_transform(data)
让我们在声纳数据集上试试。
下面列出了创建声纳数据集的正常分位数变换并绘制结果直方图的完整示例。
# visualize a normal quantile transform of the sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import QuantileTransformer
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a normal quantile transform of the dataset
trans = QuantileTransformer(n_quantiles=100, output_distribution='normal')
data = trans.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例会转换数据集并绘制每个输入变量的直方图。
我们可以看到,与原始数据相比,每个变量的直方图形状看起来非常高斯。
声纳数据集正常分位数转换输入变量的直方图
接下来,让我们评估与上一节相同的 KNN 模型,但在这种情况下是基于数据集的正常分位数变换。
下面列出了完整的示例。
# evaluate knn on the sonar dataset with normal quantile transform
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import QuantileTransformer
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
trans = QuantileTransformer(n_quantiles=100, output_distribution='normal')
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('t', trans), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到正常的分位数变换将表现从没有变换时的 79.7%提升到有变换时的约 81.7%。
Accuracy: 0.817 (0.087)
接下来,让我们仔细看看均匀分位数变换。
均匀分位数变换
有时,将高度指数或多模态分布转换为均匀分布可能是有益的。
这对于值范围大且稀疏的数据尤其有用,例如,异常值是常见的而不是罕见的。
我们可以通过定义一个quantilettransformer类并将“ output_distribution ”参数设置为“ uniform ”(默认值)来应用转换。
...
# perform a uniform quantile transform of the dataset
trans = QuantileTransformer(n_quantiles=100, output_distribution='uniform')
data = trans.fit_transform(data)
以下示例应用统一分位数变换,并创建每个变换变量的直方图。
# visualize a uniform quantile transform of the sonar dataset
from pandas import read_csv
from pandas import DataFrame
from pandas.plotting import scatter_matrix
from sklearn.preprocessing import QuantileTransformer
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
# retrieve just the numeric input values
data = dataset.values[:, :-1]
# perform a uniform quantile transform of the dataset
trans = QuantileTransformer(n_quantiles=100, output_distribution='uniform')
data = trans.fit_transform(data)
# convert the array back to a dataframe
dataset = DataFrame(data)
# histograms of the variables
dataset.hist()
pyplot.show()
运行该示例会转换数据集并绘制每个输入变量的直方图。
我们可以看到,与原始数据相比,每个变量的直方图形状看起来非常一致。
声纳数据集的均匀分位数变换输入变量的直方图
接下来,让我们评估与上一节相同的 KNN 模型,但在这种情况下是对原始数据集的统一分位数变换。
下面列出了完整的示例。
# evaluate knn on the sonar dataset with uniform quantile transform
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import QuantileTransformer
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
# define the pipeline
trans = QuantileTransformer(n_quantiles=100, output_distribution='uniform')
model = KNeighborsClassifier()
pipeline = Pipeline(steps=[('t', trans), ('m', model)])
# evaluate the pipeline
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report pipeline performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例,我们可以看到均匀变换将表现从没有变换时的 79.7%提升到有变换时的 84.5%,优于得分为 81.7%的正常变换。
Accuracy: 0.845 (0.074)
我们选择分位数作为任意数,在本例中为 100。
这个超参数可以被调整来探索变换的分辨率对模型的最终技能的影响。
下面的示例执行了该实验,并绘制了从 1 到 99 的不同“n _ 分位数”值的平均准确率。
# explore number of quantiles on classification accuracy
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import QuantileTransformer
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
from matplotlib import pyplot
# get the dataset
def get_dataset():
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv"
dataset = read_csv(url, header=None)
data = dataset.values
# separate into input and output columns
X, y = data[:, :-1], data[:, -1]
# ensure inputs are floats and output is an integer label
X = X.astype('float32')
y = LabelEncoder().fit_transform(y.astype('str'))
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
for i in range(1,100):
# define the pipeline
trans = QuantileTransformer(n_quantiles=i, output_distribution='uniform')
model = KNeighborsClassifier()
models[str(i)] = Pipeline(steps=[('t', trans), ('m', model)])
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
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, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results = list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(mean(scores))
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.plot(results)
pyplot.show()
运行该示例会报告“n _ 分位数”参数的每个值的平均分类准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,令人惊讶的是,较小的值导致更好的准确性,例如 4 的值达到了大约 85.4%的准确性。
>1 0.466 (0.016)
>2 0.813 (0.085)
>3 0.840 (0.080)
>4 0.854 (0.075)
>5 0.848 (0.072)
>6 0.851 (0.071)
>7 0.845 (0.071)
>8 0.848 (0.066)
>9 0.848 (0.071)
>10 0.843 (0.074)
...
会创建一个折线图,显示转换中使用的分位数与所得模型的分类准确率。
我们可以看到一个值小于 10 的凸起,之后表现下降并持平。
结果强调,探索不同的分布和分位数可能会有一些好处,看看是否可以实现更好的表现。
声纳数据集上分位数与 KNN 分类准确率的线图
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
资料组
蜜蜂
文章
摘要
在本教程中,您发现了如何使用分位数转换来改变机器学习中数值变量的分布。
具体来说,您了解到:
- 当数值变量具有高斯或标准概率分布时,许多机器学习算法更喜欢或表现得更好。
- 分位数转换是一种将数值输入或输出变量转换为高斯或均匀概率分布的技术。
- 如何利用 QuantileTransformer 改变数值变量的概率分布,提高预测模型的表现。
你有什么问题吗?
在下面的评论中提问,我会尽力回答。