0


数据预处理之数据的特征缩放——sklearn实现

目录

前言

在现实任务中,我们的数据集往往存在各种各样的问题,如果不对数据进行预处理,模型就无法得到有效的训练。

例如,对于神经网络而言,权重矩阵和阈值向量一般都是在

  1. (
  2. 0
  3. ,
  4. 1
  5. )
  6. (0,1)
  7. (0,1) 范围内初始化。如果输入的特征向量的某些分量过大或过小,可能会导致神经网络无法学习到一些重要的特征,因此有必要对输入的向量进行**特征缩放**。

sklearn 中的

  1. sklearn.preprocessing

中提供了数据预处理的相关函数,本文将主要围绕特征缩放来展开讲解。

一、标准化(StandardScaler)

设数据矩阵为

  1. X
  2. =
  3. [
  4. x
  5. 1
  6. T
  7. x
  8. 2
  9. T
  10. x
  11. n
  12. T
  13. ]
  14. X= \begin{bmatrix} \boldsymbol{x}_1^{\mathrm T} \\ \boldsymbol{x}_2^{\mathrm T} \\ \vdots \\ \boldsymbol{x}_n^{\mathrm T} \end{bmatrix}
  15. X=⎣⎢⎢⎢⎡​x1Tx2T​⋮xnT​​⎦⎥⎥⎥⎤​

其中

  1. x
  2. i
  3. =
  4. (
  5. x
  6. i
  7. 1
  8. ,
  9. x
  10. i
  11. 2
  12. ,
  13. ,
  14. x
  15. i
  16. d
  17. )
  18. T
  19. \boldsymbol{x}_i=(x_{i1}, x_{i2},\cdots,x_{id})^{\mathrm T}
  20. xi​=(xi1​,xi2​,⋯,xid​)T 为特征向量。

在进行下一步之前,我们有必要先引入数据矩阵的均值和标准差。

我们知道,对于数据向量

  1. a
  2. =
  3. (
  4. a
  5. 1
  6. ,
  7. ,
  8. a
  9. n
  10. )
  11. T
  12. \boldsymbol{a}=(a_1,\cdots,a_n)^{\mathrm T}
  13. a=(a1​,⋯,an​)T 而言(这里的向量可以理解成一组数据,之所以称之为向量,是为了方便后续的表述),其均值和标准差分别为:
  14. μ
  15. (
  16. a
  17. )
  18. =
  19. a
  20. 1
  21. +
  22. +
  23. a
  24. n
  25. n
  26. ,
  27. σ
  28. (
  29. a
  30. )
  31. =
  32. (
  33. 1
  34. n
  35. a
  36. μ
  37. (
  38. a
  39. )
  40. 2
  41. )
  42. 1
  43. /
  44. 2
  45. ,
  46.   
  47. μ
  48. (
  49. a
  50. )
  51. =
  52. (
  53. μ
  54. (
  55. a
  56. )
  57. ,
  58. ,
  59. μ
  60. (
  61. a
  62. )
  63. n
  64. )
  65. T
  66. \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}
  67. μ(a)=na1​+⋯+an​​,σ(a)=(n1​∥a−μ(a)∥2)1/2,其中μ(a)=(n个μ(a),⋯,μ(a)​​)T

