逐步建立深层神经网络:框架总览和初始化参数
逐步建立深层神经网络:框架总览和初始化参数
正式入坑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