爱吧机器人网 » 技术 > 机器学习 > 正文

浅析数据标准化和归一化 优化机器学习算法输出结果

关于标准化(standardization)

数据标准化能将原来的数据进行重新调整(一般也称为 z-score 规范化方法),以便他们具有标准正态分布的属性,即 μ=0 和 σ=1。其中,μ 表示平均值,σ 表示标准方差。数据标准化之后的形式可以按照如下公式进行计算:

如果我们是比较两个不同大小维度的数据,那么将这些数据标准化到以 0 为中心并且标准差为 1 的范围,这对许多的机器学习算法来说也是一般的要求。比如,从直觉上来说,我们可以将梯度下降看作一个特殊的例子。由于特征值 xj 在权重更新中发挥作用,那么某些权重可能比其他权重更新的速度更快,即:

 

其中,wj:=wj+Δwj,η 表示学习率,t 表示目标正确分类结果,o 表示模型的输出分类结果。

其他直观的例子包括 KNN 算法和一些聚类算法上面,都会使用这种数据标准化的方法。

事实上,我能想到唯一不需要数据标准化的算法就应该是基于决策树的算法了。我们来看一般的 CART 决策树算法。在这里我们不深入的分析信息熵的含义,我们可以把这个决策简单的想象成 is feature x_i >= some_val ?。从直观上来讲,我们真的不需要来关心数据特征在哪个大小维度(比如,不同数量级,不同领域 —— 这些真的不关心)。

那么,在哪些算法中特征数据标准化是比较重要的呢?比如下面这些算法:

1、对于基于欧几里得距离的 KNN 算法,如果你想要所有的数据对算法都有贡献,那么必须进行标准化;
2、k-means 算法;
3、逻辑回归,支持向量机,感知器,神经网络等,如果你正是在使用梯度下降(上升)来作为优化器,那么采用标准化会让权重更快的收敛;
4、线性判别分析,PCA,核方法;

另外,我们还要考虑我们的数据是需要进行“标准化(standardize)”还是“归一化(normalize)”(这里是缩放到 [0, 1] 范围)。因为有些算法假设我们的数据是以 0 为中心分布的,那么这时候进行标准化还是归一化就需要自己思考了。例如,如果我们对一个小型多层感知器(利用 tanh 激活函数)进行权重初始化,权重应该是 0 ,或者是以零为中心的小随机数,这样能更好的更新模型权重。作为一个经验法则,我想说的是:如果你不确定对数据进行标准化还是归一化,那么你就对数据进行标准化吧,至少它不会对数据和结果造成伤害。

标准化(Standardization)
数据的标准化是将数据按比例缩放,使之落入一个小的特定区间,标准化之后的数据可正可负,但是一般绝对值不会太大,一般是 z-score 规范化方法。
归一化(Normalization)
主要是为了数据处理提出来的,把数据映射到 0~1 范围之间处理,更加便捷快速,这应该归到数字信号处理范畴之内。一般方法是最小-最大缩放方法。

关于最小-最大缩放处理

还有一种数据处理的方法是最小 - 最大缩放。在这种方法中,数据被缩放到一个固定的范围 —— 通常是 0 到 1。与标准化相比,有限范围的损失值计算最终将得到较小的标准偏差,这也可以抑制一些异常值的影响。

最小 - 最大缩放处理可以通过以下公式完成:

选择 Z-score 标准化还是最小 - 最大缩放?

具体选择哪一个数据处理方法没有很明确的答案,它主要取决于具体的应用程序。

例如,在聚类分析中,为了比较基于特定距离度量的特征数据之间的相似性,数据标准化可能是一个特别重要的方式。另一个比较突出的例子就是主成分分析,我们通常采用标准化来做数据进行缩放。因为我们对最大化方差的方向感兴趣。

如何使用 scikit-learn 来实现标准化和归一化

