学习笔记三:MLP基本原理、矩阵求导术推反向传播、激活函数、Xavier

文章目录

    • 一、BP神经网络(MLP)
      • 1.1 感知机模型及其局限性
      • 1.2 BP神经网络基本原理
      • 1.3 softmax多分类、求导
      • 1.4 二分类使用softmax还是sigmoid好?
      • 1.5 为什么要用激活函数?
      • 1.6 梯度下降和链式求导
      • 1.7度量学习
    • 二、矩阵求导术
      • 2.1 标量对向量求导
      • 2.2 向量对向量求导
      • 2.3 标量对矩阵的矩阵
      • 2.4 向量求导及链式法则
      • 2.5 BP反向传播
      • 2.5 激活函数及其导数
    • 三、神经网络调优
      • 3.1 激活函数得选型
      • 3.2 Relu激活函数及其变体
      • 3.3 高斯误差线性单元激活函数gelu
        • 3.3.1 GELU概述
        • 3.3.2 GELU数学表示
      • 3.4 Xavier权重初始化

一、BP神经网络(MLP)

1.1 感知机模型及其局限性

感知机是一个有若干输入和一个输出的模型:
z = ∑ i = 1 m w i x i + b z=\sum\limits_{i=1}^mw_ix_i + b z=i=1mwixi+b
接着是一个神经元激活函数:
s i g n ( z ) = { − 1 z < 0 1 z ≥ 0 sign(z)= \begin{cases} -1& {z<0}\\ 1& {z\geq 0} \end{cases} sign(z)={11z<0z0

从而得到我们想要的输出结果1或者-1。

所以MLP模型只能用于二元分类,且无法学习比较复杂的非线性模型,因此在工业界无法使用。而神经网络则在感知机的模型上做了扩展来解决这个问题。

  • 加入了隐藏层,隐藏层可以有多层,增强模型的表达能力
  • 输出层的神经元可以有多个输出,这样模型可以灵活的应用于分类回归
  • 对激活函数做扩展,感知机的激活函数是 s i g n ( z ) sign(z) sign(z),虽然简单但是处理能力有限,因此神经网络中一般使用的其他的激活函数
        
    为什么要使用神经网络模型?
  1. 逻辑回归对于如今越来越复杂的任务效果越来越差,主要是难以处理线性不可分的数据,LR处理线性不可分,一般是特征变换和特征组合,将低维空间线性不可分的数据在高维空间中线性可分

  2. 改良方式有几种,本质上都是对原始输入特征做文章。但都是针对特定场景设计。如果实际场景中特征组合在设计之外,模型无能为力

    • 人工组合高维特征,将特征升维至高维空间。但是会耗费较多人力,而且需要对业务理解很深
    • 自动交叉二阶特征,例如FM模型。缺点是只能进行二阶交叉
    • SVM+核方法:可以将特征投影到高维空间。缺点是核函数种类有限,升维具有局限性,运算量巨大。
  3. 构建BP神经网络(也叫MLP多层感知器),用线性变换+非线性函数激活的方式进行特征变换。以分类为目的进行学习的时候,网络中的参数会以分类正确为目的自行调整,也就是自动提取合适的特征。(回归问题,去掉最后一层的激活函数就行。输出层激活函数只是为了结果有概率意义)神经网络最大的惊喜就是自动组合特征。

1.2 BP神经网络基本原理

  • MLP网络中,每个节点都接收前一层所有节点的信号的加权和,累加后进行激活,再传入下一层的节点。这个过程和动物神经元细胞传递信号的过程类似,所以叫神经网络,各节点称为神经元。
  • 每层神经元个数称为神经网络的宽度,层数称为神经网络的深度。所以多层神经网络称为深度神经网络DNN。
  • 神经元数据过多会造成过拟合和运算量过大。层中神经元过多,相当于该层转换后的特征维度过高,会造成维数灾难。
  • DNN仍然使用交叉熵损失函数。

1.3 softmax多分类、求导

  • 机器学习模型相对简单,参数较少。可以通过训练N个二分类模型来完成多分类。而深度学习中,模型参数较多,训练多个模型不实际。而且多分类任务的前层特征变换是一致的,没必要训练多个模型。一般是输出层采用softmax函数来完成。
  • softmax做多分类只适用于类别互斥且和为1的情况。如果和不为1,可以加一个其它类。不互斥时不能保证分母能归一化。
  • 如果多个标签有交集不互斥,比如歌曲分类:流行、摇滚、抒情、怀旧的时候,类别不互斥,且还存在其它类。此时不能用softmax,而应该用sigmoid进行多个二分类,文本分类要注意。
  • 为什么叫softmax。如果是max做分类结果,那就是直接输出one-hot向量[0,0,1],非连续函数不好求导。而softmax就要软一点,softmax(np.array([0.2,0.1,0.8]))=array([0.2683, 0.2428, 0.4889]),可求导。

1.4 二分类使用softmax还是sigmoid好?

参考《速通8-DNN神经网络学习笔记》
a、b两类二分类时:
s o f t m a x ( x = a ) = e a e a + e b = 1 1 + e b − a = 1 1 + e − d softmax(x=a)=\frac{e^{a}}{e^{a}+e^{b}}=\frac{1}{1+e^{b-a}}=\frac{1}{1+e^{-d}} softmaxx=a=ea+ebea=1+eba1=1+ed1

  • softmax等于分别学习w1和w2,而sigmoid等于学这两个的差值就行了。sigmoid是softmax在二分类上的特例。二分类时sigmoid更好。因为我们只关注w1和w2的差值,但是不关心其具体的值。
  • softmax的运算量很大,因为要考虑别的概率值。一般只在神经网络最后一层用(多分类时)。中间层神经元各算各的,不需要考虑别的w数值,所以中间层不需要softmax函数。
  • softmax函数分子:通过指数函数,将实数输出映射到零到正无穷。softmax函数分母:将所有结果相加,进行归一化。
  • softmax和sigmoid一样有饱和区,x变化几乎不会引起softmax输出的变化,而且饱和区导数几乎为0,无法有效学习。所以需要合适的初始化,控制前层输出的值域。
  • 两个函数的代码实现如下图
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
    return 1.0/(1+np.exp(-x))
	 
sigmoid_inputs = np.arange(-10,10)
sigmoid_outputs=sigmoid(sigmoid_inputs)
print("Sigmoid Function Input :: {}".format(sigmoid_inputs))
print("Sigmoid Function Output :: {}".format(sigmoid_outputs))
 
plt.plot(sigmoid_inputs,sigmoid_outputs)
plt.xlabel("Sigmoid Inputs")
plt.ylabel("Sigmoid Outputs")
plt.show()
def softmax(x):
    orig_shape=x.shape
    if len(x.shape)>1:
        #Matrix
        #shift max whithin each row
        constant_shift=np.max(x,axis=1).reshape(1,-1)
        x-=constant_shift
        x=np.exp(x)
        normlize=np.sum(x,axis=1).reshape(1,-1)
        x/=normlize
    else:
        #vector
        constant_shift=np.max(x)
        x-=constant_shift
        x=np.exp(x)
        normlize=np.sum(x)
        x/=normlize
    assert x.shape==orig_shape
    return x
 
softmax_inputs = np.arange(-10,10)
softmax_outputs=softmax(softmax_inputs)
print("Sigmoid Function Input :: {}".format(softmax_inputs))
print("Sigmoid Function Output :: {}".format(softmax_outputs))
# 画图像
plt.plot(softmax_inputs,softmax_outputs)
plt.xlabel("Softmax Inputs")
plt.ylabel("Softmax Outputs")
plt.show()

1.5 为什么要用激活函数?

  • 没有非线性函数,多层线性变换等于一层,丧失了深度的意义。
  • 非线性变换才能够解决线性不可分的问题,组合更丰富的高阶特征。

第二点从泰勒公式来说明:

泰勒公式:

任意函数可以写成多项式的和。 x 0 x_0 x0是函数定义域上的任意一点,x在a的附近。 R n R_n Rn是补偿,n越大 R n R_n Rn越小。n→∞, R n → 0 R_n→0 Rn0

  • y=kx+b, f ′ = k f{}'=k f=k f ′ ′ = 0 f{}'{}'=0 f=0,往后导数都是0 。
  • y= e x e^x ex f ′ = e x f{}'=e^x f=ex f ′ ′ = e x f{}'{}'=e^x f=ex…各阶导数都是 e x e^x ex
  • 线性变换:二阶导数以后都是0
  • 合适的非线性变换(常见激活函数):高阶导数都不为0,尽量保留高阶项。
  1. 如果神经网络不加激活函数,f(d)=d(二阶导往后都为0)
  2. 如果神经网络加了sigmoid函数,其n阶导数为nf(1-f),则: f ( d ) = s i g m o i d ( d ) = f ( x 0 ) + f ( x 0 ) ′ d + 2 f ( x 0 ) ′ ′ d 2 + 6 f ( x 0 ) ′ ′ ′ d 3 . . . f(d)=sigmoid(d)=f({x_0})+f({x_0})'d+2f({x_0})'{}'d^{2}+6f({x_0})'{}'{}'d^{3}... f(d)=sigmoid(d)=f(x0)+f(x0)d+2f(x0)d2+6f(x0)d3...
    d = ∑ i = 1 n w i x i d=\sum_{i=1}^{n} w_ix_i d=i=1nwixi,第三项就有 d = ∑ i = 1 n ( w i x i ) 2 d=\sum_{i=1}^{n} (w_ix_i)^2 d=i=1n(wixi)2,等于FM模型二阶特征组合。第四项是三阶特征组合…。所以加入激活函数等于做了高阶特征组合。

为什么不用 e x e^x ex做激活函数,因为其各阶导数都一样。即各阶特征组合权重都很大,没有衰减过程。而好的特征我们希望组合特征的越高阶,对应权重越低,否则过拟合。不衰减,模型会认为必须满足所有高阶特征才预测出正确结果,泛化能力很弱。所以希望模型可以捕获高阶特征,但是不能过于依赖高阶特征。


没有激活函数的两层线性变换的意义:
1.  Self-Attention模型的作用是提取语义级别的信息(不存在长距离依赖),而FFNN是在各个时序上对特征进行非线性变换,提高网络表达能力。
  FFNN有两层,是将attention层输出先扩维4倍再降维。为什么这么做?神经网络中线性连接可以写成 d l = W l ⋅ x d^l=W^{l}\cdot x dl=Wlx。其中三者维度分别是m×1、m×n、n×1。

  • m>n:升维,将特征进行各种类型的特征组合,提高模型分辨能力
  • m 所以一般神经网络都是先做宽再做窄。
  1. 有的时候不加激活函数可以节省大量参数。
    例如:向量x是100×1维,向量y是1000×1维。直接变换,则W是1000×100=10万维。 y = W x y=Wx y=Wx
    如果经过一个10×1的中间向量z进行变换有:
    z = M x z=Mx z=Mx
    y = N z y=Nz y=Nz
    也可以达到y=NMx变换的目的,但是M是10×100维,N是1000×10维,总共11000维,大大减少参数量。

1.6 梯度下降和链式求导

1.7度量学习

二、矩阵求导术

线性代数参考《线性代数一(基本概念)》

2.1 标量对向量求导

例如标量z对向量X求导,就是看X各元素变化对z的影响。所以结果是z对X各元素求导,结果也是一个同尺寸向量。

2.2 向量对向量求导

列向量对行向量求导,结果是一个矩阵,方便后面进行链式求导中的导数连乘。(向量既可以写成列的形式,也可以写成行的形式。列向量可以直接对列向量求导,但是维数太多不便于操作,而且没法进行连乘,一般没人这么干。)

  • m×1维列向量 y y y对n×1维列向量 x x x求导,等于 y y y的每个元素 y i y_{i} yi分别对 x x x求导,得到m×1维导数。而导数每个元素都是标量对向量求导,结果是n×1维列向量。所以最终结果是mn×1维的列向量。行向量亦然。
  • 神经网络中一般都用列向量。,如果列向量 y y y对列向量 x x x求导,结果太长不便于计算。一般是 y y y x x x的转置求导,即 ∂ y ∂ x T \frac{\partial y}{\partial x^{T}} xTy,最后结果是一个m×n的矩阵。

2.3 标量对矩阵的矩阵

向量可以看成某一维为1的矩阵(行为1或列为1),同理,标量对m×n维矩阵求导,是对矩阵中每个元素求导,结果也是一个m×n维的结果。

2.4 向量求导及链式法则

对于 x 3 = W x 2 x_{3}=Wx_{2} x3=Wx2
展开之后有:
( x 31 x 32 . . . x 3 m ) = ( m 11 m 12 . . . m 1 n m 21 m 22 . . . m 2 n . . . . . . . . . . . . m m 1 m m 2 . . . m m n ) × ( x 21 x 22 . . . x 2 n ) \begin{pmatrix} x_{31}\\ x_{32}\\ ...\\ x_{3m}\end{pmatrix}=\begin{pmatrix} m_{11} & m_{12} &... &m _{1n} \\ m_{21} &m _{22} &... &m_{2n} \\ ...& ... & ... &... \\ m_{m1}&m_{m2} &... & m_{mn} \end{pmatrix}\times \begin{pmatrix} x_{21}\\ x_{22}\\ ...\\ x_{2n}\end{pmatrix} x31x32...x3m = m11m21...mm1m12m22...mm2............m1nm2n...mmn × x21x22...x2n
所以 ∂ x 3 ∂ x 2 T = W \frac{\partial x_{3}}{\partial x_{2}^{T}}=W x2Tx3=W ∂ x 3 ∂ W = x 2 T \frac{\partial x_{3}}{\partial W}=x_{2}^{T} Wx3=x2T

  • 即之前列向量对列向量转置求导,推出结果是mn的矩阵,但是各元素的具体值不知道。这里直接求出,具体值为矩阵W
  • 求导要一直盯着尺寸看。

公式1——标量对向量求导链式法则:
向量 x 1 . . . x n x_{1}...x_{n} x1...xn为神经网络各层的输入,最终输出结果是标量z。存在依赖关系: x 1 → x 2 → x 3 . . . → x n → z x_{1}\rightarrow x_{2}\rightarrow x_{3}...\rightarrow x_{n}\rightarrow z x1x2x3...xnz,则有:
∂ z ∂ x 1 = ( ∂ x n ∂ x n − 1 T ⋅ ∂ x n − 1 ∂ x n − 2 T . . . ∂ x 2 ∂ x 1 T ) T ∂ z ∂ x n \frac{\partial z}{\partial x_{1}}=(\frac{\partial x_{n} }{\partial x_{n-1}^{T}}\cdot \frac{\partial x_{n-1} }{\partial x_{n-2}^{T}}...\frac{\partial x_{2} }{\partial x_{1}^{T}})^{T}\frac{\partial z}{\partial x_{n}} x1z=(xn1Txnxn2Txn1...x1Tx2)Txnz

  • 假如 x n 、 x n − 1 、 x n − 2 x_{n}、x_{n-1}、x_{n-2} xnxn1xn2分别是m、n、k维的列向量,则上式右边第一项分别是m×n和n×k的矩阵,这两个矩阵才有相乘的可能,结果是m×k的矩阵。所以必须是列向量对列向量的转置求导
  • 假如 x 1 x_{1} x1是h维列向量,则括号内最终结果是m×h维矩阵, ∂ z ∂ x n \frac{\partial z}{\partial x_{n}} xnz结果是m维列向量,无法直接相乘,所以括号内的矩阵必须转置。

公式2——标量对矩阵求导链式法则:
W为矩阵, x x x y y y是向量,有 y = W x y=Wx y=Wx。且标量 z = f ( y ) z=f(y) z=f(y),则:
∂ z ∂ W = ∂ z ∂ y ⋅ x T \frac{\partial z}{\partial W}=\frac{\partial z }{\partial y}\cdot x^{T} Wz=yzxT
参照上面写的: ∂ x 3 ∂ W = x 2 T \frac{\partial x_{3}}{\partial W}=x_{2}^{T} Wx3=x2T

2.5 BP反向传播

Loss对任意层 W k W^k Wk求导有:
∂ L o s s ∂ W k = ∂ L o s s ∂ d j L ⋅ ∂ d j L ∂ W k \frac{\partial Loss}{\partial W^{k}}=\frac{\partial Loss}{\partial d_{j}^{L}}\cdot \frac{\partial d_{j}^{L}}{\partial W^{k}} WkLoss=djLLossWkdjL
对于一个L层的神经网络,j表示L层第j维数据(也就是第j个神经元)
第一项 ∂ L o s s ∂ d j L = y j ′ − y j \frac{\partial Loss}{\partial d_{j}^{L}}=y_{j}'-y_{j} djLLoss=yjyj,是一个标量。(即loss对最后一层某个神经元导数为一个标量,推导见P119)
又因为:
d k = W k ⋅ a k − 1 d^{k}=W^{k}\cdot a^{k-1} dk=Wkak1
a k − 1 = f ( d l − 1 + w 0 k − 1 ) a^{k-1}=f(d^{l-1}+w_{0}^{k-1}) ak1=f(dl1+w0k1)
后一项是标量对矩阵求导,根据公式2有:
∂ d j L ∂ W k = ∂ d j L ∂ d k ⋅ ( a k − 1 ) T \frac{\partial d_{j}^{L}}{\partial W^{k}}= \frac{\partial d_{j}^{L}}{\partial d^{k}}\cdot (a^{k-1})^{T} WkdjL=dkdjL(ak1)T

d j L d_{j}^{L} djL看做是由向量 d L d^{L} dL映射成标量

上式右边第一项是标量对向量求导,根据公式1有:
∂ d j L ∂ d k = ∂ d j L ∂ a L − 1 ⋅ ( ∂ a L − 1 ∂ ( d L − 1 ) T ⋅ ∂ d L − 1 ∂ ( a L − 2 ) T . . . ∂ d k + 1 ∂ ( a k ) T ⋅ ∂ a k ∂ ( d k ) T ) T \frac{\partial d_{j}^{L}}{\partial d^{k}}=\frac{\partial d_{j}^{L}}{\partial a^{L-1}}\cdot (\frac{\partial a^{L-1}}{\partial (d^{L-1})^{T}}\cdot \frac{\partial d^{L-1}}{\partial (a^{L-2})^{T}}...\frac{\partial d^{k+1}}{\partial (a^{k})^{T}}\cdot \frac{\partial a^{k}}{\partial (d^{k})^{T}})^T dkdjL=aL1djL((dL1)TaL1(aL2)TdL1...(ak)Tdk+1(dk)Tak)T
依次求三项导数有:
∂ d j L ∂ a L − 1 = W L \frac{\partial d_{j}^{L}}{\partial a^{L-1}}=W^L aL1djL=WL
∂ a m ∂ ( d m ) T = f ′ ( d m ) \frac{\partial a^{m}}{\partial (d^{m})^{T}}=f'(d^m) (dm)Tam=f(dm)
∂ d m + 1 ∂ ( a m ) T = W m + 1 \frac{\partial d^{m+1}}{\partial (a^{m})^{T}}=W^{m+1} (am)Tdm+1=Wm+1
将以上结果联合起来就是:
∂ L o s s ∂ W k = ∂ L o s s ∂ d j L ⋅ ∂ d j L ∂ W k = ( y j ′ − y j ) ⋅ ( a k − 1 ) T ⋅ W L ⋅ f ′ ( d L − 1 ) ⋅ W L − 1 ⋅ f ′ ( d L − 2 ) . . . W k + 1 ⋅ f ′ ( d k ) \frac{\partial Loss}{\partial W^{k}}=\frac{\partial Loss}{\partial d_{j}^{L}}\cdot \frac{\partial d_{j}^{L}}{\partial W^{k}}=(y'_{j}-y_{j})\cdot (a^{k-1})^{T}\cdot W^{L}\cdot f'(d^{L-1})\cdot W^{L-1}\cdot f'(d^{L-2})... W^{k+1}\cdot f'(d^{k}) WkLoss=djLLossWkdjL=(yjyj)(ak1)TWLf(dL1)WL1f(dL2)...Wk+1f(dk)

第m层激活函数得导数有:
a m = f ( d m + w 0 m ) a^{m}=f(d^{m}+w_{0}^{m}) am=f(dm+w0m)
展开后为:
( a 1 a 2 . . . a M ) = ( f ( d 1 + w 0 1 ) f ( d 2 + w 0 2 ) . . . f ( d M ) + w 0 M ) \begin{pmatrix} a_{1}\\ a_{2}\\ ...\\ a_{M}\end{pmatrix}=\begin{pmatrix} f(d_{1}+w_{0}^{1})\\ f(d_{2}+w_{0}^{2})\\ ...\\ f(d_{M})+w_{0}^{M}\end{pmatrix} a1a2...aM = f(d1+w01)f(d2+w02)...f(dM)+w0M
其实是省去了上标层数m,其中第m层共有M个神经元。相当于向量d数乘之后得到向量a,每个元素按位操作。 a 1 = f ( d 1 + w 0 1 ) a_{1}=f(d_{1}+w_{0}^{1}) a1=f(d1+w01), a 1 a_{1} a1只和 d 1 d_{1} d1有关,和向量d其它元素无关,对d其它分量结果为0。

∂ a m ∂ ( d m ) T = f ′ ( d m ) \frac{\partial a^{m}}{\partial (d^{m})^{T}}=f'(d^m) (dm)Tam=f(dm)
列向量对行向量求导,结果是一个矩阵。所以有:
f ′ ( d m ) = ( f ′ ( d 1 + w 0 1 ) 0 . . . 0 0 f ′ ( d 2 + w 0 2 ) . . . 0 0 . . . . . . . . . 0 0 . . . f ′ ( d M + w 0 M ) ) f'(d^m)=\begin{pmatrix} f'(d_{1}+w_{0}^{1}) &0 &... &0 \\ 0& f'(d_{2}+w_{0}^{2}) & ... & 0\\ 0 &... & ... &... \\ 0& 0 & ... & f'(d_{M}+w_{0}^{M}) \end{pmatrix} f(dm)= f(d1+w01)0000f(d2+w02)...0............00...f(dM+w0M)

  • 如果激活函数f的导数f’>1,经过多次连乘,最后结果会非常大,即梯度爆炸。会产生震荡甚至溢出。
  • 如果f’<1,梯度消失,W几乎不会更新。

2.5 激活函数及其导数

  1. sigmoid函数: s i g m o i d ( d ) = 1 1 + e − d sigmoid(d)=\frac{1}{1+e^{-d}} sigmoid(d)=1+ed1导数为:
    f ′ = f ( 1 − f ) = 0.25 − ( f − 0.5 ) 2 f'=f(1-f)=0.25-(f-0.5)^2 f=f(1f)=0.25(f0.5)2,后一项非负,当f=0.5时有最大值0.25。所以其值域为(0,0.25)

  2. softmax函数及其导数,参考《Softmax函数及其导数》
    在这里插入图片描述

  3. relu函数: f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x)。其导数w为:
    f ′ ( x ) = { 0 , x < 0 1 , x > 0 f'(x)=\left\{\begin{matrix} 0 ,x<0\\ 1,x>0\end{matrix}\right. f(x)={0,x<01,x>0

  4. Tanh函数
    f ( d ) = T a n h ( d ) = e d − e − d e d + e − d = s i g m o i d ( 2 d − 1 ) f(d)=Tanh(d)=\frac{e^{d}-e^{-d}}{e^{d}+e^{-d}}=sigmoid(2d-1) f(d)=Tanh(d)=ed+ededed=sigmoid(2d1)
    导数为: ∂ a ∂ d = 1 − f 2 \frac{\partial a}{\partial d}=1-f^{2} da=1f2
    Tanh值域(-1,1),导数值域(0,1)。

三、神经网络调优

海量的数据和强大的算力为深度学习的发展提供了条件。但是也带来一些新的问题:

  • 网络太深带来梯度消失和梯度爆炸
  • 损失函数太复杂,有大量的极小点和鞍点,如果学习方法不合适,损失函数可能无法降低
  • 参数过多造成过拟合

3.1 激活函数得选型

合适的激活函数需要满足的条件

  1. 零均值输出:例如tanh,零均值输出,有正有负。W各个维度更新方向可以不同,避免单向更新学习慢的问题(各维度只能同增或者同减,走Z字路线。比如loss极小值在左下方,只能先左后下)这一点softmax、sigmoid、relu都不满足,都是非负的
  2. 适当的线性。激活函数对输入的变化不宜过于激烈,否则输入轻微变化造成输出剧烈变化,稳定性不好。softmax、sigmoid、relu、tanh都有近似线性的区域可以满足
  3. 导数不宜过大或过小,否则梯度消失或者爆炸。这也是relu成为神经网络首选的原因。tanh导数是0-1,比sigmoid好一点。
  4. 导数的单调性。避免导数有正有负造成学习震荡,例如三角函数
  5. 有值域的控制。避免多次激活后输出太大。例如 y = x 2 y=x^2 y=x2
  6. 没有超参数,计算简单。Maxout、PReLu函数有超参数,设置本身依赖经验。而且ReLu计算足够简单

3.2 Relu激活函数及其变体

参考《从ReLU到GELU,一文概览神经网络的激活函数》
线性整流函数Relu: f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x)

  • d≥0时,f(d)=d,导数为1,不存在梯度消失或者梯度爆炸,也不存在饱和区
  • d<0时,f(d)=0,梯度为0 ,神经元死亡
    梯度消失和激活函数饱和困扰业界多年,直到RELU的出现。

神经元真死和假死:
真死:

  • 无论w和x各维度如何变化,恒有 d j ( l ) = w j ( l ) a ( l − 1 ) d_{j}^{(l)}=w_{j}^{(l)}a^{(l-1)} dj(l)=wj(l)a(l1)≤0,神经元死亡。(l表示神经网络层数,j表示某层中神经元节点j)。 a ( l − 1 ) ≥ 0 a^{(l-1)}≥0 a(l1)0为上一层神经网络的输出。
  • 所以是 w j ( l ) w_{j}^{(l)} wj(l)各元素都是很大的负数时,恒有d≤0。这是参数初始化错误或者lr过大导致权重 w j ( l ) w_{j}^{(l)} wj(l)更新过大造成的。因此用Relu做激活函数,lr不宜过大,权重初始化要合理

假死:饱和形式之一

  • 恰巧造成 w j ( l ) a j ( l − 1 ) ≤ 0 w_{j}^{(l)}a_{j}^{(l-1)}≤0 wj(l)aj(l1)0,重新训练时有可能会恢复正常。神经元大多数时是假死。
  • 适当假死可以提升神经网络效果:
    • 如果没有神经元假死, a j ( l − 1 ) ≥ 0 a_{j}^{(l-1)}≥0 aj(l1)0,f(d)=d,Relu作为激活函数就是纯线性的,失去意义。
    • 假死神经元就是对某些输入特征不进行输出,达到特征选择的作用(门控决策)

LRelu: d<0时,f(d)=k,k为超参数,在0-1之间
PRelu: d<0时,f(d)=k,k是可学习的参数。
Maxout: w j ( l ) ( 1 ) w_{j}^{(l)}(1) wj(l)(1) w j ( l ) ( n ) w_{j}^{(l)}(n) wj(l)(n)有多个参数,分别和上一层输出相乘,即每个神经元节点j有多个输入,最终输出选最大值。(P133-134)

3.3 高斯误差线性单元激活函数gelu

参考《超越ReLU却鲜为人知,3年后被挖掘》
参考《GELU 论文》

3.3.1 GELU概述

BERT、RoBERTa、ALBERT 等目前业内顶尖的 NLP 模型都使用了这种激活函数。另外,在 OpenAI 声名远播的无监督预训练模型 GPT-2 中,研究人员在所有编码器模块中都使用了 GELU 激活函数。在计算机视觉、自然语言处理和自动语音识别等任务上,使用 GELU 激活函数比使用ReLU 或 ELU 效果更好。

随着网络深度的不断增加,利用 Sigmoid 激活函数来训练被证实不如非平滑、低概率性的 ReLU 有效(Nair & Hinton, 2010),因为 ReLU 基于输入信号做出门控决策。

深度学习中为了解决过拟合,会随机正则化(如在隐层中加入噪声)或采用 dropout 机制。这两个选择是和激活函数割裂的。非线性和 dropout 共同决定了神经元的输出,而随机正则化在执行时与输入无关。

由此提出高斯误差线性单元(Gaussian Error Linear Unit,GELU)。GELU 与随机正则化有关,因为它是自适应 Dropout 的修正预期(Ba & Frey, 2013)。这表明神经元输出的概率性更高。

3.3.2 GELU数学表示

Dropout、ReLU 等机制都希望将「不重要」的激活信息规整为零。即对于输入的值,我们根据它的情况乘上 1 或 0。或者说,对输入x乘上一个伯努利分布 Bernoulli(Φ(x)),其中Φ(x) = P(X ≤ x)。(x服从于标准正态分布 N(0, 1))

对于一部分Φ(x),它直接乘以输入 x,而对于另一部分 (1 − Φ(x)),它们需要归零。随着 x 的降低,它被归零的概率会升高。对于 ReLU 来说,这个界限就是 0。

我们经常希望神经网络具有确定性决策,这种想法催生了 GELU 激活函数的诞生。具体来说可以表示为:Φ(x) × Ix + (1 − Φ(x)) × 0x = xΦ(x)。可以理解为,不太严格地说,上面这个表达式可以按当前输入 x 比其它输入大多少来缩放 x。

高斯概率分布函数通常根据损失函数计算,因此研究者定义高斯误差线性单元(GELU)为:
G E L U ( x ) = x P ( X ⩽ x ) = x Φ ( x ) GELU(x)=xP(X\leqslant x)=x\Phi (x) GELU(x)=xP(Xx)=xΦ(x)
上面这个函数是无法直接计算的,因此可以通过另外的方法来逼近这样的激活函数,研究者得出来的表达式为:
G E L U ( x ) = 0.5 x ( 1 + t a n h [ 2 π ( x + 0.044175 x 3 ) ] ) GELU(x)=0.5x(1+tanh[\sqrt{\frac{2}{\pi }}(x+0.044175x^{3})]) GELU(x)=0.5x(1+tanh[π2 (x+0.044175x3)])
或: G E L U ( x ) = x σ ( 1.702 x ) GELU(x)=x\sigma (1.702x) GELU(x)=xσ(1.702x)
其中 σ() 是标准的 sigmoid 函数
在这里插入图片描述

当 x 大于 0 时,输出为 x;但 x=0 到 x=1 的区间除外,这时曲线更偏向于 y 轴。
没能找到该函数的导数,所以我使用了 WolframAlpha 来微分这个函数。结果如下:
在这里插入图片描述
微分的GELU函数:
在这里插入图片描述
GELU 的近似实现方式有两种,借助 tanh() 和借助σ()。我们在 GPT-2 的官方代码中也发现,更多研究者采用了 tanh() 的实现方式尽管它看起来要比 xσ(1.702x) 复杂很多。

# GPT-2 的 GELU 实现
def gelu(x):
	return 0.5*x*(1+tf.tanh(np.sqrt(2/np.pi)*(x+0.044715*tf.pow(x, 3))))

3.4 Xavier权重初始化

参考《苏神文章解析(6篇)》
《浅谈Transformer的初始化、参数化与标准化》
《从几何视角来理解模型参数的初始化策略》

  • 如果两个神经元参数完全相同,则梯度也相同,更新幅度一致,最后输出也相同。看上去是两个神经元,但其实相当于就一个,是互相冗余的。所以 初始化W矩阵时要破坏其对称性,独立均匀分布的随机初始化就可以做到。(正态分布采样容易集中在均值附近,可能造成权重对称)均匀分布有两个参数 μ / σ \mu/ \sigma μ/σ ,均值和方差。
  • 真实场景中,特征都是客观事实,一般都是>0。如果W矩阵各元素都是>0,则relu函数不起作用。都<0,神经元都死了。所以 W矩阵各元素需要有正有负,所以一般均匀分布选择均值为0。 σ \sigma σ 越大,w采样到大值的可能性越大,即 W i , j l ∝ σ i , j l W_{i,j}^{l}\propto \sigma _{i,j}^{l} Wi,jlσi,jl
  • 从均值为0、方差为1/m的随机分布中独立重复采样,这就是Xavier初始化(无激活函数时)relu做激活函数时,方差为2/m
  • NTK参数化:均值为0、方差为1的随机分布来初始化,但是将输出结果除以 m \sqrt{m} m 。利用NTK参数化后,所有参数都可以用方差为1的分布初始化,这意味着每个参数的量级大致都是相同的O(1)级别,让我们更平等地处理每一个参数,于是我们可以设置较大的学习率。
  • 对于 d j ( l ) = ∑ i = 1 M ( l − 1 ) w i , j ( l ) a i ( l − 1 ) d_{j}^{(l)}=\sum_{i=1}^{M(l-1)}w_{i,j}^{(l)}a_{i}^{(l-1)} dj(l)=i=1M(l1)wi,j(l)ai(l1),M(l-1)表示上一层神经元个数。 d j ( l ) d_{j}^{(l)} dj(l)不宜过大, W i , j l ∝ 1 M l − 1 , σ i , j l ∝ 1 M l − 1 W_{i,j}^{l}\propto \frac{1}{M^{l-1}},\sigma _{i,j}^{l}\propto \frac{1}{M^{l-1}} Wi,jlMl11,σi,jlMl11。否则relu前向传播时,输出会层层放大而溢出。softmax、sigmoid、tanh进入饱和区,导数基本为0。
    其它推导见P137

你可能感兴趣的:(人工智能读书笔记,深度学习,dnn)