我们将

  1. X
  2. X
  3. X 写成行向量的形式:
  4. X
  5. =
  6. (
  7. a
  8. 1
  9. ,
  10. a
  11. 2
  12. ,
  13. ,
  14. a
  15. d
  16. )
  17. X =(\boldsymbol{a}_1,\boldsymbol{a}_2,\cdots,\boldsymbol{a}_d)
  18. X=(a1​,a2​,⋯,ad​),其中每个
  19. a
  20. i
  21. \boldsymbol{a}_i
  22. ai 均为列向量,因此
  23. μ
  24. (
  25. X
  26. )
  27. =
  28. (
  29. μ
  30. (
  31. a
  32. 1
  33. )
  34. ,
  35. μ
  36. (
  37. a
  38. 2
  39. )
  40. ,
  41. ,
  42. μ
  43. (
  44. a
  45. d
  46. )
  47. )
  48. T
  49. σ
  50. (
  51. X
  52. )
  53. =
  54. (
  55. σ
  56. (
  57. a
  58. 1
  59. )
  60. ,
  61. σ
  62. (
  63. a
  64. 2
  65. )
  66. ,
  67. ,
  68. σ
  69. (
  70. a
  71. d
  72. )
  73. )
  74. T
  75. \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}
  76. μ(X)σ(X)​=(μ(a1​),μ(a2​),⋯,μ(ad​))T=(σ(a1​),σ(a2​),⋯,σ(ad​))T

设对

  1. X
  2. X
  3. X 进行标准化后得到
  4. Z
  5. Z
  6. Z,利用 numpy 的广播机制,
  7. Z
  8. Z
  9. Z 有如下形式
  10. Z
  11. =
  12. (
  13. z
  14. 1
  15. ,
  16. z
  17. 2
  18. ,
  19. ,
  20. z
  21. d
  22. )
  23. ,
  24.   
  25. z
  26. i
  27. =
  28. a
  29. i
  30. μ
  31. (
  32. a
  33. i
  34. )
  35. σ
  36. (
  37. a
  38. i
  39. )
  40. ,
  41.     
  42. i
  43. =
  44. 1
  45. ,
  46. 2
  47. ,
  48. ,
  49. d
  50. 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
  51. Z=(z1​,z2​,⋯,zd​),其中zi​=σ(ai​)ai​−μ(ai​)​,i=1,2,⋯,d

当然

  1. Z
  2. Z
  3. Z 可以更为简洁地表成
  4. Z
  5. =
  6. X
  7. μ
  8. (
  9. X
  10. )
  11. T
  12. σ
  13. (
  14. X
  15. )
  16. T
  17. Z=\frac{X-\mu(X)^{\mathrm T}}{\sigma(X)^{\mathrm T}}
  18. Z=σ(X)TX−μ(X)T

查看

  1. X
  2. X
  3. X 的均值,方差和标准差:
  1. from sklearn.preprocessing import StandardScaler
  2. import numpy as np
  3. # 数据矩阵
  4. X = np.array([[1,3],[0,1]])# 创建一个scaler实例并将数据传入该实例中
  5. scaler = StandardScaler().fit(X)# 查看X的的均值,方差和标准差print(scaler.mean_)# [0.5 2. ]print(scaler.var_)# [0.25 1. ]print(scaler.scale_)# [0.5 1. ]

之所以标准差为

  1. scale_

,是因为标准差控制着我们数据的缩放程度。需要注意的是,如果数据矩阵的某一列方差为

  1. 0
  2. 0
  3. 0,则
  1. scale_

  1. 1
  2. 1
  3. 1,即这一列不进行缩放。

  1. X
  2. X
  3. X 进行标准化,只需要使用
  1. transfrom()

方法:

  1. X = np.array([[243,80],[19,47]])
  2. scaler = StandardScaler().fit(X)# 进行缩放
  3. X_scaled = scaler.transform(X)# [[ 1. 1.]# [-1. -1.]]

查看

  1. X_scaled

的均值和标准差:

  1. print(X_scaled.mean(axis=0))# [0. 0.]print(X_scaled.std(axis=0))# [1. 1.]

可以看到

  1. X_scaled

均值为

  1. 0
  2. \boldsymbol 0
  3. 0 标准差为
  4. 1
  5. \boldsymbol 1
  6. 1,即
  7. X
  8. X
  9. X 已经标准化。

当然我们也可以用

  1. scaler

去标准化新的样本,标准化过程采用

  1. X
  2. X
  3. X 的均值和标准差:
  1. X = np.array([[243,80],[19,47]])
  2. scaler = StandardScaler().fit(X)# 缩放新的样本print(scaler.transform([[2,3]]))# [[-1.15178571 -3.66666667]]

