观察不同权重的初始值对激活值的分布,我们可以了解到权重初始值的重要性,从分布情况来看,可以非常直观的看出神经网络的学习是不是进行得顺利。
import numpy as np
import matplotlib.pyplot as plt
#三个简单激活函数
def sigmoid(x):
return 1/(1+np.exp(-x))
def ReLU(x):
return np.maximum(0,x)
def tanh(x):
return np.tanh(x)
inputData=np.random.randn(1000,100)#1000 x 100 矩阵的高斯分布
hiddenNum=100#隐藏层的100个神经元
hiddenLayerNum=5#隐藏层数
activations={}#保存激活值
x=inputData
for i in range(hiddenLayerNum):
if i!=0:
x=activations[i-1]
#权重初始值
#w=np.random.randn(hiddenNum,hiddenNum)*1#标准差为1的高斯分布
#w=np.random.randn(hiddenNum,hiddenNum)*0.01#标准差为0.01
w=np.random.randn(hiddenNum,hiddenNum)*np.sqrt(1.0/hiddenNum)
#w=np.random.randn(hiddenNum,hiddenNum)*np.sqrt(2.0/hiddenNum)
a=np.dot(x,w)
#激活函数
#z=sigmoid(a)
#z=ReLU(a)
z=tanh(a)
activations[i]=z
#画直方图,5个子图
for i,a in activations.items():
#print(a.flatten().shape)#100000条数据
plt.subplot(1,len(activations),i+1)
plt.title(str(i+1)+'Layer')
if i!=0:plt.yticks([],[])#第二个子图开始的y轴标签值不显示
plt.hist(a.flatten(),30)
#plt.hist(a.flatten(),30,range=(0,1))
plt.show()
权重初始值的标准差为1的高斯分布
图中看出输出基本集中在0和1的位置,差不多有8万多的数据都偏向了两边,这样的分布会造成反向传播中梯度的值不断变小,最后消失,这个问题称为梯度消失(gradient vanishing),随着层的加深,梯度消失的问题将更加严重
权重初始值的标准差为0.01的高斯分布
数据基本集中在0.5附近,虽然不会出现梯度消失的问题,但是在表现力方面很差,为什么呢?因为如果多个神经元都输出几乎相同的值,那就多层叠加的意义就没有了,所以我们需要的是一种激活值能够在每一层上面有适当的广度分布,这样就会在各层传递多样性的数据,神经网络就可以进行高效的学习了。
那应该如何选择比较好的初始值呢?其实在全连接的多层神经网络结构(MultiLayerNet)就出现过,通过不同的激活函数来选择不同的初始值。
如果激活函数是sigmoid选择“Xavier初始值”: ;是ReLU就选择“He初始值”:
由于ReLU的负值区域的值为0,为了使它更有广度,所以需要2倍的系数。
sigmoid函数在后面的层的分布呈稍微歪斜的形状,使用tanh函数(双曲线)来代替,显得更加的光滑,呈现的是一个吊钟型分布,其中sigmoid是关于(0,0.5)对称的S型曲线,而tanh是关于原点(0,0)对称的S型曲线,一般最好使用关于原点对称的函数。
关于Python画图的基础知识可以参阅
Python画图(直方图、多张子图、二维图形、三维图形以及图中图)https://blog.csdn.net/weixin_41896770/article/details/119798960