作者:Shay Gellerd
编译:ronghuaiyang
导读
不要再用sklearn中的StandarScaler作为默认的特征缩放方法了,别的方法可以给你7%的准确率提升!
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SOiZDO4YzMiJGN2UzYkJGN3EGM0YTZwMjNidTYiR2N08CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
每个搞机器学习的人都知道特征尺度是一个重要的问题。参考之前的文章。
讨论最多的两种缩放方法是归一化和标准化。归一化通常意味着将值重新划分为[0,1]的范围。标准化通常意味着缩放数据的均值为0,标准差为1(单位方差)。
在这个博客中,我做了一些实验,希望能够回答以下问题:
- 我们应该在所有情况下都做缩放吗?
- 有没有一种最好的缩放技术?
- 不同的缩放技术如何影响不同的分类器?
- 我们是否应该将缩放技术作为模型的一个重要超参数?
我将分析在多个实验设置中对特征应用不同缩放方法的实证结果。
0. 为什么么要讨论两者的区别?
首先,我试图理解归一化和标准化之间的区别。
因此,我遇到了Sebastian Raschka写的这个优秀的blog:https://sebastianraschka.com/Articles/2014aboutfeature_scaling.html,它提供了一个数学背景,满足了我的好奇心。如果您不熟悉归一化或标准化概念,请花5分钟阅读这个博客。
在处理由著名的Hinton使用梯度下降方法(如神经网络)训练的分类器时,也需要很好的对特征缩放进行解释。
我们学了一些数学,就这样?不完全是。
当我检查流行的机器学习库Sklearn时,我发现有许多不同的缩放方法。可以很好地可视化不同的标量对具有异常值的数据的影响。但是他们没有展示它如何影响不同分类器的分类任务。
我看到很多机器学习工作流教程使用StandardScaler (通常称为Z-score标准化)或MinMaxScaler (通常称为最小-最大归一化)来缩放特征。为什么没有人使用其他缩放技术进行分类?有没有可能StandardScaler或MinMaxScaler就是最好的缩放方法了?
我在教程中没有看到任何关于为什么或者什么时候使用它们的解释,所以我想我应该通过运行一些实验来研究这些技术的性能。这就是这篇文章的全部内容。
项目细节
像许多数据科学项目一样,让我们读取一些数据并使用一些开箱即用的分类器进行试验。
数据集
Sonar数据集。它包含208行和60个特征列。这是一个分类任务,以区分声纳信号是通过金属圆筒还是粗略圆柱形岩石反弹的。
这是一个均衡的数据集:
sonar[60].value_counts # 60 is the label column nameM 111R 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个随机分割用于使用最佳参数获得模型的分数。同样在这一部分,所有的数据都是从训练集上获取的。一图胜千言:
读取结果文件
import osimport pandas as pdresults_file = "sonar_results.csv"results_df = pd.read_csv(os.path.join("..