老饼讲解-神经网络 机器学习 神经网络 深度学习
BP神经网络建模
1.BP神经网络-工具箱说明
2.BP神经网络-建模代码
3.BP神经网络-训练技巧
4.BP神经网络-应用案例
5.BP神经网络-问题答疑

【神经网络】BP为什么需要数据归一化?

作者 : 老饼 发表日期 : 2022-06-21 14:00:39 更新日期 : 2023-10-10 16:21:56
本站原创文章,转载请说明来自《老饼讲解-BP神经网络》www.bbbdata.com



BP神经网络一般需要预先将数据进行归一化,再进行训练

本文分析为什么BP神经网络的训练需要归一化




  01. BP训练前为什么需要归一化  





     BP训练前需要归一化的原因    


BP训练前需要归一化的主要原因有
 👉1. 避免出现数值问题        
👉2. 有助于求取更优秀的解
 
为什么这么说呢?
下文进行详细具体的分析





     为什么BP归一化可以避免数值问题     


BP中的数值问题
 
BP在训练前归一化可以避免一些不必要的数值问题
 
也许有人认为一般的数据量级很难出现数值问题,
其实不然,在BP中一般的数量量级就会出现数据问题了
 原因如下:
由于 tansig 的非线性区间大约在[-1.7,1.7]
这意味着要使神经元有效,
 里的数量级
就需要在 1 (1.7所在的数量级)左右
这时输入较大,就意味着权值必须较小
一个较大,一个较小,两者相乘,就引起数值问题了
✍️实验例子
 
 假如你的输入是421,
你也许认为,这并不是一个太大的数,
但因为有效权值大概会在1/421左右,例如0.00243,
那么,在matlab里输入 421*0.00243 == 0.421*2.43

  
  
可以看到两者不相等了,说明已经引起数值问题了




     为什么BP归一化更有利于求解     


为什么归一化是为求解服务
我们建立了神经网络模型后,只要找到的解足够好,我们的网络就能够正确的预测了
而在训练前将数据归一化,说明数据归一化的目的是为了更方便的求解
 
 为什么求解需要归一化
那么,究竟给求解带来了什么方便呢?
这个问题不能一概而论,
不同的算法,在归一化中得到的好处各不相同
假若有一个很牛B的求解算法,那完全用不着归一化
不过目前大部算法,都比较需要归一化
 特别地,
对于常用的梯度下降法(或梯度下降的衍生方法)
归一化和不归一化,对梯度下降法的影响非常大

 
 不同的算法,对归一化的依赖程序不同,
 
例如,列文伯格-马跨特算法(matlab工具箱的trainlm法)
对归一化的依赖就没有梯度下降法(matlab里的traingd)那么强烈
 既然不同的算法对归一化有不同的理由
篇幅有限,本文就仅以梯度下降法举例





   02. 归一化在梯度下降法求解BP时好处   




     梯度下降法简单回顾     


在分析前,先简单重温一下梯度下降法
梯度法一般初始化一个初始解,
然后不断将解往负梯度方向迭代
直到满足终止条件
 流程简述如下
1. 初始化解                                               
2. for 循环:                                            
(1) 新解=旧解-梯度*学习率        
(2) 如果满足终止条件,退出循环
3. 输出最终的解                                       




      归一化对初始化的好处     


先看归一化对初始化的好处
尝试过初始化的同学会发现,
输入数据的范围会影响我们初始化的效果
例如,某个神经元的值为
由于tansig函数只有在[-1.7,1.7]的范围才有较好的非线性
所以的取值范围就要与 [-1.7,1.7]有交集
这个神经元才能利用到非线性部分
我们希望初始化的时候,就把每个神经元初始化成有效的状态
所以,需要知道w1*x1+w2*x2+b的取值范围,也就需要知道输入输出数据的范围。
输入数据的范围对初始化的影响是无法避免的,
一般讨论初始化方法时,我们都假设它的范围就是[0,1]或者[-1,1],这样讨论起来会方便很多。
就这样,如果数据已经归一化的话,能给初始化模块带来更简便,清晰的处理思路。

