cs231n学习之网络参数初始化(4)

前言

本文旨在学习和记录,如需转载,请附出处https://www.jianshu.com/p/113246eb8f3b

一、网络参数初始化

在神经网络训练中,训练最小化损失函数以找到一个最优解。但是,不同的网络初始化可能会产生不同的结果。本节主要探讨不同网络参数初始化的效果。

二、网络参数初始化都为0

很显然,如果网络参数都初始化为0时,那么所有的神经元都是一样的功能,网络从一开始训练到结束,所有的神经元的值都是一样的,那么我们的训练就会失败,因为我们期望每个神经元学习的功能是不一样,比如有的神经元对某一类的图片比较敏感,他的值比较大,对某些类的图片不敏感,值比较小。
所以,将网络参数初始化为0或者其他参数很显然是不可以,所以神经元功能一样,都是对称的

初始化高斯分布

标准差较小的初始化

# 均值为0标准差为0.01
w = 0.01*np.random.randn(Din, Dout)
import numpy as np
dims = [4096]*7
hs = []
x = np.random.randn(16,dims[0])
for Din, Dout in zip(dims[:-1],dims[1:]):
    W = 0.01*np.random.randn(Din, Dout)
    x = np.tanh(x.dot(W))
    hs.append(x)
print(np.mean(hs[0],axis=0))
image.png

可以发现使用tanh激活函数时,采用小的标准差数值还算比较稳定,但是所有的激活值有像0靠近的趋势,如果所有的值都为0了,学习将失败。如果网络层数加深,很明显最后所有激活值都趋近于0.

标准差较大的初始化

import numpy as np
dims = [4096]*7
hs = []
x = np.random.randn(16,dims[0])
for Din, Dout in zip(dims[:-1],dims[1:]):
    W = 0.05*np.random.randn(Din, Dout)
    x = np.tanh(x.dot(W))
    hs.append(x)
print(np.mean(hs[0],axis=0))
image.png

可以发现如果给初始化给较大的标准差,那么tanh所有的激活值都在tanh饱和区范围,我们都知道在饱和区梯度近似为0,所以学习也将失败。

三、Xavier initialization

Xavier initialization方法来源于Understanding the difficulty of training deep feedforward neural networks,该方法的主要思想是为了使网络中信息流动的更好,每一层输出的方差应该尽量相等
Xavier initialization假设使用的是对称线性激活函数,在x=0处的导数为1。

则:

已知输入数据和权重都是0均值,所以:


这里的代表所有数据每一维的组合。
为了保证输出和输入有相同的方差,所以对权重方差的要求有:

上面计算都是正向传播过程中的,反向传播也是类似的

多层反向传播中梯度方差的表示.png

所以保证前向传播和反向传播的每一层方差一致,有:

实际实验中,因为不一定相等,所以综合考虑有:

又对在[a,b]的均匀分布有:

所以真实的xavier initialization为:

code
这里的code只考虑了前向传播

import numpy as np
dims = [4096]*7
hs = []
x = np.random.randn(16,dims[0])
for Din, Dout in zip(dims[:-1],dims[1:]):
    W = np.random.randn(Din, Dout)/np.sqrt(Din)
    x = np.tanh(x.dot(W))
    hs.append(x)
print(np.mean(hs[0],axis=0))
image.png

可以发现对多层神经网络来说,采用tanh激活函数,xavier initialization都工作的很好。

采用ReLU激活函数
import numpy as np
dims = [4096]*7
hs = []
x = np.random.randn(16,dims[0])
for Din, Dout in zip(dims[:-1],dims[1:]):
    W = np.random.randn(Din, Dout)/np.sqrt(Din)
    x = np.maximum(x.dot(W),0)
    hs.append(x)
print(np.mean(hs[0],axis=0))

image.png

可以发现,xavier initialization对ReLU激活函数并不是工作的很好,实验中激活值都有趋近于0的迹象,xavier initialization的前提假设是激活函数时线性对称的,ReLU不满足要求,所以就不足为奇了

四、Kaiming initialization

Kaiming initialization也叫He initialzation,是2015年由何凯明提出的,主要针对的是Xavier initialization对Tanh激活函数能表现的很好,可是对ReLU激活函数却表现的很差。
思想:ReLU激活函数只激活输出为正的部分,作者假设每一层有一般的神经元被激活,另一半为0,所以,保持方差不变,在xavier initialization的基础上需要除以2.
所以Kaiming Initialization可以写为:

或者:

code

import numpy as np
dims = [4096]*7
hs = []
x = np.random.randn(16,dims[0])
for Din, Dout in zip(dims[:-1],dims[1:]):
    W = np.random.randn(Din, Dout)*np.sqrt(2/Din)
    x = np.maximum(x.dot(W),0)
    hs.append(x)
print(np.mean(hs[0],axis=0))
image.png

可以发现,Kaiming Initialization对ReLU激活函数能工作的很好。

五、结论

1、网络初始化不能全为0;
2、网络参数初始化用随机高斯分布(均值为0),其标准差不能太大,在标准差小的情况下、网络层数不多的情况下可以工作的很好;
3、Xavier initialization适合激活函数采用Tanh的网络
4、Kaiming Initialization适合激活函数采用ReLU的网络

六、参考

  1. Understanding the difficulty of training deep feedforward neural networks
  2. Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification
  3. cs231n教程

你可能感兴趣的:(cs231n学习之网络参数初始化(4))