二、归一化(MinMaxScaler)

  1. X
  2. X
  3. X 进行归一化就是将
  4. X
  5. X
  6. X 中的所有元素缩放至
  7. [
  8. 0
  9. ,
  10. 1
  11. ]
  12. [0,1]
  13. [0,1] 内。具体过程如下:

  1. a
  2. i
  3. =
  4. min
  5. (
  6. x
  7. 1
  8. i
  9. ,
  10. x
  11. 2
  12. i
  13. ,
  14. ,
  15. x
  16. n
  17. i
  18. )
  19. ,
  20. a
  21. i
  22. =
  23. max
  24. (
  25. x
  26. 1
  27. i
  28. ,
  29. x
  30. 2
  31. i
  32. ,
  33. ,
  34. x
  35. n
  36. i
  37. )
  38. X
  39. =
  40. (
  41. a
  42. 1
  43. ,
  44. a
  45. 2
  46. ,
  47. ,
  48. a
  49. d
  50. )
  51. T
  52. ,
  53. X
  54. =
  55. (
  56. a
  57. 1
  58. ,
  59. a
  60. 2
  61. ,
  62. ,
  63. a
  64. d
  65. )
  66. T
  67. \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}}
  68. ai​​=min(x1i​,x2i​,⋯,xni​),ai​​=max(x1i​,x2i​,⋯,xni​)X​=(a1​​,a2​​,⋯,ad​​)T,X=(a1​​,a2​​,⋯,ad​​)T

  1. X
  2. X
  3. X 进行归一化后得到
  4. Z
  5. Z
  6. Z,利用 numpy 的广播机制,我们有
  7. Z
  8. =
  9. X
  10. X
  11. T
  12. X
  13. T
  14. X
  15. T
  16. Z=\frac{X-\underline{X}^{\mathrm T}}{\overline{X}^{\mathrm T}-\underline{X}^{\mathrm T}}
  17. Z=XTXTXXT

先用

  1. make_blobs()

生成斑点数据集:

  1. from sklearn.preprocessing import MinMaxScaler
  2. from sklearn.datasets import make_blobs
  3. 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]]

  1. X
  2. X
  3. X 进行归一化:
  1. 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]]

如果我们想将

  1. X
  2. X
  3. X 中的元素缩放至
  4. (
  5. 1
  6. ,
  7. 2
  8. )
  9. (1, 2)
  10. (1,2) 区间内,只需要:
  1. 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)

  1. X
  2. X
  3. X 进行正则化也就是对其中的每个样本(**每一行**)进行正则化,即将每个样本的范数化为单位范数。具体过程如下:
  4. x
  5. i
  6. :
  7. =
  8. x
  9. i
  10. x
  11. i
  12. p
  13. ,
  14. i
  15. =
  16. 1
  17. ,
  18. 2
  19. ,
  20. ,
  21. n
  22. ,
  23. p
  24. =
  25. 1
  26. ,
  27. 2
  28. ,
  29. \boldsymbol{x}_i:=\frac{\boldsymbol{x}_i}{\Vert \boldsymbol{x}_i\Vert_p},\quad i=1,2,\cdots,n,\quad p=1,2,\infty
  30. xi​:=∥xi​∥pxi​​,i=1,2,⋯,n,p=1,2,∞
  31. p
  32. =
  33. 1
  34. p=1
  35. p=1 时即为 L1 范数,
  36. p
  37. =
  38. 2
  39. p=2
  40. p=2 时即为 L2 范数,
  41. p
  42. =
  43. p=\infty
  44. p=∞ 时为无穷(最大)范数。
  1. Normalizer

