Normalize / Standardize / Rescale
我们在处理数据的时候,常常需要对数据做这样一些操作,如Normalize / Standardize / Rescale ,那它们具体的定义是什么呢。
Rescale(尺度变换):
Rescale字面意思是重新缩放,将一个向量进行尺度变换,意味着添加或减去一个常数,然后乘以或除以一个常数,就像更改数据的测量单位一样,例如,将温度从摄氏度转换为华氏度。
Normalize(规范化;归一化):
Normalize字面意思是规范化,将一个向量进行规范化,通常意味着除以这个向量的范数。它还经常指通过向量的最小值和范围重新缩放,使所有元素位于0到1之间,从而使数据集中列的所有值具有共同的比例。
Standardize(标准化):
标准化一个向量通常意味着减去一个位移因子,然后除以一个尺度因子。例如,如果向量具有高斯分布,则可以减去平均值并除以标准差,从而获得平均值为0,标准差为1的标准正态随机变量。
为什么要Standardize / Normalize变量?
Standardize 标准化:
当我们比较不同单位的被测量时,将特征标准化为均值为0,标准偏差为1很重要。因为在不同尺度上测量的变量对分析的贡献不同,最终可能会产生偏差。
例如,范围在0到1000之间的变量将大于范围在0到1之间的变量。比如,使用这些没有标准化的变量,会在分析中给1000的变量较大权重。将数据转换为可比较的尺度可以防止这个问题。典型的数据标准化程序使范围和/或数据可变性相等。
Normalize归一化:
类似地,归一化的目标是将数据集中每列的值更改为具有公共比例,从而不会扭曲数据范围中的差异。对于机器学习,数据集一般不需要归一化,只有当特征有不同的范围时才需要。
例如,考虑一个包含两个特征的数据集,年龄和收入(x2)。年龄在0-100岁之间,收入在0 - 10万及以上,收入大约是年龄的1000倍。所以,这两个特征在完全不同的范围内。当我们做进一步的分析时,例如多元线性回归,归属收入由于其更大的值,本质上对结果的影响更大。但这并不一定意味着它作为一种预测因素更重要。所以我们将数据归一化,使所有的变量都在同一个范围内。
什么时候应该Standardize / Normalize变量?
Standardize:
假设数据具有高斯分布(钟形曲线)。即如果数据分布是高斯分布,则该技术更有效。当数据具有不同的尺度并且正在使用的算法确实假设数据具有高斯分布(例如线性回归、逻辑回归和线性判别分析)时,标准化是有用的。
Normalize:
当不知道数据的分布,或者知道分布不是高斯分布时,归一化是一种很好的技术。当数据具有不同的尺度并且使用的算法没有对数据的分布(例如k近邻和人工神经网络)进行假设时,归一化是有用的。
示例
数据
本文中使用了来自Kaggle的Lending Club贷款数据集来演示示例。
数据:https://www.kaggle.com/wendykan/lending-club-loan-data
导入库:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
导入数据集:
导入三列数据Loan amount、int_rate和installment,的前30000行(为了减少计算时间)
cols = ['loan_amnt', 'int_rate', 'installment']
data = pd.read_csv('loan.csv', nrows = 30000, usecols = cols)
如果导入整个数据,则某些列中会缺少值。可以使用pandas里的drop na方法简单地删除缺少值的行。
基本分析:
现在让我们分析数据集的基本统计值。
data.describe()
不同的变量表示不同的值范围,因此具有不同的幅度。不仅最小值和最大值不同,而且它们分布在不同宽度的范围内。
标准化(标准标量):
正如我们之前所讨论的,标准化(或z分数标准化)意味着将变量居中于0,并将方差标准化于1。这个过程包括减去每个观测值的平均值,然后除以标准差。
准化的结果是特征将被重新缩放,使它们具有标准正态分布的属性:
均值μ=0 and 方差σ=1
代码:
使用scikit-learn的StandardScaler去除平均值并将数据缩放到单位方差。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
然后检查均值和标准方差值:
print(data_scaled.mean(axis=0))
print(data_scaled.std(axis=0))
如预期,每个变量的均值现在都在0左右,标准差为1。因此,所有的变量值都在同一范围内。
print('Min values (Loan Amount, Int rate and Installment): ', data_scaled.min(axis=0))
print('Max values (Loan Amount, Int rate and Installment): ', data_scaled.max(axis=0))
然而,最小值和最大值根据变量开始时的分布情况而变化,并且受到异常值存在的高度影响。
归一化(最小-最大标量):
在这种方法中,数据被缩放到一个固定的范围——通常是0到1。
与标准化相比,拥有这个有界范围的代价是我们最终会得到更小的标准差,这可以抑制异常值的影响。因此,最小最大值标量对异常值敏感。
代码:
从Scikit-learn中导入MinMaxScalar并将其应用到我们的数据集。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data_scaled = scaler.fit_transform(data)
检查均值和标准差值:
print('means (Loan Amount, Int rate and Installment): ', data_scaled.mean(axis=0))
print('std (Loan Amount, Int rate and Installment): ', data_scaled.std(axis=0))
在MinMaxScaling之后,分布不是均值为0,标准差也不是1。但是最小值和最大值是跨变量标准化的,与标准化不同。
print('Min (Loan Amount, Int rate and Installment): ', data_scaled.min(axis=0))
print('Max (Loan Amount, Int rate and Installment): ', data_scaled.max(axis=0))
鲁棒标量(scaling到中位数和分位数):
使用中位数和分位数进行缩放包括减去所有观测值的中位数,然后除以四分位数差。它使用对异常值具有鲁棒性的统计数据来缩放特征。
四分位数差是指第75和第25分位数之间的差:
IQR = 75th quantile — 25th quantile
计算公式:
X_scaled = (X — X.median) / IQR
代码:
首先,从Scikit学习中导入RobustScalar。
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
data_scaled = scaler.fit_transform(data)
检查平均值和标准差值:
print('means (Loan Amount, Int rate and Installment): ', data_scaled.mean(axis=0))
print('std (Loan Amount, Int rate and Installment): ', data_scaled.std(axis=0))
可以看到,分布不是以均值为0,标准差也不是1。最小值和最大值也不像MinMaxScaler那样设置为一定的上限和下限。
参考文献:
- https://www.udemy.com/feature-engineering-for-machine-learning/
- https://www.geeksforgeeks.org/python-how-and-where-to-apply-feature-scaling/