当然,我们可以利用 Numpy 包来计算数据的 z-score,并使用前面提到的公式来进行标准化。但是,如果我们使用 Python 的开源机器学习库 scikit-learn 中的预处理模块来做,会更加便捷。

为了下面更好的讨论,我们采用 UCI 机器学习库中的 “Wine” 数据集来进行代码编写。

import pandas as pd
import numpy as np

df = pd.io.parsers.read_csv(
    'https://raw.githubusercontent.com/rasbt/pattern_classification/master/data/wine_data.csv',
     header=None,
     usecols=[0,1,2]
    )

df.columns=['Class label', 'Alcohol', 'Malic acid']
df.head()
  Class label Alcohol Malic acid
0 1 14.23 1.71
1 1 13.20 1.78
2 1 13.16 2.36
3 1 14.37 1.95
4 1 13.24 2.59

正如我们在上面的表格中所看到的,Alcohol 特征(百分比 / 体积)和 Malic acid(g/l)是在不同大小维度上面进行描述的,所有在比较或者组合这些特征之前,进行数据缩放是非常有必要的。

标准化和最小-最大缩放

from sklearn import preprocessing

std_scale = preprocessing.StandardScaler().fit(df[['Alcohol', 'Malic acid']])
df_std = std_scale.transform(df[['Alcohol', 'Malic acid']])

minmax_scale = preprocessing.MinMaxScaler().fit(df[['Alcohol', 'Malic acid']])
df_minmax = minmax_scale.transform(df[['Alcohol', 'Malic acid']])

