[译] 对比归一化和标准化 —— 量化分析

中止使用 Sklearn 提供的 StandardScaler 做为你的特征压缩方法甚至可让你训练好的模型有 7% 的准确率提高。html

[https://365datascience.com/standardization/](https://365datascience.com/standardization/)

每个 ML 的从业者都知道特征的压缩是一个重要的议题(更多前端

两个最热议的方法就是归一化和标准化。归一化一般来讲是将数值压缩到 [0,1] 范围内。标准化指的是从新调整数据,使数据到均值为 0,标准差为 1。android

本篇博客但愿经过一些实验回答如下的问题:ios

  1. 咱们老是须要压缩特征吗?git

  2. 是否有一个最好的压缩方法?github

  3. 不一样的压缩技术是如何影响不一样的分类器?算法

  4. 压缩方法是否也应该被考虑为一个重要的超参?后端

我将分析多个不一样压缩方法做用于不一样特征的实验结果。bash

内容总览

    1. 为什么而来?
    1. 成熟的分类器
    1. 分类器 + 压缩
    1. 分类器 + 压缩 + PCA
    1. 分类器 + 压缩 + PCA + 超参调整
    1. 用更多数据集重复进行实验
  • — 5.1 Rain in Australia 数据集
  • — 5.2 Bank Marketing 数据集
  • — 5.3 Sloan Digital Sky Survey DR14 数据集
  • — 5.4 Income classification 数据集
  • 结论

0. 为什么而来?

首先,我尝试理解归一化与标准化之间的区别。网络

而后,我发现了这篇由 Sebastian Raschka 写的很不错的 博客,这篇文章从数学的角度知足了个人好奇心。若是你不熟悉归一化与标准化的概念,那么请必定花五分钟读一下这篇博客

这里还有篇由 Hinton 大神写的文章解释了为何使用梯度降低来训练的分类器(如神经网络)须要使用特征的压缩。

好的,咱们已经恶补了一波数学的知识,是吧?远远不够。

我发现 Sklearn 提供了不少不一样的压缩方法。咱们能够经过 the effect of different scalers on data with outliers 有一个直观的认识。可是他们没有讲清楚这些方法是如何影响不一样分类器任务的。

咱们阅读了不少 ML 的主线教程,通常都是使用 StandardScaler(一般叫作零均值标准化 )或者 MinMaxScaler(一般叫作 Min-Max 归一化)来压缩特征。为何没人用其余的压缩方法来分类呢?难道 StandardScaler 和 MinMaxScaler 已是最好的压缩方法了?

我在教程中没有发现关于为何或者何时使用这些方法的解释。因此,我以为应该经过实验来研究这些技术的性能。这就是这篇文章所要讲的所有东西。

项目细节

和许多数据科学的工程同样,咱们会读取一些数据,并使用一些成熟的分类器来作实验。

数据集

Sonar 数据集包含了 208 行和 60 列特征。这个分类任务是为了判断声纳的回传信号是来自金属圆柱仍是不规则的圆柱形石头。

这是一个平衡的数据集:

sonar[60].value_counts() # 60 是标签列的名字

M    111
R     97
复制代码

数据集中全部特征都在 0 和 1 之间,可是并非每个特征都能保证 1 是最大值或者 0 是最小值。

我选择这个数据集有两个方面的考量,首先是这个数据集足够的小,我能够快速的完成实验。其次,这个问题比较复杂,没有一个分类器能够将准确率作到 100%,我得到的比对数据就更有意义。

在后面的章节,咱们也会在其余数据集上作实验。

代码

在预处理环节,我已经计算了全部结果(这个花费了很多时间)。因此,咱们只读取结果文件并在其上进行分析。

你能够在个人 GitHub 上获取产生结果的代码: github.com/shaygeller/…

我从 Sklearn 中选取了一些最流行的分类器,以下:

(MLP 是一种多层级的感知器,一个神经网络)

使用的压缩方法以下:

  • 不要将上表的最后一个压缩方法 Normalizer 和咱们以前提到的极大极小归一化混淆了。极大极小归一化对应的是第二行的 MinMaxScalar。Sklearn 中的 Normalizer 是将样本单独归一化为一个单位范数。这是一个基于行而非基于列的归一化方法。

实验细节:

  • 为了复现实验场景,咱们使用相同的随机数种子。

  • 训练集和测试集的比例为 8:2,而且是随机划分。

  • 全部的结果的准确率都是在 10 个取自训练集的随机交叉验证集上获得的。

  • 咱们不讨论测试集上的结果。一般来说,测试集都是不可见的,而且咱们的结论都是只从分类器在交叉验证集上的得分获得的。

  • 在第四部分,我使用嵌套的交叉验证集。一个内部交叉验证集包含 5 个随机的分块,并由超参进行调整。外部是 10 个随机分割的交叉验证集并使用最好的模型参数得到对应得分。这一部分的数据都是源自训练集。图片是最具备说服力的:

[https://sebastianraschka.com/faq/docs/evaluate-a-model.html](https://sebastianraschka.com/faq/docs/evaluate-a-model.html)

咱们来看看结果

import os
import pandas as pd

results_file = "sonar_results.csv"
results_df = pd.read_csv(os.path.join("..","data","processed",results_file)).dropna().round(3)
results_df
复制代码

1. 成熟的分类器

import operator

results_df.loc[operator.and_(results_df["Classifier_Name"].str.startswith("_"), ~results_df["Classifier_Name"].str.endswith("PCA"))].dropna()
复制代码

一个不错的结果,经过观察交叉验证集的均值,咱们能够发现 MLP 是最棒的,而 SVM 效果最差。

标准差的结果都是基本一致的,因此咱们主要是关注均值得分。咱们使用 10 个随机分割的交叉验证集的均值做为结果。

那么,让咱们来看看不一样压缩方法是怎么改变每一个分类器得分的。

2. 分类器 + 压缩

import operator
temp = results_df.loc[~results_df["Classifier_Name"].str.endswith("PCA")].dropna()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])

def df_style(val):
    return 'font-weight: 800'

pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold
复制代码

第一行,没有索引名称的那一行,是咱们没有使用任何压缩方法的原始算法得分。

import operator

cols_max_vals = {}
cols_max_row_names = {}
for col in list(pivot_t):
    row_name = pivot_t[col].idxmax()
    cell_val = pivot_t[col].max()
    cols_max_vals[col] = cell_val
    cols_max_row_names[col] = row_name

sorted_cols_max_vals = sorted(cols_max_vals.items(), key=lambda kv: kv[1], reverse=True)

print("Best classifiers sorted:\n")
counter = 1
for model, score in sorted_cols_max_vals:
    print(str(counter) + ". " + model + " + " +cols_max_row_names[model] + " : " +str(score))
    counter +=1
复制代码

最好的组合以下:

  1. SVM + StandardScaler : 0.849
  2. MLP + PowerTransformer-Yeo-Johnson : 0.839
  3. KNN + MinMaxScaler : 0.813
  4. LR + QuantileTransformer-Uniform : 0.808
  5. NB + PowerTransformer-Yeo-Johnson : 0.752
  6. LDA + PowerTransformer-Yeo-Johnson : 0.747
  7. CART + QuantileTransformer-Uniform : 0.74
  8. RF + Normalizer : 0.723

咱们来分析一下结果

  1. 没有一个压缩方法可让每个分类器都得到最好的结果。

  2. 咱们发现压缩是会带来增益的。SVM、MLP、KNN 和 NB 又分别从不一样的压缩方法上得到了长足的增益。

  3. 值得注意到是一些压缩方法对 NB、RF、LDA 和 CART 是无效的。这个现象是和每一种分类器的工做原理是相关的。树形分类器不受影响的缘由是它们在分割前会先对数值进行排序而且为每个分组计算熵。一些压缩函数保持了这个顺序,因此不会有什么提升。NB 不受影响的缘由是它模型的先验是由每一个类中的计数器决定的而不是实际值。线性判别分析(LDA)是经过类间的变化寻找一个系数,因此它也不受压缩的影响。

  4. 一些压缩方法,如:QuantileTransformer-Uniform,并不会保存特征的实际顺序,所以它依然会改变上述的那些与其余压缩方法无关的分类器的得分。

3. 分类器 + 压缩 + PCA

咱们知道一些众所周知的 ML 方法,好比像 PCA 就能够从压缩中获益(博客)。咱们试着加上一个 PCA(n_components=4)到实验中并分析结果。

import operator
temp = results_df.copy()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])

