深度学习基础系列(六)| 权重初始化的选择

  深层网络需要一个优良的权重初始化方案,目的是降低发生梯度爆炸和梯度消失的风险。先解释下梯度爆炸和梯度消失的原因,假设我们有如下前向传播路径:

  a= w1x + b1  

  z= σ(a1)

  a= w2z1 + b2

  z2 = σ(a2)

  ...

  a= wnzn-1 + bn

  zn = σ(an)

  简化起见,令所有的b都为0,那么可得:

  zn =  σ(wnσ(Wn-1σ(...σ(w1x))),

  若进一步简化,令z = σ(a) = a,那么可得:

  zn = wn * Wn-1 * Wn-1 *...* X

  而权重w的选择,假定都为1.5,那么可观察到 zn是呈现指数级递增,深层网络越深,意味着后面的值越大,呈现爆炸趋势;反之,w假定都为0.5,那么可观察到 zn是呈现指数级递减,深层网络越深,意味着后面的值越小,呈现消失趋势。

  若令z = σ(a) = sigmoid(a),且a= ∑nwixi + b,其中n为输入参数的个数,当输入参数很多时,猜测|a|很大概率会大于1,对于sigmoid函数而言,|a|>1,则意味着曲线越来越平滑,z值会趋近于1或0,从而也会导致梯度消失。

  那我们在每一层网络进行初始化权重时,若能给w一个合适的值,则能降低这种梯度爆炸或梯度消失的可能性吗?我们看看该如何选择。

一、随机分布权重

  在keras中,其函数为:K.random_uniform_variable(),我们来直观地看看其数据分布图,先看代码:

import numpy as np
import matplotlib.pyplot as plt
import tensorflow.keras.backend as K

w = K.eval(K.random_uniform_variable(shape=(1, 10000), low=-1, high=1))
w = w.reshape(-1)
print("w:", w)

x = K.eval(K.random_uniform_variable(shape=(1, 10000), low=-1, high=1))
x = x.reshape(-1)
print("x:", x)

a = np.dot(w, x)
print("a:", a)

n, bins, patches = plt.hist(w, 50, density=1, facecolor=‘g‘, alpha=0.75)

plt.xlabel(‘data range‘)
plt.ylabel(‘probability‘)
plt.axis([-2, 2, 0, 1])
plt.grid(True)
plt.show()

  其图像为:

  观察图像可知,随机函数取了10000个点,值范围被约束在-1~1之间,其概率分布都很均匀。

  其输出结果为:

w: [-0.3033681   0.95340157  0.76744485 ...  0.24013376  0.5394962
 -0.23630977]
x: [-0.19380212  0.86640644  0.6185038  ... -0.66250014 -0.2095201
  0.23459053]
a: 16.111116

  从结果可知,若我们的输入是10000个特征点,那么a= ∑10000wixi + b,从图像观察可知|a|>1的概率很大(结果为16.111116)。可想而知,不采用激活函数或relu函数,则有梯度爆炸的可能性;若采用sigmoid激活函数的话,则会导致梯度消失。

二、正太分布权重

  在keras中,其函数为:K.random_normal_variable()和K.truncated_normal(),我们来直观地看看其数据分布图,先看K.random_normal_variable代码: 

import numpy as np
import matplotlib.pyplot as plt
import tensorflow.keras.backend as K

w = K.eval(K.random_normal_variable(shape=(1, 10000), mean=0, scale=1))
w = w.reshape(-1)
print("w:", w)

x = K.eval(K.random_uniform_variable(shape=(1, 10000), low=-1, high=1))
x = x.reshape(-1)
print("x:", x)

a = np.dot(w, x)
print("a:", a)

n, bins, patches = plt.hist(w, 50, density=1, facecolor=‘g‘, alpha=0.75)

plt.xlabel(‘data range‘)
plt.ylabel(‘probability‘)
plt.axis([-5, 5, 0, 0.6])
plt.grid(True)
plt.show()

  其图像为:

  其结果为:

w: [-1.8685548   1.501203    1.1083876  ... -0.93544585  0.08100258
  0.4771947 ]
x: [ 0.40333223  0.7284522  -0.40256715 ...  0.79942155 -0.915035
  0.50783443]
a: -46.02679

  再看看K.truncated_normal()的代码:

import numpy as np
import matplotlib.pyplot as plt
import tensorflow.keras.backend as K

w = K.eval(K.truncated_normal(shape=(1, 10000), mean=0, stddev=1))
w = w.reshape(-1)
print("w:", w)

x = K.eval(K.random_uniform_variable(shape=(1, 10000), low=-1, high=1))
x = x.reshape(-1)
print("x:", x)

a = np.dot(w, x)
print("a:", a)

n, bins, patches = plt.hist(w, 50, density=1, facecolor=‘g‘, alpha=0.75)

plt.xlabel(‘data range‘)
plt.ylabel(‘probability‘)
plt.axis([-5, 5, 0, 0.6])
plt.grid(True)
plt.show()

  其图像为:

 

  其结果为:

w: [ 1.0354282  -0.9385183   0.57337016 ... -0.3302136  -0.10443623
  0.9371711 ]
x: [-0.7896631  -0.01105547  0.778579   ...  0.7932384  -0.17074609
  0.60096693]
a: -18.191553

  观察两个图像可知,两者都是正太分布图像,唯一区别在于K.truncated_normal()把大于2和小于2的数据给截断了,只保留了一部分数据。

  从结果可知,若我们的输入是10000个特征点,那么a= ∑10000wixi + b ,从图像观察可知,虽然图像具有一定的对称性,总体均值为0,但|a1|>1依然有很大概率存在,依旧有有梯度消失和爆炸的可能性。    

 

三、正太收窄权重

  我们的目标是使得|a1| < 1,这样无论激活函数是sigmoid还是relu,都可以保证每一层的输出值不会增长太大,也不会增长过小。所以我们可以在正太分布的基础上,让其收窄变尖,可以让wi=wi / √n,其中n为该层的输入参数的数量,以10000个输出特征点为例,wi=wi / √10000,这样a1= ∑10000wixi + b1 就可以确保大致在-1~1范围内。可看代码:

import numpy as np
import matplotlib.pyplot as plt
import tensorflow.keras.backend as K

w = K.eval(K.random_normal_variable(shape=(1, 10000), mean=0, scale=1/np.sqrt(10000)))
w = w.reshape(-1)
print("w:", w)

x = K.eval(K.random_uniform_variable(shape=(1, 10000), low=-1, high=1))
x = x.reshape(-1)
print("x:", x)

a = np.dot(w, x)
print("a:", a)

n, bins, patches = plt.hist(w, 50, density=1, facecolor=‘g‘, alpha=0.75)

plt.xlabel(‘data range‘)
plt.ylabel(‘probability‘)
plt.axis([-0.1, 0.1, 0, 50])
plt.grid(True)
plt.show()

  其图像为:

  其结果为:

w: [ 0.00635913 -0.01406644 -0.00843588 ... -0.00573074  0.00345371
 -0.01102492]
x: [ 0.3738377  -0.01633143  0.21199775 ... -0.78332734 -0.96384525
 -0.3478613 ]
a: -0.4904538

  观察图像可知,数值范围已经被压缩在-0.025~0.025附近,概率值最高也到了40以上,变得又窄又尖了。

  从结果也可知,我们成功地把|a|压缩在1范围以内,这个结果无论对sigmoid函数,还是relu函数,都是比较友好的,降低了梯度爆炸和梯度消失的风险,也利于加快训练学习过程。

原文地址:https://www.cnblogs.com/hutao722/p/9796884.html

时间: 2024-07-31 03:25:40

深度学习基础系列(六)| 权重初始化的选择的相关文章

深度学习基础系列(二)| 常见的Top-1和Top-5有什么区别?

在深度学习过程中,会经常看见各成熟网络模型在ImageNet上的Top-1准确率和Top-5准确率的介绍,如下图所示: 那Top-1 Accuracy和Top-5 Accuracy是指什么呢?区别在哪呢?我们知道ImageNet有大概1000个分类,而模型预测某张图片时,会给出1000个按概率从高到低的类别排名, 所谓的Top-1 Accuracy是指排名第一的类别与实际结果相符的准确率, 而Top-5 Accuracy是指排名前五的类别包含实际结果的准确率. 下面的代码可更为直观地说明其中的区

深度学习实践系列(2)- 搭建notMNIST的深度神经网络

如果你希望系统性的了解神经网络,请参考零基础入门深度学习系列,下面我会粗略的介绍一下本文中实现神经网络需要了解的知识. 什么是深度神经网络? 神经网络包含三层:输入层(X).隐藏层和输出层:f(x) 每层之间每个节点都是完全连接的,其中包含权重(W).每层都存在一个偏移值(b). 每一层节点的计算方式如下: 其中g()代表激活函数,o()代表softmax输出函数. 使用Flow Graph的方式来表达如何正向推导神经网络,可以表达如下: x: 输入值 a(x):表示每个隐藏层的pre-acti

深度学习实践系列之--身份证上汉字及数字识别系统的实现(上)

前言: 本文章将记录我利用深度学习方法实现身份证图像的信息识别系统的实现过程,及学习到的心得与体会.本次实践是我投身AI的初次系统化的付诸实践,意义重大,让自己成长许多.终于有空闲的时间,将其记录,只为更好的分享与学习. 目录: 1.本人的主要工作 2.关键技术 3.模型训练 4.系统设计及实现 5.总结 正文: 一.本人的主要工作 深度学习技术与传统模式识别技术相比,免去人工提取特征,识别率更高.我基于深度学习的技术背景,主要的研究内容如下: 1)身份证图像涉及个人隐私,很难获取其数据训练集.

