百面机器学习 之 激活函数+反向传播

        考完期末了,final week真的很折磨人,我发现我把书全看了也没我同学光看ppt懂的多,巨多知识点,计算过程在ppt上,我都miss掉了,很气人。还有Tobias,这老师我真的得骂一骂才爽,搞一堆幺蛾子出来,教的课就完全讲不清楚,活该评分低,活该sorry。真的把头都给气歪了

1. 软硬饱和函数

假设h(x)是一个激活函数。

1. 饱和
当我们的x趋近于正无穷,h(x)'趋近于0,那么我们称之为右饱和。
当我们的n趋近于负无穷,h(x)'趋近于0,那么我们称之为左饱和。
当一个函数既满足左饱和又满足右饱和的时候我们就称之为饱和,典型的函数有Sigmoid,Tanh函数。


2. 硬饱和
对于任意的x,如果存在常数c,当x>c时,恒有h(x)’=0,则称其为右硬饱和。
如果对于任意的x,如果存在常数c,当x<c时,恒有h(x)’=0,则称其为左硬饱和。
既满足左硬饱和又满足右硬饱和的我们称这种函数为硬饱和。


3. 软饱和
对于任意的x,如果存在常数c,当x>c时,恒有h(x)'趋近于0,则称其为右软饱和。
如果对于任意的x,如果存在常数c,当x<c时,恒有h(x)'趋近于0,则称其为左软饱和。
既满足左软饱和又满足右软饱和的我们称这种函数为软饱和。

2. 激活函数

2.1 sigmod

        这个函数嘛,估计面试的时候问到的概率还挺高的,着重说一说。

        sigmod的函数原型以及图像:

        f(x) = \frac{1}{1+e^{-x}}

        sigmod的导数:

f'(x) = f(x)(1-f(x)) = \frac{e^{-x}}{(e^{-x}+1)^2}

         sigmod函数就上图很显而易见了,不管输入是什么,得到的输出都在 0 到 1 之间。

        而导数值我们也可以看出,当x比较大或者比较小的时候,导数值是基本接近0的,这种现象我们称sigmod为饱和函数,具体就是上面给出了定义

        sigmod多用在二分类的最后一层激活函数里,他是一个非线性的激活函数。

        正是因为导数接近于0,所以会导致 梯度消失 的现象,关于梯度消失和爆炸,现在下一节反向传播会一起讲到(知识点要成块)

2.2 tanh

        tanh相当于sigmod的平移:他的函数表达式和图像(左图):

f(x) = \frac{1-e^{-2x}}{1+e^{-2x}}

         tanh的导数以及他的导数图像(上右图):

f'(x) = 1-f^2(x)

        这么一看sigmod和tanh都是饱和函数,都会导致梯度消失问题,都是一个非线性的激活函数

        但和sigmod相比,tanh的输出是[-1,1] 而sigmod的输出是[0.1],前者输出的均值是0,后者不是,所以后者会对线性组合的结果的做一定的分布漂移。这就对网络不太好了。

2.3. Relu(线性整流函数,Rectified Linear Unit)

        为了解决梯度消失的问题,于是就诞生出了线性整流函数。

        他的表达式以及图像长这个样子:

f(x) = max\left \{ 0,x \right \}

         Relu的导数以及图像:

f'(x) = \left\{\begin{matrix} 1 & x > 0 \\ 0 & x \leq 0 \end{matrix}\right.

         通过图像,我们可以看出导数值不会再是一个很小很小的值了,而是直接等于0,要么直接等于1(自己),从而解决了梯度消失的问题

        但正因为这个直接等于0,导致出现神经元死亡的问题。如果relu的输入是一个负数,那么会被映射到0,也就是说,后面不管有多少个神经元,但凡更新的时候和这个神经元沾边了,就都永远为0,且在之后也不被任何数据激活。不对任何数据产生响应,换句话说,导致神经元不可逆的按照一定比例地死亡,从而导致这个神经元的梯度不会更新,提供了网络的稀疏表达能力。

        但是和sigmod,tanh相比,这个Relu也有优点的:

        1. sigmod和tanh都是指数函数,计算量会非常大,而Relu只是卡一个阈值,大大减少了计算的复杂性。

        2. Relu是一个非饱和函数,解决了梯度消失的问题

        3. Relu的单侧抑制提供了网络的稀疏表达能力

 

2.4. ELU(指数线性单元)

        为了解决这个神经元死亡问题,于是就对Relu做了改善,引出了新的ELU

        ELU函数表达式以及图像长这样:

