6.3 数据预处理¶
sklearn.preprocessing
包提供了几个常用的实用函数和转换器类,用以将原始特征向量更改为更适合下游估计器的表示形式。
通常,学习算法受益于数据集的标准化。如果数据集中存在一些异常值,则更适合使用健壮的缩放器或转换器。不同缩放器,转换器和规范化器在包含边缘异常值的数据集上的行为突出显示了比较不同缩放器对含有异常值数据的效果。
6.3.1 标准化或均值去除和方差缩放
数据集的标准化是scikit-learn中实现许多机器学习估计器的普遍要求;如果个别特征看起来或多或少不像标准正态分布数据:均值和单位方差为零的高斯分布,则它们的性能可能不好。
在实践中,我们通常会忽略分布的形状,而只是通过删除每个特征的平均值来实现特征数据中心化,然后除以非常数特征的标准差来缩放数据。
例如,学习算法的目标函数中使用的许多元素(例如支持向量机的RBF内核或线性模型的l1和l2正则化器)都假定所有特征都围绕零为中心并且具有相同阶数的方差。如果某个特征的方差比其他特征大几个数量级,则它可能会极大影响目标函数,并使估计器无法按预期从其他特征中正确学习。
scale
函数提供了一种简单快捷的方法来对单个类似数组的数据集执行此操作:
>>> from sklearn import preprocessing
>>> import numpy as np
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
>>> X_scaled = preprocessing.scale(X_train)
>>> X_scaled
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
缩放的数据具有0均值和单位方差:
>>> X_scaled.mean(axis=0)
array([0., 0., 0.])
>>> X_scaled.std(axis=0)
array([1., 1., 1.])
preprocessing
模块还提供了一个实用程序类StandardScaler
,它使Transformer
API来计算训练集上的均值和标准差,以便以后能够在测试集上重新应用相同的转换。因此,该类适用于 sklearn.pipeline.Pipeline
的早期步骤:
>>> scaler = preprocessing.StandardScaler().fit(X_train)
>>> scaler
StandardScaler()
>>> scaler.mean_
array([1. ..., 0. ..., 0.33...])
>>> scaler.scale_
array([0.81..., 0.81..., 1.24...])
>>> scaler.transform(X_train)
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
然后可以将缩放器实例用于新数据以实现与训练集相同的转换方式:
>>> X_test = [[-1., 1., 0.]]
>>> scaler.transform(X_test)
array([[-2.44..., 1.22..., -0.26...]])
可以通过将with_mean=False
或with_std=False
传递给StandardScaler
的构造函数来取消居中或缩放。
6.3.1.1 将特征缩放至特定范围内
另一种标准化方法是将特征值缩放到给定的最小值和最大值之间,通常介于零和一之间,或者将每个特征的最大绝对值缩放到单位大小,上述操作可以分别使用MinMaxScaler
或MaxAbsScaler
来实现。
使用这种缩放的目的包括对特征极小标准偏差的稳健性以及在稀疏数据中保留零元素。
这是将简单的数据矩阵缩放到[0, 1]
范围的示例:
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
...
>>> min_max_scaler = preprocessing.MinMaxScaler()
>>> X_train_minmax = min_max_scaler.fit_transform(X_train)
>>> X_train_minmax
array([[0.5 , 0. , 1. ],
[1. , 0.5 , 0.33333333],
[0. , 1. , 0. ]])
然后,相同的转换实例可以被用与在训练过程中不可见的测试数据:实现和训练数据一致的缩放和移位操作:
>>> X_test = np.array([[-3., -1., 4.]])
>>> X_test_minmax = min_max_scaler.transform(X_test)
>>> X_test_minmax
array([[-1.5 , 0. , 1.66666667]])
可以检查缩放器(scaler)属性,以找到在训练数据上学习到的转换的确切性质:
>>> min_max_scaler.scale_
array([0.5 , 0.5 , 0.33...])
>>> min_max_scaler.min_
array([0. , 0.5 , 0.33...])
如果给MinMaxScaler
一个明确的feature_range=(min, max)
,则完整公式为:
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
MaxAbsScaler
的工作方式都非常相似,通过除以每个特征中的最大值来使训练数据位于[-1, 1]
范围内的方式进行缩放。这意味着它适用于已经以零为中心的数据或稀疏数据。
这是在此缩放器上使用上一示例中少量数据的示例:
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
...
>>> max_abs_scaler = preprocessing.MaxAbsScaler()
>>> X_train_maxabs = max_abs_scaler.fit_transform(X_train)
>>> X_train_maxabs
array([[ 0.5, -1. , 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -0.5]])
>>> X_test = np.array([[ -3., -1., 4.]])
>>> X_test_maxabs = max_abs_scaler.transform(X_test)
>>> X_test_maxabs
array([[-1.5, -1. , 2. ]])
>>> max_abs_scaler.scale_
array([2., 1., 2.])
与scale
一样,如果您不想创建对象,该模块进一步提供了 minmax_scale
和maxabs_scale
函数。
6.3.1.2 缩放稀疏数据
中心化稀疏数据会破坏数据的稀疏结构,因此明智的做法是少做这样的操作。但是,缩放稀疏输入是有意义的,尤其是当特征处于不同的缩放比例时。
MaxAbsScaler
和maxabs_scale
是专门为缩放稀疏数据而设计的,并且是实现此目的的推荐方法。然而,只要with_mean=False
显式地传递给构造函数,scale
和StandardScaler
可以接受scipy.sparse
的矩阵作为输入。否则,将引发ValueError
,因为静默居中会破坏稀疏性,并经常由于无意中分配过多的内存而使执行崩溃。 RobustScaler
不能适合稀疏输入,但是可以在稀疏输入上使用transform
方法。
请注意,缩放器接受压缩的稀疏行和压缩的稀疏列格式(请参阅scipy.sparse.csr_matrix
和 scipy.sparse.csc_matrix
)。任何其他稀疏输入都将转换为“压缩稀疏行”表示形式。为避免不必要的内存副本,建议在初期选择CSR或CSC表示形式。
最后,如果已经中心化的数据足够小,则使用稀疏矩阵的toarray
方法将输入的数据显式转换为数组是另一种选择。
6.3.1.3 缩放包含离群值的数据
如果数据中包含许多离群值,使用数据的均值和方差进行缩放可能效果不佳。在这种情况下,可以使用 robust_scale
和RobustScaler
作为替代产品。他们对数据的中心和范围的估计更可靠。
参考文献:
常见问题解答中提供了有关对数据进行居中和缩放的重要性的进一步讨论:是否应该对数据进行标准化/标准化/缩放
Scaling vs Whitening
有时候独立地中心化和缩放数据是不够的,因为下游模型可以进一步对特征间的线性独立性做出一些假设。
要解决此问题,您可以使用
sklearn.decomposition.PCA
并指定参数whiten=True
以进一步消除特征间的线性相关性。缩放一维数组
所有上述功能(即
scale
,minmax_scale
,和robust_scale
)都接受一维数组,这在某些特定的情况下很有用。
6.3.1.4 核矩阵的中心化
如果您拥有一个内核 的内核矩阵,可以在函数定义的特征空间中计算点积,[`KernelCenterer`](https://scikit-learn.org.cn/view/724.html)类可以转换该内核矩阵使其包含由函数 定义的特征空间中的内部乘积,然后删除该空间中的均值。
6.3.2 非线性转换
有两种类型的转换是可行的:分位数转换和幂转换。分位数和幂变换都基于特征的单调变换,从而保持了每个特征值的秩。
分位数变换基于公式 将所有特征置于相同的期望分布中,其中 是特征的累积分布函数,并且 是期望输出分布的 分位数函数。该公式使用了以下两个事实:(i)如果 是具有连续累积分布函数 的随机变量,则 均匀分布在上; (ii)如果 是在 上符合均匀分布的一个随机变量,则 有分布。通过执行秩变换,分位数变换可以平滑不寻常的分布,并且与缩放方法相比,离群值的影响较小。但是,它确实扭曲了特征之间的相关性和距离。
幂变换是一组参数变换,旨在将数据从任何分布映射到接近高斯分布。
6.3.2.1 映射到均匀分布
QuantileTransformer
和quantile_transform
提供了一种非参数转换,以将数据映射到值介于0和1之间的均匀分布:
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> X, y = load_iris(return_X_y=True)
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
>>> quantile_transformer = preprocessing.QuantileTransformer(random_state=0)
>>> X_train_trans = quantile_transformer.fit_transform(X_train)
>>> X_test_trans = quantile_transformer.transform(X_test)
>>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100])
array([ 4.3, 5.1, 5.8, 6.5, 7.9])
此特征对应以厘米为单位的花萼长度。一旦应用了分位数转换,这些界标便会接近先前定义的百分位数:
>>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.00... , 0.24..., 0.49..., 0.73..., 0.99... ])
可以在带有类似注释的独立测试集上对此进行确认:
>>> np.percentile(X_test[:, 0], [0, 25, 50, 75, 100])
...
array([ 4.4 , 5.125, 5.75 , 6.175, 7.3 ])
>>> np.percentile(X_test_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.01..., 0.25..., 0.46..., 0.60... , 0.94...])
6.3.2.2 映射到高斯分布
在许多建模场景中,需要对数据集中特征进行正态化。幂变换是一组参数化的单调变换,旨在将数据从任何分布映射到尽可能接近高斯分布,以稳定方差并最小化偏度。
PowerTransformer
目前提供两种这样的幂变换,即Yeo-Johnson变换和Box-Cox变换。
以下为Yeo-Johnson 变换:
以下为Box-Cox变换:
Box-Cox仅可应用于严格的正数据。在这两种方法中,变换都是通过最大似然估计确定的的参数化。这是使用Box-Cox将从服从对数正态分布的样本映射到正态分布的示例:
>>> pt = preprocessing.PowerTransformer(method='box-cox', standardize=False)
>>> X_lognormal = np.random.RandomState(616).lognormal(size=(3, 3))
>>> X_lognormal
array([[1.28..., 1.18..., 0.84...],
[0.94..., 1.60..., 0.38...],
[1.35..., 0.21..., 1.09...]])
>>> pt.fit_transform(X_lognormal)
array([[ 0.49..., 0.17..., -0.15...],
[-0.05..., 0.58..., -0.57...],
[ 0.69..., -0.84..., 0.10...]])
虽然以上示例将standardize
参数设置为False
,但 PowerTransformer
默认将零均值,单位方差归一化应用于转换后的输出。
以下是适用于各种概率分布的Box-Cox和Yeo-Johnson的示例。请注意,将幂变换应用于某些分布时,会获得非常类似于高斯的结果,但是对于其他一些分布,结果是无效的。这突出了在转换之前和之后可视化数据的重要性。
QuantileTransformer
通过设置 output_distribution='normal'
也可以将数据映射到正态分布。将先前的示例与iris数据集结合使用:
>>> quantile_transformer = preprocessing.QuantileTransformer(
... output_distribution='normal', random_state=0)
>>> X_trans = quantile_transformer.fit_transform(X)
>>> quantile_transformer.quantiles_
array([[4.3, 2. , 1. , 0.1],
[4.4, 2.2, 1.1, 0.1],
[4.4, 2.2, 1.2, 0.1],
...,
[7.7, 4.1, 6.7, 2.5],
[7.7, 4.2, 6.7, 2.5],
[7.9, 4.4, 6.9, 2.5]])
因此,输入的中位数变为以0为中心输出的平均值。正常输出被裁剪,以便输入的最小和最大值(分别对应于1e-7和1-1e-7分位数)在转换后不会变成无穷。
6.3.3 归一化
归一化是将缩放单个样本至单位范数的过程。如果计划使用点积或任何其他核的二次形式来量化任何一对样本的相似性,则此过程可能会很有用。
该假设是向量空间模型的基础,该向量空间模型经常用于文本分类和内容聚类中。
函数normalize
提供了一种快速简便的方法,可以使用l1
或l2
范式在单个类似于数组的数据集上执行此操作:
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> X_normalized = preprocessing.normalize(X, norm='l2')
>>> X_normalized
array([[ 0.40..., -0.40..., 0.81...],
[ 1. ..., 0. ..., 0. ...],
[ 0. ..., 0.70..., -0.70...]])
preprocessing
模块还提供了一个实用程序类Normalizer
,它使用Transformer
API 来实现相同的操作 (即使在这种情况下fit
方法无用:该类是无状态的,因为此操作独立地处理样本)。
因此,该类适用于 sklearn.pipeline.Pipeline
的前期步骤:
>>> normalizer = preprocessing.Normalizer().fit(X) # fit does nothing
>>> normalizer
Normalizer()
然后,可以将normalizer实例用作任何转换器的样本矢量:
>>> normalizer.transform(X)
array([[ 0.40..., -0.40..., 0.81...],
[ 1. ..., 0. ..., 0. ...],
[ 0. ..., 0.70..., -0.70...]])
>>> normalizer.transform([[-1., 1., 0.]])
array([[-0.70..., 0.70..., 0. ...]])
注意:L2归一化也称为空间符号预处理。
稀疏输入
normalize
和Normalizer
都接受来自scipy.sparse的密集数组式数据和稀疏矩阵作为输入。对于稀疏输入,在将数据馈入有效的Cython例程之前,将数据转换为“压缩的稀疏行”表示形式(请参阅
scipy.sparse.csr_matrix
参考资料)。为避免不必要的内存复制,建议选择上游的CSR表示形式。
6.3.4 类别特征编码
通常,特征不是连续值,而是分类值。例如,一个人可能具备以下特征,["male", "female"]``["from Europe", "from US", "from Asia"]``["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]
。这样的特征可以有效地编码为整数,例如 ["male", "from US", "uses Internet Explorer"]
可以表示为[0, 1, 3]
,而["female", "from Asia", "uses Chrome"]
表示为[1, 2, 1]
。
要将分类特征转换为这样的整数代码,我们可以使用 OrdinalEncoder
。此估计器将每个分类特征转换为一个新的整数特征(0到n_categories-1):
>>> enc = preprocessing.OrdinalEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OrdinalEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari']])
array([[0., 1., 1.]])
但是,此类整数表示不能直接在所有的scikit-learn估计器使用,因为这样连续型数值的输入,估计器会将类别解释为有序的,而通常是无序的(例如,浏览器的类别数据是任意无序的)。
将分类特征转换为可与scikit-learn估计器一起使用的特征的另一种方法是使用one-of-K,也称为独热或伪编码。这种类型的编码可以通过OneHotEncoder
来获得,它将具有n_categories
个可能值的每个分类特征转换为n_categories
个二进制特征,其中一个位置为1,所有其他位置为0。
继续上面的示例:
>>> enc = preprocessing.OneHotEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari'],
... ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
[0., 1., 1., 0., 0., 1.]])
默认情况下,每个特征可以采用的值是从数据集中自动推断出来的,并且可以在categories_
属性中找到:
[array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]
可以使用参数categories
显式的指定,我们的数据集中有两种性别,四个可能的大陆和四个Web浏览器:
>>> genders = ['female', 'male']
>>> locations = ['from Africa', 'from Asia', 'from Europe', 'from US']
>>> browsers = ['uses Chrome', 'uses Firefox', 'uses IE', 'uses Safari']
>>> enc = preprocessing.OneHotEncoder(categories=[genders, locations, browsers])
>>> # Note that for there are missing categorical values for the 2nd and 3rd
>>> # feature
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder(categories=[['female', 'male'],
['from Africa', 'from Asia', 'from Europe',
'from US'],
['uses Chrome', 'uses Firefox', 'uses IE',
'uses Safari']])
>>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray()
array([[1., 0., 0., 1., 0., 0., 1., 0., 0., 0.]])
如果训练数据有可能缺少分类特征,则通常最好指定handle_unknown='ignore'
而不是如上所述手动设置categories
。如果指定 handle_unknown='ignore'
且在转换过程中遇到未知类别,则不会引发任何错误,但此功能生成的一键编码列将全为零(handle_unknown='ignore'
仅支持一键编码):
>>> enc = preprocessing.OneHotEncoder(handle_unknown='ignore')
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder(handle_unknown='ignore')
>>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray()
array([[1., 0., 0., 0., 0., 0.]])
也可以通过使用 drop
参数将每一列编码为n_categories - 1
列而不是n_categories
列。该参数允许用户为每个要删除的特征指定一个类别。在某些分类器中,这有助于避免输入的矩阵存在共线性。例如,当使用非正则回归(LinearRegression
)时,此类功能很有用,因为共线性会导致协方差矩阵不可逆。当此参数不为None时,必须设置handle_unknown
为 :error
>>> X = [['male', 'from US', 'uses Safari'],
... ['female', 'from Europe', 'uses Firefox']]
>>> drop_enc = preprocessing.OneHotEncoder(drop='first').fit(X)
>>> drop_enc.categories_
[array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]
>>> drop_enc.transform(X).toarray()
array([[1., 1., 1.],
[0., 0., 0.]])
有时可能只想删除具有2个类别特征的两列之一。在这种情况下,可以设置参数drop='if_binary'
。
>>> X = [['male', 'US', 'Safari'],
... ['female', 'Europe', 'Firefox'],
... ['female', 'Asia', 'Chrome']]
>>> drop_enc = preprocessing.OneHotEncoder(drop='if_binary').fit(X)
>>> drop_enc.categories_
[array(['female', 'male'], dtype=object), array(['Asia', 'Europe', 'US'], dtype=object), array(['Chrome', 'Firefox', 'Safari'], dtype=object)]
>>> drop_enc.transform(X).toarray()
array([[1., 0., 0., 1., 0., 0., 1.],
[0., 0., 1., 0., 0., 1., 0.],
[0., 1., 0., 0., 1., 0., 0.]])
在转换后的X
中,第一列是类别为“ male” /“ female”的特征编码,而其余六列则是分别具有3个类别2个特征的编码。
请参阅从字典中加载特征以获取表示为字典而不是标量的分类特征。
6.3.5 离散化
离散化 (也称为量化或分箱)提供了一种将连续特征划分为离散值的方法。某些具有连续特征的数据集可能会从离散化中受益,因为离散化可以将连续属性的数据集转换为仅具有名义属性的数据集。
One-hot编码的离散特征可以使模型更具表现力,同时保持可解释性。例如,使用离散器的预处理可以将非线性引入线性模型。
6.3.5.1 K-bins离散化
KBinsDiscretizer
将特征离散到k
个容器中:
>>> X = np.array([[ -3., 5., 15 ],
... [ 0., 6., 14 ],
... [ 6., 3., 11 ]])
>>> est = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal').fit(X)
默认情况下,输出是one-hot编码成的稀疏矩阵(请参阅编码分类特征),并且可以使用encode
参数进行配置。对于每个特征,在箱体的边缘和箱体数量是在fit
过程中计算出来的,它们将定义区间。因此,对于当前示例,这些区间定义为:
特征1:
特征2:
特征3:
根据这些bin区间,
X
转换如下:>>> est.transform(X)
array([[ 0., 1., 1.],
[ 1., 1., 1.],
[ 2., 0., 0.]])
结果数据集包含可以在sklearn.pipeline.Pipeline
进一步使用的序数属性。
离散化类似于构造连续数据的直方图。但是,直方图着重于对落入特定区域的特征进行计数,而离散化则着重于为这些区域分配特征值。
KBinsDiscretizer
可以通过strategy
参数选择实现不同的分箱策略。“uniform”策略使用固定宽度的箱体。“quantile”策略使用分位数值在每个特征中具有均等填充的bin。“ kmeans”策略基于对每个特征执行独立的k均值聚类过程来定义箱体。
例子:
6.3.5.2 特征二值化
特征二值化是将数字特征用阈值过滤以获得布尔值的过程。这对于下游概率估计器很有用,这些估计器假设输入数据是根据多元Bernoulli分布进行分布的。例如sklearn.neural_network.BernoulliRBM
这个例子。
即使归一化计数(又称术语频率)或TF-IDF值的特征通常在实践中表现得稍好一些,在文本处理过程中常常使用二进制特征值(可能是为了简化概率推理)。
至于Normalizer
,实用程序类 Binarizer
在 sklearn.pipeline.Pipeline
的前期步骤中使用。由于每个样本都独立于其他样本进行处理,因此fit
方法无济于事:
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> binarizer = preprocessing.Binarizer().fit(X) # fit does nothing
>>> binarizer
Binarizer()
>>> binarizer.transform(X)
array([[1., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
可以调整二值化器的阈值:
>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[0., 0., 1.],
[1., 0., 0.],
[0., 0., 0.]])
对于StandardScaler
和Normalizer
类,预处理模块提供了一个伴随函数binarize
,以便在不需要转换器API时使用。
请注意,当k = 2
且bin边缘处于该阈值threshold
时,Binarizer
与KBinsDiscretizer
类似。
稀疏输入
binarize
和Binarizer
接受来自scipy.sparse的密集数组数据和稀疏矩阵作为输入。对于稀疏输入,数据将转换为“压缩的稀疏行”表示形式(请参见参考资料
scipy.sparse.csr_matrix
)。为避免不必要的内存复制,建议选择上游的CSR表示形式。
6.3.6. 估算缺失值
6.3.7 生成多项式特征
通常,考虑输入数据的非线性特征会增加模型的复杂性。多项式特征是一种简单而常用的方法,它可以获取特征的高阶和相互作用项。它在PolynomialFeatures
中实现:
>>> import numpy as np
>>> from sklearn.preprocessing import PolynomialFeatures
>>> X = np.arange(6).reshape(3, 2)
>>> X
array([[0, 1],
[2, 3],
[4, 5]])
>>> poly = PolynomialFeatures(2)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
特征已经从转换成。
在某些情况下,仅需要特征之间的交互项,并且可以通过设置interaction_only=True
获得:
>>> X = np.arange(9).reshape(3, 3)
>>> X
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> poly = PolynomialFeatures(degree=3, interaction_only=True)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 2., 0., 0., 2., 0.],
[ 1., 3., 4., 5., 12., 15., 20., 60.],
[ 1., 6., 7., 8., 42., 48., 56., 336.]])
X的特征已从 转换成。
请注意,使用多项式内核函数时,多项式特征在 kernel methods 中被隐含调用(例如sklearn.svm.SVC
,sklearn.decomposition.KernelPCA
)。
有关使用创建的多项式特征的Ridge回归的信息,请参见多项式插值。
6.3.8 自定义转换器
通常,需要将现有的Python函数转换为转换器,以帮助进行数据清理或处理。可以使用FunctionTransformer
将任意函数转化成转换器。例如,要构建在管道中应用对数转换的转换器,请执行以下操作:
>>> import numpy as np
>>> from sklearn.preprocessing import FunctionTransformer
>>> transformer = FunctionTransformer(np.log1p, validate=True)
>>> X = np.array([[0, 1], [2, 3]])
>>> transformer.transform(X)
array([[0. , 0.69314718],
[1.09861229, 1.38629436]])
在进行转换之前需要通过设置check_inverse=True
和调用fit
来确保func
和inverse_func
是彼此的逆。请注意,一个警告会被抛出,并且可以通过一个 filterwarnings
将其转化为错误。
>>> import warnings
>>> warnings.filterwarnings("error", message=".*check_inverse*.",
... category=UserWarning, append=False)
有关演示如何使用FunctionTransformer
进行自定义特征选择的完整代码示例,请参见使用FunctionTransformer选择列