created on: 2020-01-20
@author: 假如我年华正好
归一化/标准化实质是一种线性变换(对向量 X X X按比例缩放,再进行平移),在样本给定的情况下, X m a x X_{max} Xmax, X m i n X_{min} Xmin, μ \mu μ, σ \sigma σ 都可看作常数。
线性变换有很多良好的性质,决定了对数据改变后不会造成“失效”,反而能提高数据的表现,这些性质是归一化/标准化的前提。比如有一个很重要的性质:
某些模型求解需要
【⭐注意】:基于树的算法几乎是唯一不受输入大小影响的算法
为了做无量纲化
使得不同度量之间的特征具有可比性;
对目标函数的影响体现在几何分布(离散型概率分布)上,而不是数值上
避免数值问题
太大的数会引发数值问题。
(参考来源:https://blog.csdn.net/pipisorry/article/details/52247379)
有些模型在各个维度进行不均匀伸缩后,最优解与原来不等价,例如SVM(距离分界面远的也拉近了,支持向量变多?)。对于这样的模型,除非本来各维数据的分布范围就比较接近,否则必须进行标准化,以免模型参数被分布范围较大或较小的数据dominate。
有些模型在各个维度进行不均匀伸缩后,最优解与原来等价,例如logistic regression(因为θ的大小本来就自学习出不同的feature的重要性吧?)。对于这样的模型,是否标准化理论上不会改变最优解。但是,由于实际求解往往使用迭代算法,如果目标函数的形状太“扁”,迭代算法可能收敛得很慢甚至不收敛(模型结果不精确)。所以对于具有伸缩不变性的模型,最好也进行数据标准化。
有些模型/优化方法的效果会强烈地依赖于特征是否归一化,如LogisticReg,SVM,NeuralNetwork,SGD等。
不需要归一化的模型:
0/1取值的特征通常不需要归一化,归一化会破坏它的稀疏性。
有些模型则不受归一化影响,如DecisionTree。
把数据映射到 [0,1](或者 [-1, 1])区间内
把有量纲表达式变成无量纲的纯量,便于不同单位或量级的指标能够进行比较和加权。
缩放仅仅跟最大、最小值的差别有关
区间放缩法是归一化的一种
Min-Max Normalization(也叫离差标准化):输出范围 [0, 1]
X i − X m i n X m a x − X m i n \frac{X_i - X_{min}}{X_{max} - X_{min}} Xmax−XminXi−Xmin
from sklearn import preprocessing
norm_x = preprocessing.MinMaxScaler().fit_transform(x)
非线性归一化:
Z-score规范化(标准差标准化 / 零均值标准化)
通过求z-score的方法,转换为标准正态分布(均值为0,标准差为1)
和整体样本分布相关,每个样本点都能对标准化产生影响,通过均值( μ \mu μ)和标准差( σ \sigma σ)体现出来。
也能取消由于量纲不同引起的误差,使不同度量之间的特征具有可比性
输出范围:[-∞, +∞]
X i − μ σ \frac{X_i - \mu}{\sigma} σXi−μ
from sklearn import preprocessing
std_x = preprocessing.StandardScaler().fit_transform(x)
数据标准化也就是统计数据的指数化。数据标准化处理主要包括数据同趋化处理和无量纲化处理两个方面。数据同趋化处理主要解决不同性质数据问题,对不同性质指标直接加总不能正确反映不同作用力的综合结果,须先考虑改变逆指标数据性质,使所有指标对测评方案的作用力同趋化,再加总才能得出正确结果。数据无量纲化处理主要解决数据的可比性。经过上述标准化处理,原始数据均转换为无量纲化指标测评值,即各指标值都处于同一个数量级别上,可以进行综合测评分析。(原文链接:https://blog.csdn.net/pipisorry/article/details/52247379)
PCA的时候需要做中心化(centering)(参考:CSDN博文)
与标准化的区别:(参考:CSDN博文)
(参考来源:知乎回答)
归一化和标准化,都是将点平移然后缩短距离,但标准化不改变数据分布(几何距离)
⭐以下参考来源:GitHub项目:feature-engineering-and-feature-selection
Method | Definition | Pros | Cons |
---|---|---|---|
Normalization - Standardization (Z-score scaling) | removes the mean and scales the data to unit variance. z = (X - X.mean) / std |
feature is rescaled to have a standard normal distribution that centered around 0 with SD of 1 | compress the observations in the narrow range if the variable is skewed or has outliers, thus impair the predictive power. |
Min-Max scaling | transforms features by scaling each feature to a given range. Default to [0,1]. X_scaled = (X - X.min / (X.max - X.min) |
/ | compress the observations in the narrow range if the variable is skewed or has outliers, thus impair the predictive power. |
Robust scaling | removes the median and scales the data according to the quantile range (defaults to IQR) X_scaled = (X - X.median) / IQR |
better at preserving the spread of the variable after transformation for skewed variables | / |
from sklearn.preprocessing import RobustScaler
RobustScaler().fit_transform(X)
Z-score 和 Min-max方法将把大部分数据压缩到一个狭窄的范围,
而 robust scaler 在保持数据整体情况方面做得更好,尽管它不能从处理结果中移除异常值。
(但是请记住,清除/查找离群值是数据清理中的另一个主题,应该事先完成。)
⭐附加参考资源:
另外,在sklearn官方文档 中还有个Normalization(正则化),定义为:the process of scaling individual samples to have unit norm.
from sklearn import preprocessing
preprocessing.Normalizer(norm="l2").fit_transform(x)
# norm: The norm to use to normalize each non zero sample.
# ‘l1’, ‘l2’, or ‘max’, optional (‘l2’ by default)
❗ 特别注意这里的 Normalizer
是对行(对样本)进行处理,而本文前面提到的都是对列(对特征)进行处理。
from sklearn import preprocessing
X = [[ 1., -1., 2.],
[ 2., 0., 0.],
[ 0., 1., -1.],
[ 0., 1., -1.]
]
preprocessing.normalize(X, norm='l1', return_norm =True)
Out[1]:
(array([[ 0.25, -0.25, 0.5 ],
[ 1. , 0. , 0. ],
[ 0. , 0.5 , -0.5 ],
[ 0. , 0.5 , -0.5 ]]), array([4., 2., 2., 2.]))
preprocessing.normalize(X, norm='l2', return_norm =True)
Out[2]:
(array([[ 0.40824829, -0.40824829, 0.81649658],
[ 1. , 0. , 0. ],
[ 0. , 0.70710678, -0.70710678],
[ 0. , 0.70710678, -0.70710678]]),
array([2.44948974, 2. , 1.41421356, 1.41421356]))
preprocessing.normalize(X, norm='max', return_norm =True)
Out[3]:
(array([[ 0.5, -0.5, 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -1. ],
[ 0. , 1. , -1. ]]), array([2., 2., 1., 1.]))