数据预处理——特征工程
前言
特征工程是对原始数据进行一系列工程处理,将其提炼为特征,作为输入供算法和模型使用。数据预处理是其中的重要一环,通过对数据进行预处理,可以更好地提取出数据的特征,更容易训练。数据预处理的常用方法具体如下,可使用的工具有numpy/sklearn/torch...,这里主要介绍sklearn.preprocessing模块。
数据预处理方法介绍
1. 标准化
1. 1 Standard
去除均值和方差,调整成标准正太分布,也叫高斯分布。
(X-X_mean)/std计算每个属性,使得所有数据均值为0,方差为1。
from sklearn import preprocessing
# 直接对给定数据进行标准化
x_scaled = preprocessing.scale(x)
# 可保存训练集中的均值、方差参数,直接用于转换数据集
scaler = preprocessing.StandardScaler().fit(x)
scaler.transform(x)
scaler.mean_
scaler.var_
# or
x_scaled = preprocessing.StandardScaler().fit_transform(x)
1.2. MinMax
将属性缩放到指定的最大和最小值范围之间(通常0-1,即归一化),这样可以对方差小的属性数据增强稳定性。
preprocessing.MinMaxScaler(feature_range=(0, 1), copy=True)
mmxsca = preprocessing.MinMaxScaler().fit(X)
mmxsca.transform(X)
# or
x_scaled = preprocessing.MinMaxScaler().fit_transform(X)
1.3. MaxAbsScaler
数据缩放到[-1,1]之间,所有数据都会除以最大值。该方法对那些已经中心化均值为0或者稀疏的数据有意义,不会改变矩阵的稀疏性,而MinMax会改变。
mAbsSca = preprocessing.MaxAbsScaler().fit(x)
mAbsSca.transform(x)
# or
x_scaled = preprocessing.MaxAbsScaler().fit_transform(x)
1.4. RobustScaler
数据有较多异常值时,使用均值和方差来标准化显然不合适。消除中位数,按一、四等分位数缩放效果要好。
preprocessing.RobustScaler(x, with_centering=True, with_scaling=True, quantile_range=(25,75),copy=True)
from sklearn.preprocessing import RobustScaler
robustSca = RobustScaler().fit(x)
robustSca.transform(x)
robustSca.center_ # 中位数
robustSca.scale_ # 四分位间距
# or
x_scaled = preprocessing.RobustScaler().fit_transform(x)
2. 正则化
对每个样本计算其P-范数,再对每个元素除以该范数,使得处理后样本的p-范数等于1。如果后续要使用二次型等方法计算两个样本之间的相似性会有用,该方法主要应用于文本分类和聚类中。
# 1-范数:向量各分量绝对值之和
# 2-范数:向量长度
# 最大范数:向量各分量绝对值的最大值
# p-范数的计算公式:||X||p=(|x1|^p+|x2|^p+…+|xn|^p)^1/p
normsca = preprocessing.Normalizer(norm='l2').fit(x) # l2范数正则化
normsca.transform(x)
# or
x_scaled = preprocessing.Normalizer(norm='l2').fit_transform(x)
3. 非线性变换
3.1. QuantileTransformer
QuantileTransformer
函数置每个特征于相同的分布范围。通过做一个秩变换,使变换后的数据受异常值的影响较小。QuantileTransformer
函数将原始数据变换到[0, 1]区间的均匀分布。无法区分异常值,不同于RobustScaler
,QuantileTransformer
通过将异常值设为规定的范围值来达到消除异常值的目的。
preprocessing.QuantileTransformer(x, nquantiles=1000, output_distribution='uniform', ignore_implicit_zeros=False, subsample=100000, random_state=None, copy=True)
from sklearn.preprocessing import QuantileTransformer
qt = QuantileTransformer(nquantiles=10, random_state=0)
x_scaled = qt.fit_transform(x)
3.2. PowerTransformer
幂变换,将数据从任何分布映射到尽可能接近高斯分布。幂变换是一类参数化的单调变换,通过幂变换实现,目的是稳定方差和最小化偏度。该方法提供了两种幂变换Yeo-Johnson transform
和Box-Cox transform
。默认情况下,standardize=True
,即会应用零均值化和单位方差归一化
pt = preprocessing.PowerTransformer(method='box-cox', standardize=False)
x_sca = pt.fit_transform(x)
4. 离散化
离散化提供了一种将连续特征划分为离散值的方法。某些具有连续特征的数据集可能受益于离散化,因为离散化可以将连续属性的数据集转换为仅具有名义属性的数据集。
4.1. KBinsDiscretizer
将连续型变量划分为分类变量的类,能够将连续型变量排序后按顺序分箱后编码。默认情况下,输出是one-hot编码成稀疏矩阵,并且可以使用encode参数。
x = np.array([1 2 3 4 5 6 7])
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
x_scaled = est.fit_transform(x)
Out:array([[0.], [0.], [1.], [1.],[2.],[2.],[2.]])
est.bin_edges_
Out: array([array([1., 3., 5., 7.])], dtype=object)
# 这是啥?
est.inverse_transform(est.fit_transform(np.array(x).reshape(-1,1)))
Out: array([[2.],[2.],[4.],[4.], [6.],[6.],[6.]])
4.2. Binarizer
根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0
sklearn.preprocessing.Binarizer(threshold=0.0, copy=True)
5. 缺失值处理
Imputer
类提供了填补缺失值的基本策略。可以使用缺失值所在的行或列的均值、中位数、频数最大的值。
# startegy: mean/median/most_frequent/constant
# copy: 默认是True,创建特征矩阵的副本
sklearn.impute.SimpleImputer(missing_values=nan, strategy=’mean’, fill_value=None, verbose=0, copy=True)
sklearn.impute.MissingIndicator(missing_values=nan, features=’missing-only’, sparse=’auto’, error_on_new=True)
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
imp_mean.fit([[7, 2, 3], [4, np.nan, 6], [10, 5, 9]])
X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
imp_mean.transform(X)
6. 多项式特征
通过增加输入数据的非线性特征来增加模型的复杂度通常是有效的,一个简单通用的办法是使用多项式特征,将特征与特征相乘,可以获得特征的更高维度和互相间关系的项。
sklearn.preprocessing.PolynomialFeatures(degree=2, interaction_only=False, include_bias=True)
import numpy as np
X = np.arange(6).reshape(3, 2)
print(X)
"""
[[0 1]
[2 3]
[4 5]]
"""
poly = PolynomialFeatures(2)
print(poly.fit_transform(X))
"""
[[ 1. 0. 1. 0. 0. 1.]
[ 1. 2. 3. 4. 6. 9.]
[ 1. 4. 5. 16. 20. 25.]]
"""
import numpy as np
X = np.arange(9).reshape(3, 3)
print(X)
"""
[[0 1 2]
[3 4 5]
[6 7 8]]
"""
poly = PolynomialFeatures(degree=3, interaction_only=True)
print(poly.fit_transform(X))
"""
[[ 1. 0. 1. 2. 0. 0. 2. 0.]
[ 1. 3. 4. 5. 12. 15. 20. 60.]
[ 1. 6. 7. 8. 42. 48. 56. 336.]]
"""
7. 编码分类特征
机器学习中大多数算法只能处理数值型数据,不能处理文字。而在现实中许多标签和特征在数据收集完毕的时候,都不是以数字来表现的。为了让数据适应算法和库,必须将数据进行编码,将文字型数据转换为数值型。
7.1. LabelEncoder
标签专用,能够将分类转换为分类数值。
LabelEncoder().fit_transform(x)
7.2. OrdinalEncoder
特征专用,能够将分类特征转换为分类数值。
OrdinalEncoder().fit_transform(x)
7.3. OneHotEncoder
类别OrdinalEncoder可以用来处理有序变量,但对于名义变量,我们只有使用哑变量的方式来处理,才能够尽量向算法传达最准确的信息。
OneHotEncoder().fit_transform(x)
8. 自定义转换器
使用FunctionTransformer方法将任意函数转化为一个Transformer
sklearn.preprocessing.FunctionTransformer(func=None, inverse_func=None, validate=None, accept_sparse=False, pass_y=’deprecated’, check_inverse=True, kw_args=None, inv_kw_args=None)
API查询
[
'Binarizer', # 二值化
'FunctionTransformer',
'Imputer',
'KBinsDiscretizer', # 等宽离散化
'KernelCenterer',
'LabelBinarizer',
'LabelEncoder',
'MultiLabelBinarizer',
'MinMaxScaler', # 最大最小值缩放
'MaxAbsScaler', # 最大绝对值缩放
'QuantileTransformer', # 均匀分布转换
'Normalizer', # 范数归一化
'OneHotEncoder', # 独热编码
'OrdinalEncoder', # 哑编码
'PowerTransformer', # 高斯分布转换
'RobustScaler', # 鲁棒缩放
'StandardScaler', # Z-score (x-mean)/std
'add_dummy_feature',
'PolynomialFeatures', # 生成多项式特征
'binarize', # 二值化
'normalize', # 范数归一化
'scale',
'robust_scale', # 鲁棒缩放
'maxabs_scale', # 最大绝对值缩放
'minmax_scale', # 最大最小值缩放
'label_binarize',
'quantile_transform', # 均匀分布转换
'power_transform', # 高斯分布转换
]
参考文献
- https://xercis.blog.csdn.net/article/details/102799300?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-4.control
- https://blog.csdn.net/qq_40195360/article/details/88378248
- https://blog.csdn.net/wong2016/article/details/80624698