def df_style(val):
    return 'font-weight: 800'

pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold
复制代码

结果分析

  1. 大多数的状况下,压缩都改进带有 PCA 的模型, **可是,**没有指定特定的压缩方法。咱们来观察一下再大多数模型上都有较好效果的 “QuantileTransformer-Uniform”。它将 LDA-PCA 的准确率从 0.704 提高到了 0.783 提升了 8%!可是对于 RF-PCA 它却起到了负增益,模型的准确率从 0.711 降到了 0.668,降低了 4.35%。另外一个方面,若是使用 “QuantileTransformer-Normal” ,RF-PCA 的准确率又能够提升到 0.766 有 5% 的提升。

  2. 咱们能够发现 PCA 只提升了 LDA 和 RF,因此 PCA 也并非一个完美的解决方案。咱们并无去调整 n_components 这个超参,其实,就算咱们调整了,也不会有保证必定能够有提高。

  3. 同时咱们会发现 StandardScaler 和 MinMaxScaler 只在 16 个实验中的 4 个获得了最好的分数,因此,咱们应该考虑一下如何去选取最合适的默认压缩方法了。

我能够有以下结论,即便 PCA 做为一个众所周知会从压缩中得到增益的单元,也没有一个压缩方法能够保证能够提升全部的实验结果,它们中的一些甚至对 RF-PCA 这种模型使用 StandardScaler 还会产生负面的影响。

在上面的实验中,数据集也是一个重要的因素。为了能更好地理解压缩方法对 PCA 的影响,咱们将在更多数据集上作实验(其中数据集会包含类别不平衡、特征尺度不一样以及同时具备数值型和分类型特征的数据集)。咱们会在第五节进行分析。

4. 分类器 + 压缩 + PCA + 超参调整

对于给定的分类器,不一样的压缩方法会致使准确率有很大的不一样。咱们认为超参在调整完毕后,不一样的压缩方法对模型的影响会变小,这样咱们就能够像不少网上的教程那样使用 StandardScaler 或者 MinMaxScaler 做为分类器的压缩方法。 咱们来验证一下。

首先,NB 没有在此章节中,由于它不存在参数调整。

咱们与较早阶段的结果作对比能够发现几乎全部的算法都会从超参调整中获益。一个有趣的例外是 MLP,它变得更糟糕了。这个极可能是神经网络会很容易在数据集上过拟合(尤为是当参数量远远大于训练样本),同时咱们又没有用提早中止或者正则化的方式来避免过拟合。

然而,即便咱们有一组调整好的超参,运用不一样的压缩方法所得的结果仍是有很大区别的。当咱们在其余方法进行实验时会发现,用这些方法和普遍使用的 StandardScaler 在 KNN 算法上作对比,准确度竟然能够得到 7% 的提高。

这个章节的主要结论是,即便咱们有一组调试好的超参,变换不一样的压缩方法仍然会对模型结果有较大的影响。因此咱们应该将模型使用的压缩方法也看成一个关键的超参。

第五部分咱们会在更多的数据集上进行深刻的分析。若是你不想再深挖这个问题,能够直接去看结论。

5. 用更多数据集重复进行实验

为了获得更好理解同时更为普适的结论,咱们须要在更多的数据集上作更多的实验。

咱们会用到和第三节类似的分类器+压缩+PCA 的形式在几个具备不一样特征的数据集上进行实验,并在不一样的小节中分析结果。全部的数据集都来自于 Kaggel。

  • 为了方便起见,我从各个数据集中选择了只有数值的列。多元化的数据集(数值和分类特征)在如何进行压缩上一直有争议。

  • 我没有调整分类器更多的参数。

5.1 Rain in Australia 数据集

连接 分类任务:预测是否下雨? 度量方法:精度 数据集大小:(56420, 18) 各个类别的数量: 不下雨 43993 下雨 12427

这里咱们展现了 5 行数据的部分列,无法在一张图中展现全部列。

dataset.describe()
复制代码

咱们推测因为特征的尺度不一样,压缩可能会提升分类器的效果(观察上表的最大最小值,剩余数据的尺度差别会比展现的还要大)。

结果

结果分析

  • 咱们会发现 StandardScaler 和 MinMaxScaler 历来没有获得过最高的分数。

  • 咱们能够发如今 CART-PCA 算法上 StandardScaler 和其余的方法甚至有 20% 的区别

  • 咱们也能够发现压缩一般是有效果的。在 SVM 上准确率甚至从 78% 涨到了 99%。

5.2 Bank Marketing 数据集

