浅谈sklearn中的数据预处理
目录
前言
sklearn 中的 sklearn.preprocessing
中提供了数据预处理的相关函数,本文将主要围绕特征缩放来展开讲解。
一、标准化(StandardScaler)
设数据矩阵为
X = [ x 1 T x 2 T ⋮ x n T ] X= begin{bmatrix} boldsymbol{x}_1^{mathrm T} \ boldsymbol{x}_2^{mathrm T} \ vdots \ boldsymbol{x}_n^{mathrm T} end{bmatrix} X=⎣⎢⎢⎢⎡x1Tx2T⋮xnT⎦⎥⎥⎥⎤
其中 x i = ( x i 1 , x i 2 , ⋯ , x i d ) T boldsymbol{x}_i=(x_{i1}, x_{i2},cdots,x_{id})^{mathrm T} xi=(xi1,xi2,⋯,xid)T 为特征向量。
在进行下一步之前,我们有必要先引入数据矩阵的均值和标准差。
我们知道,对于数据向量 a = ( a 1 , ⋯ , a n ) T boldsymbol{a}=(a_1,cdots,a_n)^{mathrm T} a=(a1,⋯,an)T 而言(这里的向量可以理解成一组数据,之所以称之为向量,是为了方便后续的表述),其均值和标准差分别为:
μ ( a ) = a 1 + ⋯ + a n n , σ ( a ) = ( 1 n ∥ a − μ ( a ) ∥ 2 ) 1 / 2 , 其 中 μ ( a ) = ( μ ( a ) , ⋯ , μ ( a ) ⏟ n 个 ) T mu(boldsymbol{a})=frac{a_1+cdots+a_n}{n},quadsigma(boldsymbol a)=left(frac1n Vert boldsymbol{a}-boldsymbol{mu}(boldsymbol{a})Vert^2right)^{1/2},quad 其中 ;boldsymbol{mu}(boldsymbol{a})=(underbrace{mu(boldsymbol{a}),cdots, mu(boldsymbol{a})}_{n 个})^{mathrm T} μ(a)=na1+⋯+an,σ(a)=(n1∥a−μ(a)∥2)1/2,其中μ(a)=(n个 μ(a),⋯,μ(a))T
我们将 X X X 写成行向量的形式: X = ( a 1 , a 2 , ⋯ , a d ) X =(boldsymbol{a}_1,boldsymbol{a}_2,cdots,boldsymbol{a}_d) X=(a1,a2,⋯,ad),其中每个 a i boldsymbol{a}_i ai 均为列向量,因此
μ ( X ) = ( μ ( a 1 ) , μ ( a 2 ) , ⋯ , μ ( a d ) ) T σ ( X ) = ( σ ( a 1 ) , σ ( a 2 ) , ⋯ , σ ( a d ) ) T begin{aligned} mu(X)&=(mu(boldsymbol{a}_1),mu(boldsymbol{a}_2),cdots,mu(boldsymbol{a}_d))^{mathrm T} \ sigma(X)&=(sigma(boldsymbol{a}_1),sigma(boldsymbol{a}_2),cdots,sigma(boldsymbol{a}_d))^{mathrm T} end{aligned} μ(X)σ(X)=(μ(a1),μ(a2),⋯,μ(ad))T=(σ(a1),σ(a2),⋯,σ(ad))T
设对 X X X 进行标准化后得到 Z Z Z,利用 numpy 的广播机制, Z Z Z 有如下形式
Z = ( z 1 , z 2 , ⋯ , z d ) , 其 中 z i = a i − μ ( a i ) σ ( a i ) , i = 1 , 2 , ⋯ , d Z=(boldsymbol{z}_1,boldsymbol{z}_2,cdots,boldsymbol{z}_d),quad 其中; boldsymbol{z}_i=frac{boldsymbol{a}_i-mu(boldsymbol{a}_i)}{sigma(boldsymbol{a}_i)},;;i=1,2,cdots,d Z=(z1,z2,⋯,zd),其中zi=σ(ai)ai−μ(ai),i=1,2,⋯,d
当然 Z Z Z 可以更为简洁地表成
Z = X − μ ( X ) T σ ( X ) T Z=frac{X-mu(X)^{mathrm T}}{sigma(X)^{mathrm T}} Z=σ(X)TX−μ(X)T
查看 X X X 的均值,方差和标准差:
from sklearn.preprocessing import StandardScaler
import numpy as np
# 数据矩阵
X = np.array([
[1, 3],
[0, 1]
])
# 创建一个scaler实例并将数据传入该实例中
scaler = StandardScaler().fit(X)
# 查看X的的均值,方差和标准差
print(scaler.mean_) # [0.5 2. ]
print(scaler.var_) # [0.25 1. ]
print(scaler.scale_) # [0.5 1. ]
之所以标准差为 scale_
,是因为标准差控制着我们数据的缩放程度。需要注意的是,如果数据矩阵的某一列方差为
0
0
0,则 scale_
为
1
1
1,即这一列不进行缩放。
对
X
X
X 进行标准化,只需要使用 transfrom()
方法:
X = np.array([
[243, 80],
[19, 47]
])
scaler = StandardScaler().fit(X)
# 进行缩放
X_scaled = scaler.transform(X)
# [[ 1. 1.]
# [-1. -1.]]
查看 X_scaled
的均值和标准差:
print(X_scaled.mean(axis=0))
# [0. 0.]
print(X_scaled.std(axis=0))
# [1. 1.]
可以看到 X_scaled
均值为
0
boldsymbol 0
0, 标准差为
1
boldsymbol 1
1,即
X
X
X 已经标准化。
当然我们也可以用 scaler
去标准化新的样本,标准化过程采用
X
X
X 的均值和标准差:
X = np.array([
[243, 80],
[19, 47]
])
scaler = StandardScaler().fit(X)
# 缩放新的样本
print(scaler.transform([[2, 3]]))
# [[-1.15178571 -3.66666667]]
二、归一化(MinMaxScaler)
对 X X X 进行归一化就是将 X X X 中的所有元素缩放至 [ 0 , 1 ] [0,1] [0,1] 内。具体过程如下:
记
a i ‾ = min ( x 1 i , x 2 i , ⋯ , x n i ) , a i ‾ = max ( x 1 i , x 2 i , ⋯ , x n i ) X ‾ = ( a 1 ‾ , a 2 ‾ , ⋯ , a d ‾ ) T , X ‾ = ( a 1 ‾ , a 2 ‾ , ⋯ , a d ‾ ) T underline{boldsymbol{a}_i}=min(x_{1i},x_{2i},cdots,x_{ni}),quad overline{boldsymbol{a}_i}=max(x_{1i},x_{2i},cdots,x_{ni}) \ \ underline{X}=(underline{boldsymbol{a}_1},underline{boldsymbol{a}_2},cdots,underline{boldsymbol{a}_d})^{mathrm{T}},quad overline{X}=(overline{boldsymbol{a}_1},overline{boldsymbol{a}_2},cdots,overline{boldsymbol{a}_d})^{mathrm{T}} ai=min(x1i,x2i,⋯,xni),ai=max(x1i,x2i,⋯,xni)X=(a1,a2,⋯,ad)T,X=(a1,a2,⋯,ad)T
设 X X X 进行归一化后得到 Z Z Z,利用 numpy 的广播机制,我们有
Z = X − X ‾ T X ‾ T − X ‾ T Z=frac{X-underline{X}^{mathrm T}}{overline{X}^{mathrm T}-underline{X}^{mathrm T}} Z=XT−XTX−XT
先用 make_blobs()
生成斑点数据集:
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import make_blobs
X, _ = make_blobs(n_samples=6, centers=2, random_state=27)
print(X)
# [[ 5.93412904 6.82960749]
# [-1.66484812 6.53450678]
# [-1.26216614 6.23733539]
# [ 5.26739446 7.73680694]
# [-0.66451524 7.50872847]
# [ 4.14680663 6.35238034]]
对 X X X 进行归一化:
scaler = MinMaxScaler().fit(X)
print(scaler.transform(X))
# [[1. 0.39498722]
# [0. 0.19818408]
# [0.0529916 0. ]
# [0.91225996 1. ]
# [0.13164046 0.8478941 ]
# [0.76479434 0.07672366]]
如果我们想将 X X X 中的元素缩放至 ( 1 , 2 ) (1, 2) (1,2) 区间内,只需要:
scaler = MinMaxScaler((1, 2)).fit(X)
print(scaler.transform(X))
# [[2. 1.39498722]
# [1. 1.19818408]
# [1.0529916 1. ]
# [1.91225996 2. ]
# [1.13164046 1.8478941 ]
# [1.76479434 1.07672366]]
三、正则化(Normalizer)
对 X X X 进行正则化也就是对其中的每个样本(每一行)进行正则化,即将每个样本的范数化为单位范数。具体过程如下:
x i : = x i ∥ x i ∥ p , i = 1 , 2 , ⋯ , n , p = 1 , 2 , ∞ boldsymbol{x}_i:=frac{boldsymbol{x}_i}{Vert boldsymbol{x}_iVert_p},quad i=1,2,cdots,n,quad p=1,2,infty xi:=∥xi∥pxi,i=1,2,⋯,n,p=1,2,∞
p
=
1
p=1
p=1 时即为 L1 范数,
p
=
2
p=2
p=2 时即为 L2 范数,
p
=
∞
p=infty
p=∞ 时为无穷(最大)范数。Normalizer
默认采用 L2 范数。
对 X X X 进行 L2 正则化:
from sklearn.preprocessing import Normalizer
import numpy as np
X = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8]
])
scaler = Normalizer().fit(X)
print(scaler.transform(X))
# [[0.18257419 0.36514837 0.54772256 0.73029674]
# [0.37904902 0.45485883 0.53066863 0.60647843]]
如果要采用最大范数或 L1 范数,只需要:
scaler = Normalizer('max').fit(X)
print(scaler.transform(X))
# [[0.25 0.5 0.75 1. ]
# [0.625 0.75 0.875 1. ]]
scaler = Normalizer('l1').fit(X)
print(scaler.transform(X))
# [[0.1 0.2 0.3 0.4 ]
# [0.19230769 0.23076923 0.26923077 0.30769231]]
四、绝对值最大标准化(MaxAbsScaler)
对 X X X 进行绝对值最大标准化即对 X X X 的每一列,根据其最大绝对值进行缩放。具体过程如下:
记
M a x A b s ( a i ) = max ( ∣ x 1 i ∣ , ∣ x 2 i ∣ , ⋯ , ∣ x n i ∣ ) , M a x A b s ( X ) = ( M a x A b s ( a 1 ) , ⋯ , M a x A b s ( a d ) ) T mathrm{MaxAbs}(boldsymbol{a_i})=max(|x_{1i}|,|x_{2i}|,cdots,|x_{ni}|),quad mathrm{MaxAbs}(X)=(mathrm{MaxAbs}(boldsymbol{a}_1),cdots, mathrm{MaxAbs}(boldsymbol{a}_d))^{mathrm T} MaxAbs(ai)=max(∣x1i∣,∣x2i∣,⋯,∣xni∣),MaxAbs(X)=(MaxAbs(a1),⋯,MaxAbs(ad))T
设 X X X 进行绝对值最大标准化后得到 Z Z Z,利用 numpy 的广播机制,有
Z = X M a x A b s ( X ) T Z=frac{X}{mathrm{MaxAbs}(X)^{mathrm T}} Z=MaxAbs(X)TX
对 X X X 进行绝对值最大标准化:
from sklearn.preprocessing import MaxAbsScaler
import numpy as np
X = np.array([
[1, -1, 2],
[2, 0, 0],
[0, 1, -1]
])
scaler = MaxAbsScaler().fit(X)
print(scaler.transform(X))
# [[ 0.5 -1. 1. ]
# [ 1. 0. 0. ]
# [ 0. 1. -0.5]]
五、二值化(Binarizer)
对 X X X 进行二值化就是设定一个阈值, X X X 中大于该阈值的元素置为 1 1 1,小于等于该阈值的元素置为 0 0 0。
Binarizer
默认的阈值为
0
0
0。
对 X X X 进行二值化:
from sklearn.preprocessing import Binarizer
import numpy as np
X = np.array([
[1, -1, 2],
[2, 0, 0],
[0, 1, -1]
])
transformer = Binarizer().fit(X)
print(transformer.transform(X))
# [[1 0 1]
# [1 0 0]
# [0 1 0]]
若将阈值调为 1 1 1,则结果变成:
transformer = Binarizer(threshold=1).fit(X)
print(transformer.transform(X))
# [[0 0 1]
# [1 0 0]
# [0 0 0]]
事实上,利用 numpy 的特性,我们可以只用 numpy 完成这些操作:
import numpy as np
def binarizer(X, threshold):
Y = X.copy()
Y[Y > threshold] = 1
Y[Y <= threshold] = 0
return Y
X = np.array([
[1, -1, 2],
[2, 0, 0],
[0, 1, -1]
])
print(binarizer(X, 0))
# [[1 0 1]
# [1 0 0]
# [0 1 0]]