目录
前言
在现实任务中,我们的数据集往往存在各种各样的问题,如果不对数据进行预处理,模型就无法得到有效的训练。
例如,对于神经网络而言,权重矩阵和阈值向量一般都是在
(
0
,
1
)
(0,1)
(0,1) 范围内初始化。如果输入的特征向量的某些分量过大或过小,可能会导致神经网络无法学习到一些重要的特征,因此有必要对输入的向量进行**特征缩放**。
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},\quad\sigma(\boldsymbol a)=\left(\frac1n \Vert \boldsymbol{a}-\boldsymbol{\mu}(\boldsymbol{a})\Vert^2\right)^{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}_i\Vert_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
defbinarizer(X, threshold):
Y = X.copy()
Y[Y > threshold]=1
Y[Y <= threshold]=0return 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]]
参考
[1] https://scikit-learn.org/stable/modules/preprocessing.html#preprocessing.
版权归原作者 serity 所有, 如有侵权,请联系我们删除。