进一步聊聊weight initialization
深度学习模型训练的过程本质是对weight(即参数W)进行更新,这需要每个参数有相应的初始值。
有人可能会说:“参数初始化有什么难点?直接将所有weight初始化为0或者初始化为随机数!” 对一些简单的机器学习模型,或当optimization function是convex function时,这些简单的方法确实有效。
然而对于深度学习而言,非线性函数被疯狂叠加,这便是一个非凸函数,如何选择参数初始值便成为一个值得探讨的问题。
研究的目的是:选择更适合的初始化方法,使得目标函数更容易被优化。
初始化为0
如果所有参数都被初始化为0,那么所有神经元的输出将是相同的,反向传播时每一层内所有的神经元的梯度也是相同的,这显然是一个不可行的方案。
预训练
pre-training是早期训练神经网络的有效初始化方法。第一步,将神经网络的每一层取出来,构建auto-encoder做训练,使得输入层和输出层保持一致。在这个过程中参数得到更新,形成初始值;第二步,将每一层放回神经网络中,使用训练数据fine-tuning网络。
随着数据量的增加以及activation function的发展,这种方案已很少采用,大家直接奔着训练的主题去了。现在我们往往是拿任务A(imagenet竞赛)中训练好的模型(可称为pre-training model),将其放在任务B上做fine-tuning。
random initialization
随机初始化,是最容易想到的方案。但是一旦随机分布选择不当,会导致网络优化陷入困境。
data = tf.constant(np.random.randn(2000, 800))
layer_sizes = [800 - 50 * i for i in range(0,10)]
num_layers = len(layer_sizes)
fcs = [] # To store fully connected layers' output
for i in range(0, num_layers - 1):
X = data if i == 0 else fcs[i - 1]
node_in = layer_sizes[i]
node_out = layer_sizes[i + 1]
W = tf.Variable(np.random.randn(node_in, node_out)) * 0.01
fc = tf.matmul(X, W)
fc = tf.nn.tanh(fc)
fcs.append(fc)
这里我们创建了一个10层的神经网络,非线性变换为tanh,每一层的参数都是随机正态分布,均值为0,标准差为0.01。每一层输出值分布的直方图:
随着层数的增加,网络输出迅速向0靠拢。在反向传播中,根据链式法则,梯度等于当前输入x(上一层的输出)乘以后一层的梯度,x趋向于0,意味着梯度将很小,参数更新缓慢。
调整初始化策略,增加方差:
W = tf.Variable(np.random.randn(node_in, node_out))
均值仍然为0,标准差现在变为1,此时每一层输出值分布的直方图:
此时,所有值会集中到-1或1附近,神经元饱和saturated了,也就是说tanh在-1和1附近的gradient都接近0,参数亦难更新。
Xavier initialization
泽维尔初始化的基本思想是:保持输入和输出的方差一致。注意:Xavier推到过程是基于线性函数的,但是它在非线性的神经元中依然表现不错。
W = tf.Variable(np.random.randn(node_in, node_out)) / np.sqrt(node_in)
输出值在很多层之后依然保持着良好的分布,这很有利于我们优化神经网络!之前谈到Xavier是在线性函数上推导得出,这说明它对非线性函数并不具有普适性,所以这个例子仅仅说明它对tanh很有效,那么对于目前最常用的ReLU神经元呢?
W = tf.Variable(np.random.randn(node_in, node_out)) / np.sqrt(node_in)
...
fc = tf.nn.relu(fc)
前面看起来还不错,但是后面的趋势却是越来越接近0。幸运的是,He initialization可以用来解决ReLU初始化的问题。
He initialization
He initialization的思想是:在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0,所以,要保持variance不变,只需要在Xavier的基础上再除以2。
W = tf.Variable(np.random.randn(node_in,node_out)) / np.sqrt(node_in/2)
...
fc = tf.nn.relu(fc)
效果得到了很大改善。
Batch Normalization Layer
BN是一种巧妙又粗暴的方法,可以来削弱bad initialization的影响。在网络传播中,我们想要的是在非线性activation之前,输出值应该有较好的分布(如高斯分布),以便于反向传播时计算梯度。BN的做法就是将输出值强制做一次高斯归一化和线性变换。BN的知识可以参考LRN和Batch Norm
随机初始化,有Batch Normalization:
W = tf.Variable(np.random.randn(node_in, node_out)) * 0.01
...
fc = tf.contrib.layers.batch_norm(fc, center=True, scale=True, is_training=True)
fc = tf.nn.relu(fc)
很容易看到,Batch Normalization的效果非常好。
参考
Xavier initialization是由Xavier Glorot et al.在2010年提出,He initialization是由Kaiming He et al.在2015年提出,Batch Normalization是由Sergey Ioffe et al.在2015年提出。
进一步聊聊weight initialization的更多相关文章
- [深度学习] 权重初始化--Weight Initialization
深度学习中的weight initialization对模型收敛速度和模型质量有重要影响! 在ReLU activation function中推荐使用Xavier Initialization的变种 ...
- (转载)深度学习的weight initialization
本文转自:谷歌工程师:聊一聊深度学习的weight initialization TLDR (or the take-away) Weight Initialization matters!!! 深度 ...
- [CS231n-CNN] Training Neural Networks Part 1 : activation functions, weight initialization, gradient flow, batch normalization | babysitting the learning process, hyperparameter optimization
课程主页:http://cs231n.stanford.edu/ Introduction to neural networks -Training Neural Network ________ ...
- 深度学习 weight initialization
转自: https://www.leiphone.com/news/201703/3qMp45aQtbxTdzmK.htmla https://blog.csdn.net/shuzfan/articl ...
- Coursera Deep Learning 2 Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization - week1, Assignment(Initialization)
声明:所有内容来自coursera,作为个人学习笔记记录在这里. Initialization Welcome to the first assignment of "Improving D ...
- (原)torch的训练过程
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6221622.html 参考网址: http://ju.outofmemory.cn/entry/284 ...
- [Hinton] Neural Networks for Machine Learning - Converage
Link: Neural Networks for Machine Learning - 多伦多大学 Link: Hinton的CSC321课程笔记 Ref: 神经网络训练中的Tricks之高效BP ...
- Understanding the Effective Receptive Field in Deep Convolutional Neural Networks
Understanding the Effective Receptive Field in Deep Convolutional Neural Networks 理解深度卷积神经网络中的有效感受野 ...
- Convolutional Neural Networks for Visual Recognition 5
Setting up the data and the model 前面我们介绍了一个神经元的模型,通过一个激励函数将高维的输入域权值的点积转化为一个单一的输出,而神经网络就是将神经元排列到每一层,形 ...
随机推荐
- Xamarin Essentials教程构建共享请求
Xamarin Essentials教程构建共享请求 共享请求类ShareTextRequest可以用于构建复杂形式的数据,用于向其他应用传输.例如,它可以指定共享内容的主题Subject,用于给邮件 ...
- angular笔记_6
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- sql关于对一个字段同时满足多条件判断来筛选查询
表所有数据 查询userName为abc或xyz的 以下为本菜鸟项目中遇到的问题: 背景: /** * wangjie 180629 * * 学生需要查询四种可能的消息 * 1.班级管理员发 ...
- 解决nuxt.js新建项目报错的问题
查了一下nuxt的github才知道是node.js版本太低造成的,据说升级到8.6以上就可以了(本人直接升了9.9) node_modules\nuxt\lib\core\middleware\nu ...
- LOJ.6235.区间素数个数(Min_25筛)
题目链接 \(Description\) 给定\(n\),求\(1\sim n\)中的素数个数. \(2\leq n\leq10^{11}\). \(Solution\) Min_25筛.只需要求出\ ...
- JavaScript基础笔记(八)DOM扩展
DOM扩展 一.选择符API Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询. 一)querySelector() 在Document和Element类型实例 ...
- JavaScript基础笔记(六)BOM
BOM 一.Window对象 在浏览器中window对象即是全局对象,又是JavaScript访问浏览器的一个接口. 定义全局变量和定义window对象还是有差别的,全局变量不能通过delete操作符 ...
- node 将本地项目docker化
vi test.sh docker rm -f kao3 || echo kao3 not exists;docker run -itd \--privileged=true \-v ~/logs:/ ...
- POJ 1905 Expanding Rods 木棍膨胀
描述 当长度为L的一根细木棍的温度升高n度,它会膨胀到新的长度L'=(1+n*C)*L,其中C是热膨胀系数. 当一根细木棍被嵌在两堵墙之间被加热,它将膨胀形成弓形的弧,而这个弓形的弦恰好是未加热前木棍 ...
- Android RxJava
GitHut 地址: https://github.com/ReactiveX/RxAndroid build.gradle: compile 'io.reactivex:rxandroid:1.2. ...