【C++自我精讲】基础系列六 PIMPL模式

0 前言 很实用的一种基础模式. 1 PIMPL解释 PIMPL(Private Implementation 或 Pointer to Implementation)是通过一个私有的成员指针,将指针所指向的类的内部实现数据进行隐藏. 2 PIMPL优点 举例: //x.h class X { public: void Fun(); private: int i; //add int i; }; //c.h #include <x.h> class C { public: void Fun()

算法工程师&lt;深度学习基础&gt;

<深度学习基础> 卷积神经网络,循环神经网络,LSTM与GRU,梯度消失与梯度爆炸,激活函数,防止过拟合的方法,dropout,batch normalization,各类经典的网络结构,各类优化方法 1.卷积神经网络工作原理的直观解释 https://www.zhihu.com/question/39022858 简单来说,在一定意义上,训练CNN就是在训练每一个卷积层的滤波器.让这些滤波器组对特定的模式有高的激活能力,以达到CNN网络的分类/检测等目的. 2.卷积神经网络的复杂度分析 ht

TensorFlow深度学习基础与应用实战高清视频教程

TensorFlow深度学习基础与应用实战高清视频教程,适合Python C++ C#视觉应用开发者,基于TensorFlow深度学习框架,讲解TensorFlow基础.图像分类.目标检测训练与测试以及后期在C++和C#的应用. 视频目录如下: 你能学到那些内容预览: TensorFlow深度学习基础与应用实战高清视频教程,适合Python C++ C#视觉应用开发者,基于TensorFlow深度学习框架,讲解TensorFlow基础.图像分类.目标检测训练与测试以及后期在C++和C#的应用.