连接 分类任务:预测客户是否已经订购了按期存款? 度量方法:AUC (数据集不平衡) 数据集大小:(41188, 11) 各种别数量: 没订购 36548 订购 4640

这里咱们展现了 5 行数据的部分列,无法在一张图中展现全部列。

dataset.describe()
复制代码

再次说明,特征的尺度不一样。

结果

结果分析

  • 咱们会发现,在这个数据集上,即便特征是不一样尺度的,压缩也不必定会对全部使用了 PCA 的模型带来增益。尽管如此, 在全部带 PCA 的模型上,第二高的得分和最高得分都十分接近。这个可能意味着调整 PCA 的最终维度同时使用压缩方法是优于全部不进行压缩的结果的。

  • 再次强调,依然没有一个压缩方法表现的很是优秀。

  • 另外一个有趣的结果,全部压缩方法在大多数的模型上都没有带来很是大的提高(基本都在 1% - 3% 之间)。这是由于数据集自己是不平衡的,咱们也没有调整参数。另外一个缘由是 AUC 的得分已经很高(在 90% 左右),这就很难再有大的提高了。

5.3 Sloan Digital Sky Survey DR14 数据集

连接 分类任务:预测目标是星系、恒星仍是类星体? 度量方式:准确度 (多分类) 数据集大小:(10000, 18) 各种别数量: 星系 4998 行星 4152 类星体 850

这里咱们展现了 5 行数据的部分列,无法在一张图中展现全部列。

dataset.describe()
复制代码

再次说明,特征的尺度不一样。

结果

结果分析

  • 压缩对结果带来了很大的提高。这是咱们能够预期的,是由于数据集中的特征尺度是不一样的。

  • 咱们会发现 RobustScaler 基本上在全部使用了 PCA 的模型上都表现的很好。这多是大量的异常点致使 PCA 的特征向量发生了平移。另外一方面,这些异常点在咱们不使用 PCA 时,又没有那么大的影响。这个咱们须要深挖数据集才能肯定。

  • StandardScaler 和其余压缩方法的准度差别能够达到 5%。这也说明咱们要用多种压缩方法进行实验。

  • PCA 老是能够从压缩上得到增益。

5.4 Income classification 数据集

连接 分类任务:收入是 >50K 仍是 <=50K? 度量:AUC (不平衡数据集) 数据集大小:(32561, 7) 各种别数量: <=50K 24720

50K 7841

这里咱们展现了 5 行数据的部分列,无法在一张图中展现全部列。

dataset.describe()
复制代码

这又是个特征的尺度不一样的数据集。

结果

结果分析

  • 再次说明,数据集是不平衡的,可是咱们能够发现压缩是十分有效的可使结果出现高达 20% 的提高。这个极可能是 AUC 的得分相较于 Bank Marketing 数据集而言比较低(80%),因此很容易得到较大的提升。

  • 虽然 StandardScaler 没有被高亮(我只标亮了每列得分最高的一项),可是在不少列它都很接近最好的结果,固然也不老是有这样的结论。在运行时(没有展现),StandardScaler 的速度比大多数的压缩方法都快。若是你比较关注速度,StandardScaler 是个很好的选择。可是若是你关注的是精度,那么你就须要试试其余压缩方法了。

  • 再次强调,依然没有一个压缩方法在全部算法上都表现的很是优秀。

  • PCA 几乎老是能够从压缩上得到增益。

结论

  • 实验代表即便在超参调整好的模型上,压缩也能够在结果上带来增益。因此,压缩方法须要被看成一个重要的超参来考虑。

  • 不一样的压缩方法会对不一样的分类器产生影响。SVM、KNN 和 MLP(神经网络)等基于距离的分类器都会从压缩上得到较大的收益。但即便是树型(CART 和 RF)这种某些压缩技术不起做用的分类器,也能够从其它的压缩方法上获益。

  • 明白模型和预处理方法背后的数学理论是理解这些结果的最好方法。(举个例子,树型分类器是怎么工做的?为何一些压缩方法对它们无效?)。这会节约你不少的时间,若是你知道在使用随机森林时不能使用 StandardScaler。

  • 像 PCA 这样的预处理方法确实是会从压缩上得到增益。若是没有效果,多是由于 PCA 的维度设置的很差,异常点较多或者错误的选择压缩方法。

若是你发现任何的错误、实验覆盖率的改进方法或者改进意见均可以联系我。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索