默认采用 L2 范数。


  1. X
  2. X
  3. X 进行 L2 正则化:
  1. from sklearn.preprocessing import Normalizer
  2. import numpy as np
  3. X = np.array([[1,2,3,4],[5,6,7,8]])
  4. 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 范数,只需要:

  1. scaler = Normalizer('max').fit(X)print(scaler.transform(X))# [[0.25 0.5 0.75 1. ]# [0.625 0.75 0.875 1. ]]
  2. 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)

  1. X
  2. X
  3. X 进行绝对值最大标准化即对
  4. X
  5. X
  6. X 的每一列,根据其最大绝对值进行缩放。具体过程如下:

  1. M
  2. a
  3. x
  4. A
  5. b
  6. s
  7. (
  8. a
  9. i
  10. )
  11. =
  12. max
  13. (
  14. x
  15. 1
  16. i
  17. ,
  18. x
  19. 2
  20. i
  21. ,
  22. ,
  23. x
  24. n
  25. i
  26. )
  27. ,
  28. M
  29. a
  30. x
  31. A
  32. b
  33. s
  34. (
  35. X
  36. )
  37. =
  38. (
  39. M
  40. a
  41. x
  42. A
  43. b
  44. s
  45. (
  46. a
  47. 1
  48. )
  49. ,
  50. ,
  51. M
  52. a
  53. x
  54. A
  55. b
  56. s
  57. (
  58. a
  59. d
  60. )
  61. )
  62. T
  63. \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}
  64. MaxAbs(ai​)=max(∣x1i​∣,∣x2i​∣,⋯,∣xni​∣),MaxAbs(X)=(MaxAbs(a1​),⋯,MaxAbs(ad​))T

  1. X
  2. X
  3. X 进行绝对值最大标准化后得到
  4. Z
  5. Z
  6. Z,利用 numpy 的广播机制,有
  7. Z
  8. =
  9. X
  10. M
  11. a
  12. x
  13. A
  14. b
  15. s
  16. (
  17. X
  18. )
  19. T
  20. Z=\frac{X}{\mathrm{MaxAbs}(X)^{\mathrm T}}
  21. Z=MaxAbs(X)TX

  1. X
  2. X
  3. X 进行绝对值最大标准化:
  1. from sklearn.preprocessing import MaxAbsScaler
  2. import numpy as np
  3. X = np.array([[1,-1,2],[2,0,0],[0,1,-1]])
  4. scaler = MaxAbsScaler().fit(X)print(scaler.transform(X))# [[ 0.5 -1. 1. ]# [ 1. 0. 0. ]# [ 0. 1. -0.5]]

五、二值化(Binarizer)

  1. X
  2. X
  3. X 进行二值化就是设定一个阈值,
  4. X
  5. X
  6. X 中**大于**该阈值的元素置为
  7. 1
  8. 1
  9. 1,**小于等于**该阈值的元素置为
  10. 0
  11. 0
  12. 0
  1. Binarizer

默认的阈值为

  1. 0
  2. 0
  3. 0

  1. X
  2. X
  3. X 进行二值化:
  1. from sklearn.preprocessing import Binarizer
  2. import numpy as np
  3. X = np.array([[1,-1,2],[2,0,0],[0,1,-1]])
  4. transformer = Binarizer().fit(X)print(transformer.transform(X))# [[1 0 1]# [1 0 0]# [0 1 0]]

若将阈值调为

  1. 1
  2. 1
  3. 1,则结果变成:
  1. transformer = Binarizer(threshold=1).fit(X)print(transformer.transform(X))# [[0 0 1]# [1 0 0]# [0 0 0]]

事实上,利用 numpy 的特性,我们可以只用 numpy 完成这些操作:

  1. import numpy as np
  2. defbinarizer(X, threshold):
  3. Y = X.copy()
  4. Y[Y > threshold]=1
  5. Y[Y <= threshold]=0return Y
  6. 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.


本文转载自: https://blog.csdn.net/weixin_44022472/article/details/123346449
版权归原作者 serity 所有, 如有侵权,请联系我们删除。

“数据预处理之数据的特征缩放&mdash;&mdash;sklearn实现”的评论:

还没有评论