使用Python对数据进行归一化规格化

5,383 阅读6分钟
原文链接: www.biaodianfu.com

数据归一化问题是数据挖掘中特征向量表达时的重要问题,当不同的特征成列在一起的时候,由于特征本身表达方式的原因而导致在绝对数值上的小数据被大数据“吃掉”的情况,这个时候我们需要做的就是对抽取出来的features vector进行归一化处理,以保证每个特征被分类器平等对待。先前的文章中已经介绍了几种常见的数据归一化的方法,这里对主要整理了如何将这些公式和方法转化程Python代码。

min-max标准化(Min-Max Normalization)

也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 – 1]之间。转换函数如下:

\[{x}_{normalization}=\frac{x-Min}{Max-Min}\]

x_min表示样本数据的最小值,x_max表示样本数据的最大值。

Python代码实现:

def max_min_normalization(x, max, min):
    return (x - min) / (max - min)

或:

def max_min_normalization(x):
    return [(float(i)-min(x))/float(max(x)-min(x)) for i in x]

找大小的方法除了使用list自带的max和min,推荐使用np.max和np.min,因为起功能更加强大。

>>> a = np.array([[0, 1, 6], [2, 4, 1]])
>>> np.max(a)
6
>>> np.max(a, axis=0) # max of each column
array([2, 4, 6])

参考链接:stackoverflow.com/questions/3…

如果想要将数据映射到[-1,1],则将公式换成:

\[{x}_{normalization}=\frac{x-x_{mean}}{Max-Min}\]

x_mean 表示平均值。

Python代码实现:

import numpy as np
 
def normalization(x):
    return [(float(i)-np.mean(x))/(max(x)-min(x)) for i in x]

该标准化方法有一个缺点就是,如果数据中有一些偏离正常数据的异常点,就会导致标准化结果的不准确性。

z-score标准化

z-score标准化方法适用于属性A的最大值和最小值未知的情况,或有超出取值范围的离群数据的情况。这种方法给予原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。

经过处理的数据符合标准正态分布,即均值为0,标准差为1,转化函数为:

\[{x}_{normalization}=\frac{x-\mu }{\sigma }\]

其中μ为所有样本数据的均值,σ为所有样本数据的标准差。

Python实现:

def z_score_normalization(x,mu,sigma):  
    return (x - mu) / sigma

mu为均值,sigma为标注差,所以代码可以改写为:

#定义数组:x = numpy.array(x)
#获取二维数组列方向的均值:x.mean(axis = 0)
#获取二维数组列方向的标准差:x.std(axis = 0)
 
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = numpy.array(x)
def z_score(x):
    return (x - np.mean(x)) / np.std(x, ddof = 1)

z-score标准化方法同样对于离群异常值的影响。改进的z-score标准化:将标准分公式中的均值改为中位数,将标准差改为绝对偏差。

\[{x}_{normalization}=\frac{x-{x}_{center} }{\sigma_1 }\]

中位数是指将所有数据进行排序,取中间的那个值,如数据量是偶数,则取中间两个数据的平均值。

# 中位数 英文:median
# 对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。
# 如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。
def get_median(data):
    data = sorted(data)
    size = len(data)
    if size % 2 == 0: # 判断列表长度为偶数
        median = (data[size/2]+data[size/2-1])/2
    if size % 2 == 1: # 判断列表长度为奇数
        median = data[(size-1)//2]
    return median

σ1为所有样本数据的绝对偏差,其计算公式为:

\[\frac{1}{N} \sum_{1}^{n}|x_{i} - x_{center}|\]

Sigmoid函数

Sigmoid函数是一个具有S形曲线的函数,是良好的阈值函数,在(0, 0.5)处中心对称,在(0, 0.5)附近有比较大的斜率,而当数据趋向于正无穷和负无穷的时候,映射出来的值就会无限趋向于1和0,是个人非常喜欢的“归一化方法”,之所以打引号是因为我觉得Sigmoid函数在阈值分割上也有很不错的表现,根据公式的改变,就可以改变分割阈值,这里作为归一化方法,我们只考虑(0, 0.5)作为分割阈值的点的情况:

\[{x}_{normalization}=\frac{1}{1+{e}^{-x}}\]

Python实现:

def sigmoid(X,useStatus):  
    if useStatus:  
        return 1.0 / (1 + np.exp(-float(X)));  
    else:  
        return float(X);

这里useStatus管理是否使用sigmoid的状态,方便调试使用。

sklearn中的归一化

sklearn.preprocessing 提供了一些实用的函数 用来处理数据的维度,以供算法使用。

1)均值-标准差缩放

即我们上边对应的z-score标准化。

from sklearn import preprocessing
import numpy as np
 
x_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])
x_scaled = preprocessing.scale(x_train)
print(x_scaled)
 
# output:
# [[ 0.         -1.22474487  1.33630621]
#  [ 1.22474487  0.         -0.26726124]
#  [-1.22474487  1.22474487 -1.06904497]]

2)min-max标准化

from sklearn import preprocessing
import numpy as np
 
x_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])
min_max_scaler = preprocessing.MinMaxScaler()
x_train_minmax = min_max_scaler.fit_transform(x_train)
print(x_train_minmax)
 
# output:
# [[ 0.5         0.          1.        ]
#  [ 1.          0.5         0.33333333]
#  [ 0.          1.          0.        ]]

3)最大值标准化(每个数值/每个维度的最大数值)

from sklearn import preprocessing
import numpy as np
 
x_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
max_abs_scaler = preprocessing.MaxAbsScaler()
x_train_maxabs = max_abs_scaler.fit_transform(x_train)
print(x_train_maxabs)
 
# output:
# [[ 0.5 -1.   1. ]
#  [ 1.   0.   0. ]
#  [ 0.   1.  -0.5]]

4)规范化

规范化是文本分类和聚类中向量空间模型的基础。

from sklearn import preprocessing
import numpy as np
 
x_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
x_normalized = preprocessing.normalize(x_train, norm='l2')
print(x_normalized)
 
# output:
# [[ 0.40824829 -0.40824829  0.81649658]
#  [ 1.          0.          0.        ]
#  [ 0.          0.70710678 -0.70710678]]

norm 该参数是可选的,默认值是l2(向量各元素的平方和然后求平方根),用来规范化每个非零向量,如果axis参数设置为0,则表示的是规范化每个非零的特征维度。

具体请参考:范数规则化L0、L1与L2范数

5)二值化(将数据转换到0和1)

from sklearn import preprocessing
import numpy as np
 
x_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
binarizer = preprocessing.Binarizer().fit(x_train)
print(binarizer)
print(binarizer.transform(x_train))
# output:
# Binarizer(copy=True, threshold=0.0)
# [[ 1.  0.  1.]
#  [ 1.  0.  0.]
#  [ 0.  1.  0.]]

参考链接: