逐步建立深层神经网络:框架总览和初始化参数

逐步建立深层神经网络:框架总览和初始化参数

正式入坑ML中的神经网络已经半月有余。目前,主要是以吴恩达的课程基础进行进修,然却力感进度太缓,理解不够透彻,遂萌生了依据其课程《Deeplearning.AI》为基础,使用python逐步建立完成深层神经网络(deep neural network)。

以下是深层神经网络的构建框架:逐步建立深层神经网络:框架总览和初始化参数

这里因数据处理是很大的一块,我将放在最后进行处理。所以,先进行初始化参数(initialize_parameters)

初始化参数(INITIALIZE_PARAMETERS)

参数初始化的方法有三种:分别是全零填充(zeros)、随机填充(random)和He填充。因为偏置b可以使用全零填充,而权重W使用全零填充,将导致对称性问题,就此,下面将分别简略讲述三种初始化权重W 方法的特征。

全零填充(zeros)

权重W的初始化值,全为零。代码:

np.zeros()

以下图片是使用全零填充,更新一定轮数的神经网络返回的cost值,即loss值。
逐步建立深层神经网络:框架总览和初始化参数
由图可以看出,使用全零填充后,随着轮数的更新,cost值并没有变化,始终保持着一条直线,所以全零初始化W,将产生对称性问题。

随机初始化(random)

权重W的初始值,将采用随机(random)进行赋值。代码:

w = np.random.randn()

以下图片是使用随机初始化(random),更新一定轮数的神经网络返回的cost值

逐步建立深层神经网络:框架总览和初始化参数
图中,起始的cost很大,这是由于采用的随机初始化的权重矩阵值较大,导致有些样本对于**函数(sigmoid,输出层)输出结果值很靠近0或者1。当输出的结果值不同于真实值,其代价很大,比如log(a[3])=log(0)log⁡(a[3])=log⁡(0),其代价是无穷大的。
虽然,随机初始化成功打破了对称性问题,但过大或者过小的权重矩阵将导致梯度的暴涨或者快速衰减,这都会减缓优化算法获取最优结果的速度。那什么是梯度爆炸和梯度消失呢?

梯度爆炸和梯度消失

假设,由一个L层的深度神经网络,同时假设偏置b=0,**函数个g(z) = z。
由神经网络的前向传播 z= wx+ b.可得:
y_hat = w[L]w[l-1]w[l-2]…w[3]w[2]w[1]x
逆推:
a[1]=z[1]=w[1]x
a[2]= z[2]=w[2]z[1]=w[2]w[1]x
a[3]=z[3]=w[3]z[2]=w[3]w[2]w[1]x

y_hat=a[L]=w[l]z[l]=w[l]w[l-1]…w[3]w[2]w[1]x
若,w=2,则y_hat=w1 x=22x y_hat将呈指数级增长;
同理,若,w=0.1,则y_hat=0.13x y_hat将呈指数级衰减。
所以,随着神经网络层数的递增,计算量逐步加大,最后将减缓优化算法获取最优结果的速度。

说明:w是权重,b是偏置,z是前向传播线性输出,a是前向传播非线性输出,[l]表示层数。另y_hat是中的2和0.1 是表示的其l-1次方

He 初始化

He初始化方法就是为了解决上述梯度消失和梯度爆炸问题而提出的。这种初始化方式是对随机初始化的权重矩阵乘以sqrt(2./layers_dims[l-1])。代码如下:

w = np.random.randn() * sqrt(2/layers_dims[l-1])

以下图片是使用随机初始化(random),更新一定轮数的神经网络返回的cost值
逐步建立深层神经网络:框架总览和初始化参数
可以看到曲线相对平滑,并无突然的直线下降存在。

ps:He初始化和ReLU一起会有很好的表现。

总结:

  • 随机输出可以打破对称性;
  • 初值不可设置太大或太小;
  • He可以消除梯度爆炸和梯度消失,同时和线性整流单元ReLU一起使用会有很好的表现。

最后,我建立的初始化包,将使用He进行.代码如下:

#GRADED FUNCTION: initialize_parameters_deep
improt numpy as py

def initialize_parameters_deep(layers_dims):
    
    np.random.seed()   #生成随机种子
    parameters = {}        #定义parameters的字典
    L = len(layers_dims)       #表示神经网络层数
    
    for l in range(0, L):
 	 	 #初始化参数
   		 parameters["W" + str(l)] = np.random.ramdm(layers_dims[l], layers_dims[l-1])
		 parameters["b" + str(l)] = np.zeros((layers_dims[l], 1))
   
   		#定义parameters的形状
		 assert (parameters["W" + str(l)].shape == (layers_dims[l], layers_dims[l-1])
  		 assert (parameters["b" + str(l)].shape == (layers_dins[l], 1)

	return parameters
    


  1. l-1 ↩︎

  2. l-1 ↩︎

  3. l-1 ↩︎