《神经网络和深度学习》系列文章十六:反向传播算法代码

出处: Michael Nielsen的<Neural Network and Deep Learning>,点击末尾“阅读原文”即可查看英文原文. 本节译者:哈工大SCIR硕士生 李盛秋 声明:如需转载请联系[email protected],未经授权不得转载. 使用神经网络识别手写数字 反向传播算法是如何工作的 热身:一个基于矩阵的快速计算神经网络输出的方法 关于损失函数的两个假设 Hadamard积 反向传播背后的四个基本等式 四个基本等式的证明(选读) 反向传播算法 反向传播算法代码

【转】深度学习基础概念理解

原文链接 神经网络基础 1)神经元(Neuron)--就像形成我们大脑基本元素的神经元一样,神经元形成神经网络的基本结构.想象一下,当我们得到新信息时我们该怎么做.当我们获取信息时,我们一般会处理它,然后生成一个输出.类似地,在神经网络的情况下,神经元接收输入,处理它并产生输出,而这个输出被发送到其他神经元用于进一步处理,或者作为最终输出进行输出.  2)权重(Weights)--当输入进入神经元时,它会乘以一个权重.例如,如果一个神经元有两个输入,则每个输入将具有分配给它的一个关联权重.我们随

《神经网络和深度学习》系列文章二:感知机

出处: Michael Nielsen的<Neural Network and Deep Leraning>,点击末尾“阅读原文”即可查看英文原文. 本节译者:哈工大SCIR硕士生 徐梓翔 (https://github.com/endyul) 声明:我们将在每周一,周四,周日定期连载该书的中文翻译,如需转载请联系[email protected],未经授权不得转载. “本文转载自[哈工大SCIR]微信公众号,转载已征得同意.” 使用神经网络识别手写数字 感知机 sigmoid神经元 神经网络