归一化 vs 标准化 定量的分析

共 8913字,需浏览 18分钟

 ·

2021-04-25 10:27

点击上方小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

导读

不要再用sklearn中的StandarScaler作为默认的特征缩放方法了,别的方法可以给你7%的准确率提升!


每个搞机器学习的人都知道特征尺度是一个重要的问题。参考之前的文章

讨论最多的两种缩放方法是归一化和标准化。归一化通常意味着将值重新划分为[0,1]的范围。标准化通常意味着缩放数据的均值为0,标准差为1(单位方差)。

在这个博客中,我做了一些实验,希望能够回答以下问题:

  1. 我们应该在所有情况下都做缩放吗?

  2. 有没有一种最好的缩放技术?

  3. 不同的缩放技术如何影响不同的分类器?

  4. 我们是否应该将缩放技术作为模型的一个重要超参数?

我将分析在多个实验设置中对特征应用不同缩放方法的实证结果。

0. 为什么么要讨论两者的区别?

首先,我试图理解归一化和标准化之间的区别。

因此,我遇到了Sebastian Raschka写的这个优秀的blog:https://sebastianraschka.com/Articles/2014aboutfeature_scaling.html,它提供了一个数学背景,满足了我的好奇心。如果您不熟悉归一化或标准化概念,请花5分钟阅读这个博客。

在处理由著名的Hinton使用梯度下降方法(如神经网络)训练的分类器时,也需要很好的对特征缩放进行解释。

我们学了一些数学,就这样?不完全是。

当我检查流行的机器学习库Sklearn时,我发现有许多不同的缩放方法。可以很好地可视化不同的标量对具有异常值的数据的影响。但是他们没有展示它如何影响不同分类器的分类任务。

我看到很多机器学习工作流教程使用StandardScaler (通常称为Z-score标准化)或MinMaxScaler (通常称为最小-最大归一化)来缩放特征。为什么没有人使用其他缩放技术进行分类?有没有可能StandardScaler或MinMaxScaler就是最好的缩放方法了?

我在教程中没有看到任何关于为什么或者什么时候使用它们的解释,所以我想我应该通过运行一些实验来研究这些技术的性能。这就是这篇文章的全部内容。

项目细节

像许多数据科学项目一样,让我们读取一些数据并使用一些开箱即用的分类器进行试验。

数据集

Sonar数据集。它包含208行和60个特征列。这是一个分类任务,以区分声纳信号是通过金属圆筒还是粗略圆柱形岩石反弹的。

这是一个均衡的数据集:

  1. sonar[60].value_counts() # 60 is the label column name

  2. M 111

  3. R 97

这个数据集中的所有特征都在0到1之间,但是不能确保每个特征中1是最大值或0是最小值。

我选择这个数据集是因为,一方面,它很小,所以我可以很快地进行实验。另一方面,这是一个困难的问题,没有一个分类器可以达到接近100%的准确率,所以我们可以比较有意义的结果。

在最后一节中,我们将试验更多的数据集。

代码

在预处理阶段,我已经计算了所有的结果(这需要一些时间)。所以我们只加载结果文件并处理它。

产生结果的代码可以在我的GitHub中找到:

https://github.com/shaygeller/NormalizationvsStandardization.git

我从Sklearn中选取了一些最流行的分类模型,记为:

(MLP是多层感知器,神经网络)

我使用的缩放方法记为:

不要将上面列表中的最后一个Normalizer与我之前讨论过的min-max normalization技术混淆。min-max归一化是列表中的第二个,名为MinMaxScaler。Sklearn中的Normalizer类将样本单独归一化为单位长度。它不是基于列的,而是基于行的归一化技术。

实验细节:

  • 当需要重现性时使用相同的种子。

  • 随机将数据分成训练测试集,分别为80%-20%。

  • 所有结果都是训练集的10-fold随机交叉验证的准确性得分。

  • 我不在这里讨论测试集的结果。通常,测试集应该是隐藏的,我们关于分类器的所有结论应该只从交叉验证分数中得出。

  • 在第4部分中,我执行了嵌套交叉验证。一个内部交叉验证包含5个随机分割用于超参数调优,另一个外部CV包含10个随机分割用于使用最佳参数获得模型的分数。同样在这一部分,所有的数据都是从训练集上获取的。一图胜千言:

读取结果文件

  1. import os

  2. import pandas as pd

  3. results_file = "sonar_results.csv"

  4. results_df = pd.read_csv(os.path.join("..","data","processed",results_file)).dropna().round(3)

  5. results_df

1. 开箱即用的分类器

  1. import operator

  2. results_df.loc[operator.and_(results_df["Classifier_Name"].str.startswith("_"), ~results_df["Classifier_Name"].str.endswith("PCA"))].dropna()

不错的结果。通过查看CV_mean列,我们可以看到,目前MLP处于领先地位。SVM的性能最差。

标准差基本相同,所以我们主要可以通过均值来判断。下面的所有结果将是10-fold交叉验证随机分割的平均得分。

现在,让我们看看不同的缩放方法如何改变每个分类器的分数

2. 分类器+缩放

  1. import operator

  2. temp = results_df.loc[~results_df["Classifier_Name"].str.endswith("PCA")].dropna()

  3. temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])

  4. temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])

  5. def df_style(val):

  6. return 'font-weight: 800'

  7. pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)

  8. pivot_t_bold = pivot_t.style.applymap(df_style,

  9. subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])

  10. for col in list(pivot_t):

  11. pivot_t_bold = pivot_t_bold.applymap(df_style,

  12. subset=pd.IndexSlice[pivot_t[col].idxmax(),col])

  13. pivot_t_bold

第一行没有索引名,是没有应用任何缩放方法的算法。

  1. import operator

  2. cols_max_vals = {}

  3. cols_max_row_names = {}

  4. for col in list(pivot_t):

  5. row_name = pivot_t[col].idxmax()

  6. cell_val = pivot_t[col].max()

  7. cols_max_vals[col] = cell_val

  8. cols_max_row_names[col] = row_name


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

  10. print("Best classifiers sorted:\n")

  11. counter = 1

  12. for model, score in sorted_cols_max_vals:

  13. print(str(counter) + ". " + model + " + " +cols_max_row_names[model] + " : " +str(score))

  14. 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. 我们可以看到缩放改进了结果。支持向量机、MLP、KNN和NB在不同尺度下均有显著提高。

  3. 注意NB, RF, LDA, CART不受某些缩放方法的影响。当然,这与每个分类器的工作方式有关。树不受尺度的影响,因为分裂准则首先对每个特征的值进行排序,然后计算分裂的基尼熵。某些缩放方法保持这个排序,所以精度分数没有变化。NB不受影响,因为模型的先验由每个类中的计数决定,而不是由实际值决定。线性判别分析(LDA)使用类之间的变化来得到它的系数,因此缩放也不重要。

  4. 有些缩放方法,比如QuantileTransformer-Uniform,并不能保持每个特征中值的精确顺序,因此即使在上面的分类器中,得分的变化也与其他缩放方法无关。

3. 分类器+缩放+PCA

我们知道一些著名的机器学习方法,比如PCA,可以从缩放中获益。我们尝试向工作流中添加PCA(n_components=4)并分析结果。

  1. import operator

  2. temp = results_df.copy()

  3. temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])

  4. temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])


  5. def df_style(val):

  6. return 'font-weight: 800'


  7. pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)

  8. pivot_t_bold = pivot_t.style.applymap(df_style,

  9. subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])

  10. for col in list(pivot_t):

  11. pivot_t_bold = pivot_t_bold.applymap(df_style,

  12. subset=pd.IndexSlice[pivot_t[col].idxmax(),col])

  13. pivot_t_bold

分析一下结果

  1. 大多数的缩放方法使用PCA对模型都有改进,但是并不针对具体的缩放方法。

    让我们来看看“QuantileTransformer-Uniform”,这是得分最高的方法。

    在LDA-PCA中,它将结果从0.704提高到0.783(准确率提高了8% !),但是在RF-PCA中,它使情况变得更糟,从0.711降到0.668(准确率下降了4.35% !)

    另一方面,使用RF-PCA与“QuantileTransformer-Normal”,提高精度到0.766(5%的精度提升!)

  2. 我们可以看到PCA只改善了LDA和RF,所以PCA并不是一个神奇的解决方案。

    这样很好。我们没有调试n_components参数,即使我们调参了,PCA也不能保证改进预测。

  3. 我们可以看到StandardScaler和MinMaxScaler在16个案例中只有4个获得了最好的分数。所以我们应该仔细考虑选择什么样的缩放方法,即使是默认的。

我们可以得出结论,虽然PCA是一个已知的组件,可以从缩放中获益,但是没有一种缩放方法总是能够改善我们的结果,其中一些方法甚至会造成伤害(带standard - scaler的RF-PCA).

数据集也是一个重要因素。为了更好地理解缩放方法对PCA的影响,我们应该对更多不同的数据集进行实验(类不平衡、不同尺度的特征以及具有数值和分类特征的数据集)。我在第5部分做这个分析

4. 分类器+缩放+PCA+超参数调参

对于给定的分类器,不同缩放方法的精度评分存在较大差异。我们可以假设,当超参数调优之后,缩放技术之间的差别会变小,我们可以使用StandardScaler或MinMaxScaler,就像网上上许多教程中使用的那样。

让我们看看是不是这样!

首先,NB不在这里,因为NB没有参数可调。

我们可以看到,几乎所有的算法都从超参数调优中获益,与前面步骤的结果相比。一个有趣的例外是MLP,它的结果变差了。这可能是因为神经网络很容易对数据进行过拟合(尤其是当参数的数量远远大于训练样本的数量时),我们没有很小心的进行提前停止以避免它,也没有应用任何正则化。

然而,即使对超参数进行了调优,使用不同缩放方法得到的结果仍然存在很大差异。如果我们将不同的缩放技术与广泛使用的标准缩放技术进行比较,在使用其他技术时,我们可以获得高达7%的精确度提升 (KNN列)。

这一步的主要结论是,即使超参数被调优,改变缩放方法也会显著影响结果。因此,我们应该将缩放方法作为模型的一个重要超参数。

第5部分包含对更多不同数据集的更深入分析。如果你不想深入研究,可以直接跳到结论部分。

5. 在更多的数据集上再做一遍

为了更好地理解和得出更一般化的结论,我们应该使用更多的数据集进行实验。

我们将像第3节一样,对几个具有不同特征的数据集应用分类器+缩放+PCA,并分析结果。所有数据集均取自Kaggel。

  • 为了方便起见,我只从每个数据集中选择了数值列。在多元数据集(数值和分类特性)中,关于如何缩放特征一直存在争论。

  • 我没有超调任何分类器的参数。

5.1 澳大利亚降雨数据集

链接:https://www.kaggle.com/jsphyg/weather-dataset-rattle-package#weatherAUS.csv 

分类任务: 预测会不会下雨?

度量: 准确率 

数据集大小: (56420, 18) 

每个类别包含: No 43993 Yes 12427

  1. dataset.describe()

我们会怀疑,由于特征的尺度不同,缩放会改善分类结果(查看上表中的最小最大值,其他一些特征甚至会变得更糟)。

结果

结果分析

  • 我们可以看到StandardScaler从来没有得到最高的分数,也没有得到最低的分数。

  • 我们可以看到StandardScaler和其他方法之间的差异高达20%。(CART-PCA列)

  • 我们可以看到缩放通常会改善结果。以支持向量机为例,支持向量机从78%跳到了99%

5.2 银行市场数据集

链接:https://www.kaggle.com/henriqueyamahata/bank-marketing 

分类任务: 预测客户会不会存款? 

度量: AUC (数据集是不均衡的) 

数据集大小: (41188, 11) 

每个类别的数量: no 36548 yes 4640

  1. dataset.describe()

结果

结果分析

  • 我们可以看到,在这个数据集中,即使特征具有不同的尺度,缩放时使用PCA并不总是改善结果。然而,在每个PCA列中第二好的分数与最好的分数非常接近。这可能表明,对PCA的成分的数量进行超调和使用缩放将比完全不缩放得到更好的结果。

  • 同样,没有一个单一的缩放方法脱颖而出。

  • 另一个有趣的结果是,在大多数模型中,所有的缩放方法都没有产生太大的影响(通常是1%-3%的改进)。让我们记住这是一个不平衡的数据集,我们没有调超参数。另一个原因是AUC的分数已经很高(约90%),所以很难看到明显的改善。

5.3 天体监测数据集

链接:https://www.kaggle.com/lucidlenn/sloan-digital-sky-survey 

分类任务: 预测一个天体是星系,恒星还是类星体 

度量: 准确率(多类) 

数据集大小: (10000, 18) 

每个类别的数量: GALAXY 4998 STAR 4152 QSO 850

  1. dataset.describe()

结果

结果分析

  • 我们可以看到缩放大大改善了结果。我们可以期待它,因为它包含不同尺度的特征。

  • 我们可以看到,当我们使用PCA的时候,RobustScaler几乎总是赢家。这可能是由于这个数据集中有许多异常值导致了PCA特征向量有所变化。另一方面,当我们不使用PCA时,这些异常值不会产生这样的影响。我们应该做一些数据研究来验证这一点。

  • 如果我们将StandardScaler与其他缩放方法进行比较,其准确度会有高达5%的差异。所以这是另一个需要用多种缩放技术进行实验的指标。

  • 主成分分析几乎总是受益于缩放。

5.4 收入分类数据集

链接:https://www.kaggle.com/lodetomasi1995/income-classification 

分类任务: 预测收入大于50k还是小于50k 

度量: AUC (不平衡数据集) 

数据集大小: (32561, 7) 

每个类别的数量: <=50K 24720 >50K 7841

  1. dataset.describe()

结果

结果分析

  • 这里,我们有一个不平衡的数据集,但我们可以看到,缩放在改善结果方面做得很好(高达20%!)这可能是因为与银行营销数据集相比,AUC评分较低(约80%),因此更容易看到重大改进。

  • 尽管StandardScaler没有突出显示(我只突出显示了每个列中的第一个最佳得分),但在许多列中,它可以获得与最佳相同的结果,但并不总是如此。从运行时间上看(这里没有出现),我可以告诉你,运行StandatdScaler要比许多其他缩放方法快得多。所以,如果你急于得到一些结果,这可能是一个很好的起点。但是如果你想从你的模型中挤出每一个百分比,你可能想要体验多种缩放方法。

  • 同样,没有单一的最佳缩放方法。

  • PCA几乎总是受益于缩放

结论

  • 尝试多种缩放方法可以显著提高你在分类任务上的得分,即使你调整了超参数。因此,你应该将缩放方法视为模型的一个重要超参数。

  • 缩放方法对不同分类器的影响不同。基于距离的分类器,如SVM、KNN和MLP(神经网络),极大地受益于缩放。但是,即使树(CART、RF)对某些缩放方法是不可知的,也可以从其他方法中获益。

  • 了解模型预处理方法背后的数学原理是理解结果的最佳方法。(例如,树是如何工作的,以及为什么一些缩放方法没有影响它们)。如果你的模型是随机森林,而你不知道如何应用StandardScaler,那么它还可以为您节省大量时间。

  • 像PCA这样的预处理方法已知可以从缩放中获益,确实也是这样。当没有的时候,可能是由于PCA的分量参数个数设置不当、数据中的异常值或缩放方法选择不当。


下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲
小白学视觉公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲
小白学视觉公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群


欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报