print('Mean after standardization:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_std[:,0].mean(), df_std[:,1].mean()))
print('\nStandard deviation after standardization:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_std[:,0].std(), df_std[:,1].std()))

Mean after standardization:
Alcohol=0.00, Malic acid=0.00

Standard deviation after standardization:
Alcohol=1.00, Malic acid=1.00

print('Min-value after min-max scaling:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_minmax[:,0].min(), df_minmax[:,1].min()))
print('\nMax-value after min-max scaling:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_minmax[:,0].max(), df_minmax[:,1].max()))

Min-value after min-max scaling:
Alcohol=0.00, Malic acid=0.00

Max-value after min-max scaling:
Alcohol=1.00, Malic acid=1.00

画图

%matplotlib inline

from matplotlib import pyplot as plt

def plot():
    plt.figure(figsize=(8,6))

    plt.scatter(df['Alcohol'], df['Malic acid'],
            color='green', label='input scale', alpha=0.5)

    plt.scatter(df_std[:,0], df_std[:,1], color='red',
            label='Standardized ', alpha=0.3)

    plt.scatter(df_minmax[:,0], df_minmax[:,1],
            color='blue', label='min-max scaled [min=0, max=1]', alpha=0.3)

    plt.title('Alcohol and Malic Acid content of the wine dataset')
    plt.xlabel('Alcohol')
    plt.ylabel('Malic Acid')
    plt.legend(loc='upper left')
    plt.grid()

    plt.tight_layout()

plot()
plt.show()
 

上面的图包括所有三个不同比例的葡萄酒数据点:原始酒精含量数据(绿色),标准化之后的数据(红色)和归一化之后的数据(蓝色)。在下面的图中,我们将放大三个不同的坐标轴。

fig, ax = plt.subplots(3, figsize=(6,14))

for a,d,l in zip(range(len(ax)),
               (df[['Alcohol', 'Malic acid']].values, df_std, df_minmax),
               ('Input scale',
                'Standardized',
                'min-max scaled [min=0, max=1]')
                ):
    for i,c in zip(range(1,4), ('red', 'blue', 'green')):
        ax[a].scatter(d[df['Class label'].values == i, 0],
                  d[df['Class label'].values == i, 1],
                  alpha=0.5,
                  color=c,
                  label='Class %s' %i
                  )
    ax[a].set_title(l)
    ax[a].set_xlabel('Alcohol')
    ax[a].set_ylabel('Malic Acid')
    ax[a].legend(loc='upper left')
    ax[a].grid()

plt.tight_layout()

plt.show()

\
\

自己动手,丰衣足食

当然,我们也可以手动编写标准化方程和最小-最大缩放。但是,实际正真项目中,还是比较推荐使用 scikit-learn 。比如:

std_scale = preprocessing.StandardScaler().fit(X_train)
X_train = std_scale.transform(X_train)
X_test = std_scale.transform(X_test)

接下来,我们采用纯 Python 代码来实现这几个指标,并且也会用 numpy 来进行计算加速。回想一下我们用的几个参数指标:

\

纯 python

# Standardization

x = [1,4,5,6,6,2,3]
mean = sum(x)/len(x)
std_dev = (1/len(x) * sum([ (x_i - mean)**2 for x_i in x]))**0.5

z_scores = [(x_i - mean)/std_dev for x_i in x]

# Min-Max scaling

minmax = [(x_i - min(x)) / (max(x) - min(x)) for x_i in x]

Numpy

import numpy as np

# Standardization

x_np = np.asarray(x)
z_scores_np = (x_np - x_np.mean()) / x_np.std()

# Min-Max scaling

np_minmax = (x_np - x_np.min()) / (x_np.max() - x_np.min())

可视化

为了检验我们的代码是否正常工作,我们通过可视化来进行查看。

from matplotlib import pyplot as plt

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(10,5))

y_pos = [0 for i in range(len(x))]

ax1.scatter(z_scores, y_pos, color='g')
ax1.set_title('Python standardization', color='g')

ax2.scatter(minmax, y_pos, color='g')
ax2.set_title('Python Min-Max scaling', color='g')

ax3.scatter(z_scores_np, y_pos, color='b')
ax3.set_title('Python NumPy standardization', color='b')

ax4.scatter(np_minmax, y_pos, color='b')
ax4.set_title('Python NumPy Min-Max scaling', color='b')

plt.tight_layout()

for ax in (ax1, ax2, ax3, ax4):
    ax.get_yaxis().set_visible(False)
    ax.grid()

plt.show()
 

实战:PCA 中是否进行数据标准化对分类任务的影响

在文章的前面,我们提到了在 PCA 中对数据进行标准化是至关重要的,因为它是分析不同特征之间的差异。现在,让我们看看标准化是如何影响 PCA 对整个葡萄酒数据分类结果产生的影响。

接下来,我们主要通过这些步骤进行描述:

读取数据集;
将原始数据集拆分为训练集和测试集;
特征数据标准化;
PCA 降维;
训练朴素贝叶斯分类器;
利用标准化数据和不利用标准化数据分别对分类器进行评估;

读取数据集

import pandas as pd

df = pd.io.parsers.read_csv(
    'https://raw.githubusercontent.com/rasbt/pattern_classification/master/data/wine_data.csv',
    header=None,
    )

将原始数据集拆分为训练集和测试集

在这一步中,我们将数据随机的分为一个训练集和一个测试集,其中训练集包含整个数据集的 70%,测试集包含整个数据集的 30%。

from sklearn.cross_validation import train_test_split

X_wine = df.values[:,1:]
y_wine = df.values[:,0]

X_train, X_test, y_train, y_test = train_test_split(X_wine, y_wine,
    test_size=0.30, random_state=12345)

特征数据标准化

from sklearn import preprocessing

std_scale = preprocessing.StandardScaler().fit(X_train)
X_train_std = std_scale.transform(X_train)
X_test_std = std_scale.transform(X_test)

PCA 降维

现在,我们对标准化的数据和非标准化的数据分别进行 PCA 操作,将数据集转化为二维特征子空间。在一个真实的应用程序中,我们还会有一个交叉验证的过程,以便找出一些过度拟合的信息。但是,在这里我们就不做这个过程了,因为我们不是要设计一个完美的分类器,我们在这里只是想要去比较标准化对分类结果的影响。

from sklearn.decomposition import PCA

# on non-standardized data
pca = PCA(n_components=2).fit(X_train)
X_train = pca.transform(X_train)
X_test = pca.transform(X_test)


# om standardized data
pca_std = PCA(n_components=2).fit(X_train_std)
X_train_std = pca_std.transform(X_train_std)
X_test_std = pca_std.transform(X_test_std)

让我们快速的查看一下我们的新特征。如下图:

from matplotlib import pyplot as plt

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10,4))


for l,c,m in zip(range(1,4), ('blue', 'red', 'green'), ('^', 's', 'o')):
    ax1.scatter(X_train[y_train==l, 0], X_train[y_train==l, 1],
        color=c,
        label='class %s' %l,
        alpha=0.5,
        marker=m
        )

for l,c,m in zip(range(1,4), ('blue', 'red', 'green'), ('^', 's', 'o')):
    ax2.scatter(X_train_std[y_train==l, 0], X_train_std[y_train==l, 1],
        color=c,
        label='class %s' %l,
        alpha=0.5,
        marker=m
        )

ax1.set_title('Transformed NON-standardized training dataset after PCA')    
ax2.set_title('Transformed standardized training dataset after PCA')    

for ax in (ax1, ax2):

    ax.set_xlabel('1st principal component')
    ax.set_ylabel('2nd principal component')
    ax.legend(loc='upper right')
    ax.grid()
plt.tight_layout()

plt.show()  

 
 

训练朴素贝叶斯分类器

接下来,我们使用一个朴素贝叶斯分类器来进行分类任务。也就是说,我们假设每一个特征都是独立分布的。总而言之,这是一个简单的分类器,但是具有很好的鲁棒性。

贝叶斯规则:

其中:

ω:表示分类标签;
P(ω | x):表示后验概率;
P(x | ω):表示先验概率;

判别规则如下:

 

我不想在本文介绍很多的贝叶斯内容,如果你对这方面感兴趣,可以自己上网看看材料,网上有很多这方面的资料。

from sklearn.naive_bayes import GaussianNB

# on non-standardized data
gnb = GaussianNB()
fit = gnb.fit(X_train, y_train)

# on standardized data
gnb_std = GaussianNB()
fit_std = gnb_std.fit(X_train_std, y_train)

利用标准化数据和不利用标准化数据分别对分类器进行评估

from sklearn import metrics

pred_train = gnb.predict(X_train)

print('\nPrediction accuracy for the training dataset')
print('{:.2%}'.format(metrics.accuracy_score(y_train, pred_train)))

pred_test = gnb.predict(X_test)

print('\nPrediction accuracy for the test dataset')
print('{:.2%}\n'.format(metrics.accuracy_score(y_test, pred_test)))

Prediction accuracy for the training dataset
81.45%

Prediction accuracy for the test dataset
64.81%

pred_train_std = gnb_std.predict(X_train_std)

print('\nPrediction accuracy for the training dataset')
print('{:.2%}'.format(metrics.accuracy_score(y_train, pred_train_std)))

pred_test_std = gnb_std.predict(X_test_std)

print('\nPrediction accuracy for the test dataset')
print('{:.2%}\n'.format(metrics.accuracy_score(y_test, pred_test_std)))

Prediction accuracy for the training dataset
96.77%

Prediction accuracy for the test dataset
98.15%

正如我们所看到的,在 PCA 之前进行标准化,确实对模型的正确率增加了不少。



作者:chen_h,目前在某独角兽公司担任 AI 部门负责人,平时利用 TensorFlow 处理一些图像和文本的交叉问题。微信公众号:coderpai ,专注于人工智能在量化交易中的应用,从程序员角度理解金融问题。
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


上一篇:机器学习模型初印象:什么是过拟合和欠拟合
下一篇:ArXiv最受欢迎开源深度学习框架榜单:TensorFlow第一,PyTorch第四
精选推荐
2023年服务机器人市场将超过250亿美元
2023年服务机器人市场将超过250亿美元

[2017-09-04]  全球服务机器人市场预计到2023年将达到250亿美元, 并在预测期内登记15% 的复合年增长率。短期中期回收期和投资回报率高 (ROI), 以及在教育和研究、临场感、防御、救援和安......

如何让人工智能机器人快速自我纠正错误并吃一堑长一智?
如何让人工智能机器人快速自我纠正错误并吃一堑长一智?

[2017-08-23]  莱斯特大学数学系的研究人员在《Neural Networks》杂志上发表了一篇文章,概述了新算法的数学基础,可以使人工智能收集错误报告并立即纠正,而不影响现有技能 ,同时还会积......

人工智能民主化能否实现取决于科技巨头
人工智能民主化能否实现取决于科技巨头

[2017-12-29]  我们经常听到像谷歌和微软这样的公司说他们希望人工智能民主化。这是一个很好的词,民主化。 但这些公司如何界定“民主化”还不清楚,像AI本身一样,它似乎有点炒作的味道...

机器人从工业走向家庭  库卡KUKA目标是引领中国市场
机器人从工业走向家庭 库卡KUKA目标是引领中国市场

[2017-12-08]  机器人正在改变着人们的生活方式,而库卡KUKA想要在中国这个大蛋糕中占有一块大份额,库卡公司正在引领市场...

全自动膝关节置换手术机器人被美国FDA批准上市
全自动膝关节置换手术机器人被美国FDA批准上市

[2019-10-14]  美国Think Surgical公司已获得美国食品和药物管理局(FDA)的批准,在美国销售用于全膝关节置换(TKA)的TSolution One®全膝关节应用 ...

揭秘达芬奇手术机器人
揭秘达芬奇手术机器人

[2018-04-19]  达芬奇手术系统是由美国Intuitive Surgical公司制造的机器人手术系统。美国食品和药物管理局(FDA)于2000年通过该标准,旨在利用微创手段 ...

美国普渡大学研发快动作软体机器人,灵感来自变色龙舌头捕食
美国普渡大学研发快动作软体机器人,灵感来自变色龙舌头捕食

[2019-10-31]  本文图片均来自:Ramses v Martinez 普渡大学变色龙、蝾螈和许多蟾蜍利用积蓄的弹性能量,向距离1 5倍体长的毫无防备的昆虫伸出粘糊糊的舌 ...

比利时研发出可以自我愈合伤口的软体机器人
比利时研发出可以自我愈合伤口的软体机器人

[2017-09-03]  软体机器人是机器人技术的新兴领域; 他们“可以与人类相互作用,而不会杀死他们,并拿起像西红柿这样柔软的物体。” 从长远来看,布鲁塞尔大学队伍正在努力创建一个类似的材......

本周栏目热点

关于应用机器学习作为搜索问题的入门简介

[2018-01-03]  机器学习的应用可以理解为一个搜索问题,即根据某个项目的已知信息和可获取的资源,找到从输入到输出的最好的映射。在本文你即将看到把应用机器学习当作搜索问题的概念...

[2017-03-02]   随着人工智能的不断发展,许多新的机器学习技术、架构和算法被提出,但这里有三个宏观趋势,将成为机器学习中,游戏规则的改变者。 机 ...

顶级AI会议NIPS压轴2017(附PPT、视频、代码大汇总)

[2017-12-19]  NIPS,全称神经信息处理系统大会(Conference and Workshop on Neural Information Processing Systems),是一个关于机器学习和计算神经科学的国际会议。该会议固定在每年的12月举行...

机器学习之——正则化

[2018-05-18]  最近在刷李航的《统计学习方法》这本书,在很多算法的损失函数里,都出现类似的描述:损失函数最小化原则一般就是用正则化的极大似然估计进 ...

机器学习算法可预测出乳腺癌治疗率(图)

[1970-01-01]    据外媒报道,患有同种疾病的不同病人在接受同一种治疗方案时,其获得的疗效也会存在不同,这就给医生留下了一个难题:他们怎样才能知道 ...