f(x) = \left\{\begin{matrix} x & x>0\\ \alpha(e^x-1) & x<0 \end{matrix}\right.

         这是他对应的导函数表达式以及图像:

f'(x) = \left\{\begin{matrix} 1 & x>0 \\ f(x)+\alpha & x\leq 0 \end{matrix}\right.

         可以从图上看出,其实ELU当x小于0的部分稍微沉下来了点儿,以此来避免神经元死亡问题,但其实还是不能完全避免,还是有一部分存在的。

        但是里面却包含了指数运算,所以对应的计算速度相比于Relu还是要慢的,并且这个alpha值是人为设定的,并不是网络自己学习。

2.5. Leaky Relu

        他的数学表达式以及图形长这样:

f(x) = \left\{\begin{matrix} x & x>0\\ \alpha x & x \leq 0 \end{matrix}\right.

        求导后的数学表达式以及图形:

f'(x) = \left\{\begin{matrix} 1 &x > 0 \\ \alpha & x \leq0 \end{matrix}\right. 

         这个相比于ELU,就完全避免了神经元死亡的问题了,同时还减少了指数函数的复杂计算量

        但是这个alpha 也是我们认为自己设定的,经验值

2.6. SELU 扩展型指数线性单元激活函数

        对应的表达式以及图形:

f(x) = \lambda\left\{\begin{matrix} x & x>0\\ \alpha e^x-\alpha & x\leq 0 \end{matrix}\right.

         f'(x) = \lambda\left\{\begin{matrix} 1 & x>0 \\ \alpha e^x & x\leq0 \end{matrix}\right.

         其中,lambda 和alpha 两个值都是给定的

        其中最主要的作用就是:寻找一个激活函数,使得神经元输出的激活值 a 也满足均值为零,方差为 1从而避免梯度爆炸和梯度消失。

        但是好像太难了,看不懂啊大佬,但我知道这个函数应该很牛逼,怎么输出都是mean=0,variance=1,和batch normalization的作用就非常像了。

2.7. GELU

        这个激活听说也是非常极其重要:

图片

在神经网络的建模过程中,模型很重要的性质就是非线性,同时为了模型泛化能力,需要加入随机正则,例如dropout(随机置一些输出为0,其实也是一种变相的随机非线性激活), 而随机正则与非线性激活是分开的两个事情, 而其实模型的输入是由非线性激活与随机正则两者共同决定的。

GELUs正是在Relu系的激活函数中引入了随机正则的思想,是一种对神经元输入的概率描述,直观上更符合自然的认识,同时实验效果要比Relus与ELUs都要好。

它们都希望将「不重要」的激活信息规整为零。我们可以理解为,对于输入的值,我们根据它的情况乘上 1 或 0。更「数学」一点的描述是,对于每一个输入 x,其服从于标准正态分布 N(0, 1),它会乘上一个伯努利分布 Bernoulli(Φ(x)),其中Φ(x) = P(X ≤ x)。

随着 x 的降低,它被归零的概率会升高。对于 ReLU 来说,这个界限就是 0,输入少于零就会被归零。这一类激活函数,不仅保留了概率性,同时也保留了对输入的依赖性。

我们可以理解为,对于一部分Φ(x),它直接乘以输入 x,而对于另一部分 (1 − Φ(x)),它们需要归零。不太严格地说,上面这个表达式可以按当前输入 x 比其它输入大多少来缩放 x

3. 反向传播 

        首先定义好第l层的参数W^l,b^l 每一层的线性变换就是z^l = W^lx^l+b^l,用上激活函数后:a^l = f(z^l),而这里的a^l作为下一层L+1的input。

        然后第L-1层的第K神经元连接第L层里面的第J个神经元的权重w^l_{kj}

        第L层的第J个神经元的bias就是b^l_j

        激活函数就是:\sigma(x)

        我们定义损失函数C关于第L层的第J个神经元的偏导数(误差)为:

        \frac{\partial C}{\partial z_j^l} = \delta ^l_j

        于是,开始啦!先看第L-1层单个神经元的偏导

        \delta^{l-1}_j = \frac{\partial C}{\partial z^{l-1}_j} = \frac{\partial C}{\partial a^{l-1}_j}\frac{\partial a^{l-1}_j}{\partial z_j^{l-1}} = \frac{\partial C}{\partial a^{l-1}_j}*\sigma'(z_j^{l-1})

        再看第L层,为什么看第L层呢,因为前向传播的时候第L-1层的第J个神经元对第L层的神经元产生了影响(就是累加了)假设第L层有K个神经元

        \delta^{l-1}_j = \frac{\partial C}{\partial z_j^{l-1}} = \sum^K_{k=1} \frac{\partial C}{\partial a_k^l}\frac{\partial a_k^l}{\partial z_k^l}\frac{\partial z_k^l}{\partial a_j^{l-1}}\frac{\partial a_j^{l-1}}{\partial z_j^{l-1}}

= \sum^K_{k=1}\delta^l_k*\frac{\partial z_k^l}{\partial_j^^{l-1}}*\sigma'(z_j^{l-1})

= \sum^K_{k=1}\delta^l_k*w^l_{kj}\sigma'(z_j^{l-1})

        于是,损失函数对参数的梯度可以写出来了:

\frac{\partial C}{\partial w_{jk}^l} = \frac{\partial C}{\partial z^l_{j}}\frac{\partial z_j^l}{\partial w_{jk}^l} = \delta^l_j*a_k^{l-1}

\frac{\partial C}{\partial b_j^l} = \frac{\partial C}{\partial z_j^l}\frac{\partial z_j^l}{\partial b^l_j} = \delta_j^l

        于是有

        W_{ij}^l = W_{ij}^l -\alpha\frac{\partial C}{\partial w_{ij}^l}

b_{i}^l = b_{i}^l -\alpha\frac{\partial C}{\partial b_{i}^l}

3.1 梯度消失 and 梯度爆炸

        当我们用sigmod去做激活的时候,上面不是提到了会导致梯度消失嘛,就是怎么样的呢,这里就借助反向传播刚好一并讲了:

        根据上面的公式:我们得知每一个权重更新都离不开 \delta ,又有:

        \delta_j^{l-1}= \sum^K_{k=1}\delta^l_k*w^l_{kj}\sigma'(z_j^{l-1})

        此时我们看上式,后面带有一个对激活函数的求导,这里当x非常大或者非常小,sigmod的导数就会无限接近于0,从而导致整个权重的更新变得非常缓慢。这就引起了梯度消失的问题。

        如果这个激活函数的导数值非常大,那么就会引起梯度爆炸的问题,特别是当层非常深,即使这激活函数的输出是1.1 然后有100层,那梯度也会变得非常大,导致来回跳跃了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值