玩命加载中 . . .

Scaler-数据标准化


数据标准化

在深度学习/机器学习领域,数据标准化是一个应用非常广泛的手段。所谓标准化,即消除原始数据中不同特征之间的量纲差异,使得后续的训练过程更加合理有效

StandardScaler:标准差标准化

这是应用非常广泛的一种标准化方式:根据数据的均值、方差进行标准化。

通常来说,数据的形式是一个$N\times D$的矩阵,其中$N$为样本数量,$D$为特征维度。而标准化则是在某个特征维度上,对全部的样本进行归一。

具体地,接下来,我们初始化一个$4\times 5$的矩阵作为原始数据,对其进行标准差标准化:

feature_nums = 5 # 5个特征维度
sample_nums = 4 # 4个样本
data = np.random.randint(low=-5, high=5, size=(sample_nums, feature_nums)) # 创建一个矩阵
print(data)
'''
[[-2  3  0  0 -1]
 [-1  2 -1 -2  0]
 [-1  3  0 -3  3]
 [ 0 -1 -3 -4  3]]
'''

接下来,计算均值和标准差:

mean = np.mean(data, axis=0) # 指定轴为行轴,计算均值
std = np.std(data, axis=0) # 指定轴为列轴,计算标准差
standard_data = (data - mean) / std
print('均值: ', mean)
print('标准差: ', std)
print('标准差标准化数据: \n', standard_data)
'''
均值:  [-1.    1.75 -1.   -2.25  1.25]
标准差:  [0.70710678 1.63935963 1.22474487 1.47901995 1.78535711]
标准差标准化数据: 
 [[-1.41421356  0.76249285  0.81649658  1.52127766 -1.26025208]
 [ 0.          0.15249857  0.          0.16903085 -0.70014004]
 [ 0.          0.76249285  0.81649658 -0.50709255  0.98019606]
 [ 1.41421356 -1.67748427 -1.63299316 -1.18321596  0.98019606]]
'''

当然,也可以逆向进行还原原始数据:

recon_data = standard_data * std + mean # 还原
print('还原原始数据: \n', recon_data)
'''
还原原始数据: 
 [[-2.  3.  0.  0. -1.]
 [-1.  2. -1. -2.  0.]
 [-1.  3.  0. -3.  3.]
 [ 0. -1. -3. -4.  3.]]
'''

sklearn库快捷用法

导入sklearn包之后,便可快速使用其中的标准化工具,而无需我们再手工实现这个方法。

我们通过一个简单的实例展示其用法。

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split

iris = datasets.load_iris()
X = iris.data
y = iris.target

# 1)归一化前,将原始数据分割
X_train, X_test, y_train, y_test = train_test_split(X, y, seed = 666)

# 2)导入均值方差归一化模块:StandardScaler
from sklearn.preprocessing import StandardScaler

# 实例化,不需要传入参数
standardScaler = StandardScaler()

# 3)fit过程:返回StandardScaler对象,对象内包含训练数据集的均值和方差
# fit过程,传入训练数据集;
standardScaler.fit(X_train)
# 输出:StandardScaler(copy=True, with_mean=True, with_std=True)

# fit后可通过standardScaler查看均值和标准差
# standardScaler.mean_:查看均值
# standardScaler.scale_:查看标准差

# 4)transform:对训练数据集和测试数据集进行归一化,分别传入对应的数据集
# 归一化并没有改变训练数据集,而是又生成一个新的矩阵,除非将新生成的数据集赋给原数据集,一般不改变原数据
X_train_standard = standardScaler.transform(X_train)
X_test_standard = standardScaler.transform(X_test)

# 接下来就是使用归一化后的数据集训练并测试模型...

自定义Scaler

上面的讨论均基于数据是二维的尺寸(即行数表示样本数量、列数表示特征数量)这一大前提。那么如果现在将数据集改为三维,该如何做标准化?这实际上就需要灵活运用numpy的两个方法mean(),std()

考虑一个现实例子:今有$M$台风力涡轮机,每台风机均有$N$条数据,每条数据包含$D$项观测指标,故组成一个尺寸为$M\times N\times D$的三维张量数据集$\mathcal{D}$。我们希望对每台风力涡轮机,单独进行数据标准化(不同的风机所处环境有差异,若统一进行标准化可能带来误差、弱化数据异质性)。

于是我们需要实现一个自定义类Scaler

class Scaler:
    def __init__(self) -> None:
        pass
        
    def fit(self, data: np.ndarray):
        self.mean = data.mean(axis=1, keepdims=True) # 这里指定轴序号,非常重要,同时设定keepdims为True
        self.std = data.std(axis=1, keepdims=True)
    
    def transform(self, data: np.ndarray):
        return (data - self.mean) / self.std

    def inverse_transform(self, data:np.ndarray):
        return data * self.std + self.mean

