本文不是介绍如何使用matlab对数据集进行归一化,而是通过matlab来介绍一下数据归一化的概念。
以下内容是自己的血泪史,因为归一化的错误,自己的实验过程至少走了两个星期的弯路。由此可见机器学习中一些基础知识和概念还是应该扎实掌握。
背景介绍:
- 归一化后加快了梯度下降求最优解的速度,归一化有可能提高精度。
- 训练集和测试集归一化方法相同。
- 数据集不小,81*132337,81行表示包含81维属性,132337列表示包含132337条训练数据。
- 数据中包含NaN数据。
- 使用matlab中的mapminmax函数,归一化到默认的范围[-1 +1]。
为了方便演示,我们以一个简单的矩阵来说明归一化。
⎡⎣⎢123234345456⎤⎦⎥(1)
这是3*4的矩阵,表示有4条训练数据,每条数据有3个属性。数据归一化应该针对属性,而不是针对每条数据,针对每条数据是完全没有意义的,因为只是等比例缩放,对之后的分类没有任何作用。这是我遇到的 第一个坑。
针对属性进行归一化的代码
inst = [1 2 3 4; 2 3 4 5; 3 4 5 6];
inst_norm = mapminmax(inst);
得到的归一化矩阵如下
⎡⎣⎢−1.0000−1.0000−1.0000−0.3333−0.3333−0.33330.33330.33330.33331.00001.00001.0000⎤⎦⎥(2)
针对数据进行归一化的代码
inst = [1 2 3 4; 2 3 4 5; 3 4 5 6];
inst_norm = mapminmax(inst')';
得到的归一化矩阵如下
⎡⎣⎢−101−101−101−101⎤⎦⎥(3)
我们应该采用 第一种归一化方法,即对属性进行归一化。
训练集和测试集归一化的方法应该相同,但是在具体实验过程中,脑子发生了短路,对训练集的归一化是针对属性的,但是测试集却针对了数据,这是我遇到的 第二个坑。这种做法让测试结果接近随机,跟训练集没什么关系。
网上有一些说法,觉得训练集和测试集应该放到一起进行归一化,我觉得这种做法有所不妥,这样会让测试集受到训练集的影响,导致训练集和测试集不相互独立。
正确的做法是记录下训练集的归一化方法,用该方法对测试集单独进行归一化,matlab中的 mapminmax函数提供了相应的机制。
对于一条新的数据,应该先按照训练集的归一化方法进行归一化,再进行分类,比如对于如下一条新数据,
⎡⎣⎢135⎤⎦⎥(4)
通过如下代码
inst = [1 2 3 4; 2 3 4 5; 3 4 5 6];
[inst_norm, settings] = mapminmax(inst);
test = [1 3 5]';
test_norm = mapminmax('apply', test, settings);
其中settings记录了训练集的归一化方法,得到以下归一化结果,可以参考矩阵(2)
⎡⎣⎢−1.0000−0.33330.3333⎤⎦⎥(5)
mapminmax会跳过NaN数据,最好的方法是归一化之后,将NaN赋值成0。
inst_norm(find(isnan(inst_norm))) = 0;