matlab工具箱在初始化权值阈值的时候,会考虑数据的范围,所以,即使数据没归一化,也不会影响matlab工具箱的初始化



  (2)梯度  


以输入-隐层-输出这样的三层BP为例,
我们知道对于输入-隐层权值的梯度有的形式
(e是誤差,w是隐层到输出层的权重,a是隐层神经元的值,x是输入),
如果输出层的数量级很大,会引起e的数量级很大,
同理,w为了将隐层(数量级为1)映身到输出层,w也会很大,
再加上x也很大的话,从梯度公式可以看出,三者相乘,梯度就非常大了。
这时会给梯度的更新带来数值问题。


(3)学习率  


由(2)可知,梯度非常大,学习率就必须非常小,
因此,学习率(学习率初始值)的选择需要参考输入的范围,
不如直接将数据归一化,这样学习率就不必再根据数据范围作调整
由于隐层到输出层的权值梯度为                  
而输入层到隐层的权值梯度为  
从上面两式式可以看到,
受 x 和 w 的影响,各个梯度的数量级并不相同
因此,它们需要的学习率数量级也就不相同
对w1适合的学习率,可能相对于w2来说会太小,
如果使用适合w1的学习率,
会导致在w2方向上步进非常慢,会消耗非常多的时间,
而使用适合w2的学习率,
对w1来说又太大,搜索不到适合w1的解
如果使用固定学习率,而数据没归一化,则后果可想而知

如果使用自适应学习率,学习率的问题会稍稍得到一些缓和。


(4)搜索轨迹  


前面已说过,输入范围不同,对应的 w 的有效范围就不同。
假设 w1 的范围在 [-10,10],而w2的范围在[-100,100],
梯度每次都前进1单位,那么在w1方向上每次相当于前进了 1/20,而在w2上只相当于 1/200!
某种意义上来说,在w2上前进的步长更小一些,而w1在搜索过程中会比w2“走”得更快。
这样会导致,在搜索过程中更偏向于w1的方向。
抛开哪种路线更有效于找到最佳解的问题不谈,
两点之间直线距离最短,这种直角路线明显会更耗时间,所以不归一化,时间会明显增加。
从上面的分析总结,除了数值问题的影响,最主要的影响就是,每一维的偏导数计算出来数量级会不一致。






  03. 小实验印证上述理论  




     本节说明    


上面的理论分析了一大堆,
那么,怎么证明上面的分析是正确的呢?
下面我们不妨来做个小实验,dirty our hand~
用实验来侧面验证我们的分析是正确的



  问 题  


假设我们有两个输入变量,
x1范围是[-1,1],但x2是[-100,100],输出范围是[-1,1]
x2在输入数据上没有做归一化
怎么修改训练过程,才能让训练结果如同数据归一化了一样呢



     分析与实验     


问题解决方案分析
通过上面的讨论,
我们知道x2增大了,会使w2的梯度也很大,
因此我们在计算w2梯度时,
需要把它的梯度除以100.才能得到它的梯度数量级与w1的一致
然后在更新w步长的时候,
w1的有效取值范围(1/1)是w2的有效取值范围(1/100)的100倍
因此w2走的时候,应该以1/100的步去走
所以w2的学习率也需要除以100

 实验与结果
这样,如果不考虑数值问题,会和数据作了归一化的结果是一样的
这里就不展示实验的代码了,因为需要涉及整个BP代码
有兴趣研究的同学在自己的编写的代码上动下刀

这是一个案例分析,说明不考虑数值问题的话,只是影响了这两个地方。
假设,x2的输入范围是[100,300],那肯定不是除以100就可以了,需要更复杂一些的变换,这里不再深入纠结。


为什么要归一化,对于使用梯度下降法训练的三层BP神经网络总结出的就是这些原因了

