Standardization即标准化,尽量将数据转化为均值为零,方差为一的数据,形如标准正态分布(高斯分布)。实际中我们会忽略数据的分布情况,仅仅是通过改变均值来集中数据,然后将非连续特征除以他们的标准差。
1.1 标准化:去均值,方差规模化
Standardization标准化:将特征数据的分布调整成标准正太分布,也叫高斯分布,也就是使得数据的均值为0,方差为1.
标准化的原因在于如果有些特征的方差过大,则会主导目标函数从而使参数估计器无法正确地去学习其他特征。
标准化的过程为两步:去均值的中心化(均值变为0);方差的规模化(方差变为1)。
(1) 在sklearn.preprocessing中提供了一个scale的方法
In [149]: from sklearn import preprocessing
In [150]: import numpy as np
In [151]: X = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]])
In [152]: X_scaled = preprocessing.scale(X)
In [153]: X_scaled
Out[153]:
array([[ 0. , -1.22474487, 1.33630621],
[ 1.22474487, 0. , -0.26726124],
[-1.22474487, 1.22474487, -1.06904497]])
#scaled之后的数据零均值,单位方差
In [154]: X_scaled.mean(axis=0)
Out[154]: array([0., 0., 0.])
# # axis=1表示对每一行去做这个操作,axis=0表示对每一列做相同的这个操作
In [155]: X_scaled.std(axis=0)
Out[155]: array([1., 1., 1.])
(2) StandardScaler计算训练集的平均值和标准差,以便测试数据集使用相同的变换
preprocessing这个模块还提供了一个实用类StandarScaler,它可以在训练数据集上做了标准转换操作之后,把相同的转换应用到测试训练集中。
这样就可以对训练数据,测试数据应用相同的转换,以后有新的数据进来也可以直接调用,不用再重新把数据放在一起再计算一次了。
>>> from sklearn.preprocessing import StandardScaler
>>> data = [[0, 0], [0, 0], [1, 1], [1, 1]]
>>> scaler = StandardScaler()
>>> print(scaler.fit(data)) # 调用fit方法,根据已有的训练数据创建一个标准化的转换器
StandardScaler(copy=True, with_mean=True, with_std=True)
>>> print(scaler.mean_)
[0.5 0.5]
>>> print(scaler.transform(data)) # 使用上面这个转换器去转换数据data,调用transform方法
[[-1. -1.]
[-1. -1.]
[ 1. 1.]
[ 1. 1.]]
>>> print(scaler.transform([[2, 2]])) # 对于新来的一组样本,也想得到相同的转换
[[3. 3.]]
注 :
1)StandardScaler()中可以传入两个参数:with_mean,with_std.这两个都是布尔型的参数,默认情况下都是true,但也可以自定义成false.即不要均值中心化或者不要方差规模化为1.
2)scale和StandardScaler可以用于回归模型中的目标值处理。
(3) 将数据特征缩放至某一范围(from sklearn.preprocessing import MinMaxScaler)
也就是使得特征的分布是在一个给定最小值和最大值的范围内的。一般情况下是在[0,1]之间,或者是特征中绝对值最大的那个数为1,其他数以此维标准分布在[[-1,1]之间
以上两者分别可以通过MinMaxScaler 或者 MaxAbsScaler方法来实现。
之所以需要将特征规模化到一定的[0,1]范围内,是为了对付那些标准差相当小的特征并且保留下稀疏数据中的0值。
MinMaxScaler(最小最大值标准化)
X _ s t d = ( X − X . m i n ( a x i s = 0 ) ) ( X . m a x ( a x i s = 0 ) − X . m i n ( a x i s = 0 ) ) X\_std = \frac{ (X - X.min(axis=0))}{(X.max(axis=0) - X.min(axis=0))} X_std=(X.max(axis=0)−X.min(axis=0))(X−X.min(axis=0))
X _ s c a l e r = X s t d ( m a x − m i n ) + m i n X\_scaler =\frac {X_std} {(max - min)} + min X_scaler=(max−min)Xstd+min
In [159]: from sklearn import preprocessing
# 将数据缩放至[0, 1]间。训练过程: fit_transform()
In [160]: X_train = np.array([[1., -1., 2.], [2., 0., 0.], [0., 1., -1.]])
In [161]: min_max_scaler = preprocessing.MinMaxScaler()
In [162]: X_train_minmax = min_max_scaler.fit_transform(X_train)
In [163]: X_train_minmax
Out[163]:
array([[0.5 , 0. , 1. ],
[1. , 0.5 , 0.33333333],
[0. , 1. , 0. ]])
# 将上述得到的scale参数应用至测试数据
In [164]: X_test= np.array([[ -3., -1., 4.]])
In [165]: X_test_minmax = min_max_scaler.transform(X_test)
In [166]: X_test_minmax
Out[166]: array([[-1.5 , 0. , 1.66666667]])
# 可以用以下方法查看scaler的属性
In [167]: min_max_scaler.scale_
Out[167]: array([0.5 , 0.5 , 0.33333333])
In [168]: min_max_scaler.min_
Out[168]: array([0. , 0.5 , 0.33333333])
MaxAbsScaler(绝对值最大标准化)
与上述标准化方法相似,但是它通过除以最大值将训练集缩放至[-1,1]。这意味着数据已经以0为中心或者是含有非常多0的稀疏数据。
In [169]: X_train = np.array([[ 1., -1., 2.],[ 2., 0., 0.],[ 0., 1., -1.]])
In [170]: max_abs_scaler = preprocessing.MaxAbsScaler()
In [171]: X_train_maxabs =max_abs_scaler.fit_transform(X_train)
In [172]: X_train_maxabs
Out[172]:
array([[ 0.5, -1. , 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -0.5]])
In [173]: X_test = np.array([[ -3., -1., 4.]])
In [174]: X_test_maxabs = max_abs_scaler.transform(X_test)
In [175]: X_test_maxabs
Out[175]: array([[-1.5, -1. , 2. ]])
In [176]: max_abs_scaler.scale_
Out[176]: array([2., 1., 2.])
(4) 规模化稀疏数据
对稀疏数据进行去均值的中心化会破坏稀疏的数据结构。此时可以用其他方法对稀疏的输入数据进行转换,特别是那些特征之间的数据规模不一样的数据。MaxAbsScaler 和 maxabs_scale
这两个方法是专门为稀疏数据的规模化所设计的。
(5) 规模化有异常值的数据
如果数据有许多异常值,那么使用数据的均值与方差去做标准化就不行了。
在这里,你可以使用robust_scale 和 RobustScaler
这两个方法。它会根据中位数或者四分位数去中心化数据。
更多的数据预处理方法参考官方文档:http://scikit-learn.org/stable/modules/preprocessing.html#standardization-or-mean-removal-and-variance-scaling
1.2 正则化Normalization
正则化是将样本在向量空间模型上的一个转换,经常被使用在分类与聚类中。
函数normalize 提供了一个快速有简单的方式在一个单向量上来实现这正则化的功能。正则化有l1,l2等,这些都可以用上:
In [42]: import numpy as np
# # 创建一组特征数据,每一行表示一个样本,每一列表示一个特征
In [43]: x = np.array([[1., -1., 2.],[2., 0., 0.],[0., 1., -1.]])
In [44]: from sklearn import preprocessing
In [45]: x_normalized = preprocessing.normalize(x, norm='l2')
In [46]: x
Out[46]:
array([[ 1., -1., 2.],
[ 2., 0., 0.],
[ 0., 1., -1.]])
In [47]: x_normalized
Out[47]:
array([[ 0.40824829, -0.40824829, 0.81649658],
[ 1. , 0. , 0. ],
[ 0. , 0.70710678, -0.70710678]])
# preprocessing这个模块还提供了一个实用类Normalizer,实用transform方法同样也可以对新的数据进行同样的转换
In [48]: normalizer = preprocessing.Normalizer().fit(x)
In [49]: normalizer
Out[49]: Normalizer(copy=True, norm='l2')
# 对训练数据进行正则
In [50]: normalizer.transform(x)
Out[50]:
array([[ 0.40824829, -0.40824829, 0.81649658],
[ 1. , 0. , 0. ],
[ 0. , 0.70710678, -0.70710678]])
# 对新的测试数据进行正则
In [51]: normalizer.transform([[-1., 1., 0.]])
Out[51]: array([[-0.70710678, 0.70710678, 0. ]])
normalize和Normalizer都既可以用在密集数组也可以用在稀疏矩阵(scipy.sparse)中
1.3 特征的二值化
特征的二值化是指将数值型的特征数据转换成布尔类型的值。可以使用使用类Binarizer。
In [52]: binarizer = preprocessing.Binarizer().fit(x)
In [53]: binarizer.transform(x) # 默认是根据0来二值化,大于0的都标记为1,小于等于0的都标记为0
Out[53]:
array([[1., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
In [54]: binarizer = preprocessing.Binarizer(threshold=1.5) # 也可以自己设置这个阀值,只需传出参数threshold即可
In [55]: binarizer.transform(x)
Out[55]:
array([[0., 0., 1.],
[1., 0., 0.],
[0., 0., 0.]])
binarize and Binarizer都可以用在密集向量和稀疏矩阵上。
1.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].
. . . ... ...
然而上面这种表征的方式仍然不能直接为scikit-learn的模型所用,因为模型会把它们当成序列型的连续变量。
要想使得类别型的变量能最终被模型直接使用,可以使用one-of-k编码或者one-hot编码。这些都可以通过OneHotEncoder实现,它可以将有n种值的一个特征变成n个二元的特征。
In [61]: enc = preprocessing.OneHotEncoder()
In [62]: enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
Out[62]:
OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>,
handle_unknown='error', n_values='auto', sparse=True)
In [63]: enc.transform([[0,1,3]]).toarray()
Out[63]: array([[1., 0., 0., 1., 0., 0., 0., 0., 1.]])
In [64]: enc = preprocessing.OneHotEncoder(n_values=[2,3,4])
In [65]: enc.fit([[1, 2, 3], [0, 2, 0]])
Out[65]:
OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>,
handle_unknown='error', n_values=[2, 3, 4], sparse=True)
In [66]: enc.transform([[1,0,0]]).toarray()
Out[66]: array([[0., 1., 1., 0., 0., 1., 0., 0., 0.]])
特征1中有(0,1)两个值,特征2中有(0,1,2)3个值,特征3中有(0,1,2,3)4个值,所以编码之后总共有9个二元特征。
但也会存在这样的情况,某些特征中可能对一些值有缺失,比如明明有男女两个性别,样本数据中都是男性,这样就会默认被判别为只有一类值。这个时候我们可以向OneHotEncoder传如参数n_values,用来指明每个特征中的值的总个数,如上enc = preprocessing.OneHotEncoder(n_values=[2,3,4])
1.5 弥补缺失数据
在scikit-learn的模型中都是假设输入的数据是数值型的,并且都是有意义的,如果有缺失数据是通过NAN,或者空值表示的话,就无法识别与计算了。
要弥补缺失值,可以使用均值,中位数,众数等等。Imputer这个类可以实现。
In [67]: from sklearn.preprocessing import Imputer
In [68]: imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
In [69]: imp.fit([[1, 2], [np.nan, 3], [7, 6]])
Out[69]: Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)
In [70]: x = [[np.nan, 2], [6, np.nan], [7, 6]]
In [71]: imp.transform(x)
Out[71]:
array([[4. , 2. ],
[6. , 3.66666667],
[7. , 6. ]])
In [72]: import scipy.sparse as sp # Imputer类同样也可以支持稀疏矩阵,以下例子将0作为了缺失值,为其补上均值
In [73]: x = sp.csc_matrix([[1, 2], [0, 3], [7, 6]]) # 创建一个稀疏矩阵
In [74]: x
Out[74]:
<3x2 sparse matrix of type 'numpy.int64'>'
with 5 stored elements in Compressed Sparse Column format>
In [75]: imp = Imputer(missing_values=0, strategy='mean', verbose=0)
In [76]: imp.fit(x)
Out[76]: Imputer(axis=0, copy=True, missing_values=0, strategy='mean', verbose=0)
In [77]: x_test = sp.csc_matrix([[0, 2], [6, 0], [7, 6]])
In [78]: imp.transform(x_test)
Out[78]:
array([[4. , 2. ],
[6. , 3.66666667],
[7. , 6. ]])
1.6 创建多项式特征
有的时候线性的特征并不能做出美的模型,于是我们会去尝试非线性。非线性是建立在将特征进行多项式地展开上的。
比如将两个特征 ( X 1 , X 2 ) (X_1, X_2) (X1,X2),它的平方展开式便转换成5个特征 ( 1 , X 1 , X 2 , X 1 2 , X 1 X 2 , X 2 2 ) (1, X_1, X_2, X_1^2, X_1X_2, X_2^2) (1,X1,X2,X12,X1X2,X22),其中1是Bias:
In [79]: import numpy as np
In [80]: from sklearn.preprocessing import PolynomialFeatures
In [81]: x = np.arange(6).reshape(3, 2)
In [82]: x
Out[82]:
array([[0, 1],
[2, 3],
[4, 5]])
In [83]: poly = PolynomialFeatures(2)
In [84]: poly.fit_transform(x)
Out[84]:
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
In [85]: x = np.arange(9).reshape(3, 3)
In [86]: poly = PolynomialFeatures(degree=3, interaction_only=True)
In [87]: poly.fit_transform(x)
Out[87]:
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 1 , X 2 , X 3 ) (X_1, X_2, X_3) (X1,X2,X3) 转换成
( 1 , X 1 , X 2 , X 3 , X 1 X 2 , X 1 X 3 , X 2 X 3 , X 1 X 2 X 3 ) (1, X_1, X_2, X_3, X_1X_2, X_1X_3, X_2X_3, X_1X_2X_3) (1,X1,X2,X3,X1X2,X1X3,X2X3,X1X2X3),如上所示。
1.7 自定义特征的转换函数
把原始的特征放进一个函数中做转换,这个函数出来的值作为新的特征。比如说将特征数据做log转换,做倒数转换等等。FunctionTransformer 可以实现这个功能
from sklearn.preprocessing import FunctionTransformer
transformer = FunctionTransformer(np.log1p)
x = np.array([[0, 1], [2, 3]])
transformer.transform(x)
Out[91]:
array([[0. , 0.69314718],
[1.09861229, 1.38629436]])
总结:当我们拿到一批原始的数据
In [2]: import numpy as np
In [3]: arr = np.arange(10)
In [4]: arr
Out[4]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [5]: np.random.shuffle(arr)
In [6]: arr
Out[6]: array([6, 8, 3, 7, 5, 4, 1, 2, 0, 9])
In [7]: arr = np.arange(9).reshape((3, 3))
In [8]: arr
Out[8]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
# 多维矩阵中,只对第一维(行)做打乱顺序操作
In [9]: np.random.shuffle(arr)
In [10]: arr
Out[10]:
array([[0, 1, 2],
[6, 7, 8],
[3, 4, 5]])
参考:
https://blog.csdn.net/csmqq/article/details/51461696
https://blog.csdn.net/sinat_33761963/article/details/53433799