文档章节

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

o
 osc_g8254g7s
发布于 2019/08/19 16:35
字数 3237
阅读 7
收藏 0

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

 


关于标准化(standardization)

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

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

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

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

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

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

  • 对于基于欧几里得距离的 KNN 算法,如果你想要所有的数据对算法都有贡献,那么必须进行标准化;
  • k-means 算法;
  • 逻辑回归,支持向量机,感知器,神经网络等,如果你正是在使用梯度下降(上升)来作为优化器,那么采用标准化会让权重更快的收敛;
  • 线性判别分析,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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
Class label Alcohol Malic acid
0 1 14.23
1 1 13.20
2 1 13.16
3 1 14.37
4 1 13.24

正如我们在上面的表格中所看到的,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()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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()))
  • 1
  • 2
  • 3
  • 4

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

自己动手,丰衣足食

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

std_scale = preprocessing.StandardScaler().fit(X_train)
X_train = std_scale.transform(X_train)
X_test = std_scale.transform(X_test)
  • 1
  • 2
  • 3

接下来,我们采用纯 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]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
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())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
可视化

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

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

实战: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, )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

在这一步中,我们将数据随机的分为一个训练集和一个测试集,其中训练集包含整个数据集的 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

特征数据标准化

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)
  • 1
  • 2
  • 3
  • 4
  • 5

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

训练朴素贝叶斯分类器

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

贝叶斯规则:

其中:

  • ω:表示分类标签;
  • 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Prediction accuracy for the training dataset
96.77%

Prediction accuracy for the test dataset
98.15%

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

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
基于LSTM模型的广告库存预估算法

最初的传统时序预测,可以追溯到移动平均法、指数平滑法,这类方法基于某段时间的历史数据拟合曲线,对于周期性的波动或方差较大的数据模拟效果较差;之后,随着移动平均与自回归的ARMA,ARI...

iqiyi-kaiyuan
2019/12/20
2
0
机器学习&深度学习基础(目录)

从业这么久了,做了很多项目,一直对机器学习的基础课程鄙视已久,现在回头看来,系统的基础知识整理对我现在思路的整理很有利,写完这个基础篇,开始把AI+cv的也总结完,然后把这么多年做的...

osc_adpilc97
2018/07/09
3
0
特征工程2:归一化与标准化

归一化与标准化属于特征预处理的范畴 · 特征预处理是什么? 通过特定的数学统计方法将数据转化为算法要求的数据; 特征预处理在scikit-learn中的模块是:sklearn.preprocessing 对于不同的数...

osc_xcg0s5cw
2019/06/18
3
0
基于LSTM模型的广告库存预估算法

最初的传统时序预测,可以追溯到移动平均法、指数平滑法,这类方法基于某段时间的历史数据拟合曲线,对于周期性的波动或方差较大的数据模拟效果较差;之后,随着移动平均与自回归的ARMA,ARI...

iqiyi-kaiyuan
2019/12/20
0
0
​特征工程系列:特征预处理(上)

特征工程系列:特征预处理(上) 关于作者:JunLiang,一个热爱挖掘的数据从业者,勤学好问、动手达人,期待与大家一起交流探讨机器学习相关内容~ 0x00 前言 数据和特征决定了机器学习的上限...

osc_c847shr3
2019/08/13
7
0

没有更多内容

加载失败,请刷新页面

加载更多

高职考技能提升教程012期 阶层求和的综合运用

视频讲解 文字讲解: 高职考VB技能提升教程 阶层求和的综合运用 阶层如何理解?看例子 3!=3*2*1 6!=6*5*4*3*2*1 程序实现阶层 举例实现6! 现在看模拟题 模拟题实现 1.设置combobox控件的t...

刘金玉编程
06/05
7
0
22岁的UI设计师,100天成功逆袭UI常用英语,强大到让你别害怕!!

「写在前面」前一段时间有好几个小伙伴留言,告诉我今年一定要多提升自己争取拿一个好的offer。但是不知不觉2020已经过去了三分之一,当初立下突破sketch、学好英语、考驾照的flag依旧没进展...

静电1983
05/08
11
0
docker 容器内服务自启动

centos6/7 有区别先说6 centos6: 方式一:rc.local + 容器内的启动脚本 1.chkconfig docker on  #docker开机自启动 2.[root@master yum.repos.d]# tail -1 /etc/rc.local    #开机自启...

osc_facwbzof
18分钟前
7
0
moco API合集

moco API 解决moco框架API在post请求json参数情况下query失效的问题 解决moco框架API在cycle方法缺失的问题 给moco API添加limit功能 给moco API添加random功能 解决moco框架API在cycle方法缺...

八音弦
07/09
11
0
什么?春节别人抢红包你却在抢锁

今年春节响应国家号召在家宅着抵抗疫情,拜年也改用微信红包,春节发了很多也抢了很多微信红包,也算支持了公司业务,微信支付融入生活,抢红包已经是非常平常的事情,想到WXG的小伙伴丰厚的...

柠檬橙1024
01/30
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部