对于其他的神经网络模型,会有其它的原因,这里就不再作分析





  04. 拓展讨论 




        网友的看法与笔者的见解        


网友的看法
下面是网友关于为什么BP神经网络需要归一化的一些看法(欢迎补充):
 
👉1. 避免数值问题                                                                               
 👉2. 使网络快速的收敛                                                                        
 👉3. 统一量纲                                                                                      
 样本数据的评价标准不一样,需要对其量纲化,统一评价标准 
 👉4. 预防神经元饱和                                                                            
 bp中常采用sigmoid函数作为激活函数                      
归一化能够防止净输入绝对值过大引起的神经元输出饱和现象 

  👉5. 数值吞食                                                                                       
 保证输出数据中数值小的不被吞食                         
 
 笔者的看法
对于网友的看法,笔者部分赞同,部分不赞同
下面是笔者对各个观点的个人看法
1. 避免数值问题:赞同                                                         
 2. 使网络快速的收敛:赞同                                                   
3. 统一量纲:不认同                                                            
 本人认为这从属于业务层,与网络的训练无关       
4. 避免神经元饱和:部分认同                                              
 与权值阈值相乘后,才是sigmoid的输入值,         
初始化得好的话,并不会饱和输出                
一般初始化时就需要考虑到这因素                
从而不让神经元一开始就饱和                    
当然,如果只是随意的将权重初始化在[-1,1]之间  
那么在这种初始化方案下,归一化是比较重要的    

5. 大数吞小数:不认同                                                        
  如果我们找到适合的权值,是不会吞掉的           
例如x1=10000,x2=1, 而w1=0.0001,w2=1           
那么w1*x1是不会吞掉w2*x1的                    
 
  事实上本文的研究大部分都是借鉴了网友的见解,基于这些观点进一步探讨所得




      对使用matlab工具箱时的建议     


由于归一化对BP神经网络有影响
根据笔者的经验,
使用matlab工具箱需要注意以下两点

 
 👉 1. 输出数据的归一化               
   👉 2. 归一化对模型表达式的影响  

  
   输出数据的归一化  
Matlab2012b之后的版本会自动将输入数据归一化
所以不必再自己去做数据的预处理,直接用原始数据建立网络就可以
但需要注意的是,输出最好做一下归一化处理!
 因为工具箱计算误差的时候,
使用的是原始数据的误差(这应该是matlab的算法BUG),
因此误差数量级可能很大,这样一来梯度就很大了
在学习率还没来得及自适应减小的时候,
梯度就一下子把原来初始化好的权重给吞掉了,
使网络的权重掉到一个离最优解非常远的地方
 
 因此, 在使用matlab神经网络工具箱时
如果使用的是梯度下降法(traingd、traingda)的话,输出一定要做归一化
但如果用的是默认的trainlm(列文伯格-马跨特法),那影响不会太严重      
 因为 trainlm对方向 h 的计算公式是:
 

由于JJ和Jf 的数量级不会差太多,
而且由于有u的调整,最终会得到一个适当的 h

 
  归一化对模型表达式的影响  
 
使用matlab2012b(或以上)工具箱得到的网络权值,
是面向作了归一化后的数据的
所以使用时不能直接对数据进行预测
而需要按如下步骤
1. 先对数据进行归一化                                         
2. 将归一化后的输入数据放到网络中计算网络输出
3. 再将输出反归一化                                            
这样才是真正的预测结果
 如果想把归一化过程揉合到网络的权值的话,
请参考文章:<提取对应原始数据的权重和阈值>





   编后语    


本文在很多细节之处,都没有作深入的讨论,
一来展开这些讨论会让文章非常冗赘,失去主题
二来(也是最主要的原因),对归一化作用的研究,
只能让我们更清晰归一化的好处,减少我们对归一化的疑惑,
并不能促进我们更好的改进网络效果
所以本文都仅从大方面,不十分严谨的提及归一化在训练过程各方面的好处


感谢大家的阅读!







 End 




联系老饼