接下来应用一下这个自定义标准化工具:

# 初始化原始数据
turbine_nums = 2 # 简单起见,设置2台风力涡轮机
sample_nums = 4
feature_nums = 5
raw_data = np.random.randint(low=-10, high=10, size=(turbine_nums, sample_nums, feature_nums))
print('原始数据尺寸: ', raw_data.shape)
print('原始数据: \n', raw_data)
# 实例化标准化工具类
scaler = Scaler()
scaler.fit(raw_data)
print('均值: ', scaler.mean)
print('标准差: ', scaler.std)
# 标准化数据
standard_data = scaler.transform(raw_data)
print('标准化数据: \n', standard_data)
# 还原
recon_data = scaler.inverse_transform(standard_data)
print('还原数据: \n', recon_data)
'''
原始数据尺寸:  (2, 4, 5)
原始数据: 
 [[[  6   2  -5   4 -10]
  [ -7 -10  -8   0   7]
  [ -9   6  -2  -7  -2]
  [  9   0  -5   8 -10]]

 [[  8   5   7  -6  -3]
  [ -1   1 -10   1  -6]
  [ -2  -8  -2   2   4]
  [ -7  -6   8  -7  -8]]]
  
 均值:  [[[-0.25 -0.5  -5.    1.25 -3.75]]
 [[-0.5  -2.    0.75 -2.5  -3.25]]]
标准差:  [[[7.85413904 5.89491306 2.12132034 5.53962995 7.01338007]]
 [[5.40832691 5.24404424 7.32717544 4.03112887 4.54835135]]]
  
标准化数据: 
 [[[ 0.79575877  0.42409446  0.          0.49642305 -0.89115376]
  [-0.85941947 -1.61155897 -1.41421356 -0.22564684  1.53278446]
  [-1.11406227  1.10264561  1.41421356 -1.48926915  0.24952305]
  [ 1.17772298  0.08481889  0.          1.21849294 -0.89115376]]

 [[ 1.57165056  1.33484762  0.85298899 -0.86824314  0.05496497]
  [-0.09245003  0.57207755 -1.46714107  0.86824314 -0.60461468]
  [-0.2773501  -1.14415511 -0.37531516  1.11631261  1.59398416]
  [-1.20185043 -0.76277007  0.98946723 -1.11631261 -1.04433445]]]
  
还原数据: 
 [[[ 6.00000000e+00  2.00000000e+00 -5.00000000e+00  4.00000000e+00
   -1.00000000e+01]
  [-7.00000000e+00 -1.00000000e+01 -8.00000000e+00  0.00000000e+00
    7.00000000e+00]
  [-9.00000000e+00  6.00000000e+00 -2.00000000e+00 -7.00000000e+00
   -2.00000000e+00]
  [ 9.00000000e+00 -5.55111512e-17 -5.00000000e+00  8.00000000e+00
   -1.00000000e+01]]

 [[ 8.00000000e+00  5.00000000e+00  7.00000000e+00 -6.00000000e+00
   -3.00000000e+00]
  [-1.00000000e+00  1.00000000e+00 -1.00000000e+01  1.00000000e+00
   -6.00000000e+00]
  [-2.00000000e+00 -8.00000000e+00 -2.00000000e+00  2.00000000e+00
    4.00000000e+00]
  [-7.00000000e+00 -6.00000000e+00  8.00000000e+00 -7.00000000e+00
   -8.00000000e+00]]]
'''

MinMaxScaler

利用特征的最大值和最小值的绝对差,将原始的数据映射到$[0,1]$范围内。

from sklearn.preprocessing import StandardScaler, MinMaxScaler
feature_nums = 5 # 5个特征维度
sample_nums = 4 # 4个样本
data = np.random.randint(low=-5, high=5, size=(sample_nums, feature_nums)) # 创建一个矩阵
print(data)
scaler = MinMaxScaler()
scaler.fit(data)
minmax_standard_data = scaler.transform(data)
print('最值归一化数据: \n', minmax_standard_data)
'''
[[-3  2 -3  4 -1]
 [ 1 -3 -2 -4 -4]
 [ 1  1  2  4  0]
 [-3  3  3  0 -1]]
 最值归一化数据: 
 [[0.         0.83333333 0.         1.         0.75      ]
 [1.         0.         0.16666667 0.         0.        ]
 [1.         0.66666667 0.83333333 1.         1.        ]
 [0.         1.         1.         0.5        0.75      ]]
'''

文章作者: 鹿卿
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 鹿卿 !
评论
  目录