神经网络和深度学习(四) ——浅层神经网络的激活函数与反向传播

神经网络和深度学习(四)——浅层神经网络的激活函数与反向传播

(原创内容,转载请注明来源,谢谢)

一、神经网络的表示

复习一下神经网络的表示,其主要是将单层的多个神经元,整合到一个矩阵中,调用numpy提供的函数,一次性进行运算。

下面的例子中,先不考虑b,把w、x都拆成一系列的列向量的集合,可以看出最终的wx的值。如果要考虑到b,则在加上b即可。

向量化计算,便利之处,就在于不用for循环,可以直接计算出结果,对于神经元非常多的神经网络的计算,这样速度快很多。

二、激活函数

1、概述

之前一直用到的激活函数,是sigmoid函数,即1/(1+e-z)。实际上,除了这个激活函数,还有其他几种激活函数,图像如下图所示:

1)sigmoid

g(z)=1/(1+e-z),其结果在0~1之间,且在z非常大或非常小时,比较平缓,z=0时g(0)=0.5。对其求导,可以得出g’(z)=g(z)*(1-g(z)),由于g(z)=a,即g’(z)=a*(1-a)。

这里计算导数,是为了后面推导反向传播算法做铺垫。

可以看到,sigmoid的导数,在z很大或很小时,为0,这就是其的一大缺点,在z的值很大或很小时,导数小,导致优化学习速度较慢。

但是其的优点很明显,可以将结果控制在0~1,故经常用在输出层。

2)tanh

g(z)=(ez - e-z)/( ez +e-z),该函数除了结果在-1~1分布,整个图像和sigmoid非常像。但是由于其在-1~1分布,故其函数的平均值是0,可以达到中心化的效果。在没有要求分类结果一定要是0和1时,通常都用tanh来取代sigmoid。

另外,g’(z)=1- (g(z))2=1-a2。

3)ReLU和泄漏ReLU

当z>0,ReLU的g(z)=z,否则g(z)=0。这个函数有效的防止了sigmoid和tanh,在z非常大或者非常小时,导数太小导致优化速度太慢的问题,这里可以保证一个固定的优化速度,故优化速度较快。

泄漏的ReLU,就是在z小于0时,结果不是0,而是一个略微的负数,可以设置为0.01z,这样一定程度上可以保证在z小于0时,效果更好,但是这个函数不常用。

当z=0时,可以看出ReLU的导数不存在,但是对于z在整个实数区间,出现z=0的概率极低,因此可以把z=0时的导数,取分段函数任意一头的导数即可。泄漏的ReLU在z=0时的做法同ReLU。

ReLU作为激活函数,非常常用,除了输出层,大部分情况下,都会用这个函数作为神经网络的隐藏层中的激活函数。甚至在需要线性回归,如房价预测等结果时,也会用到这个函数在输出层。

2、使用非线性激活函数的原因

如果使用线性激活函数,即g(z)=z,根据计算,会发现,最终多层的神经网络,会被简化层一层的线性回归的神经网络,这样就没有深度学习的效果了。

推导过程如下:

z1=w1x+b1,a1=z1(由于线性激活函数)èz2=w2a1+b2,a2=z2è将a1=z1=w1x+b1带入到z2=w2a1+b2,得到z2=w2*( w1x+b1)+b2=(w1w2)x+(w2b1+b2),可以看到两个括号里的内容,等同于还是wx+b的形式,这样就使多层神经网络失去多层的意义。

3、激活函数的使用

使用其实很简单,就是直接令g(z)等于上面的某种激活函数,进行计算和反向传播计算即可。

每一层的激活函数,可以设置的都不一样,来达到想要的效果。

通常,最后一层用sigmoid,以保证输出的结果在0~1,中间层用ReLU,以保证学习速率。但是具体应用,还需要根据实际需要来决定。

三、梯度下降

神经网络梯度下降的过程,实际上和logistic回归,以及其他机器学习的梯度下降的算法,思想是一样的。只不过由于其层次比较多,需要进行的梯度成为链式,因此被整合成反向传播算法。

首先看到,梯度下降来获取最优化情况下的各层w、b参数的具体步骤:1)正向计算出预测结果y以及代价函数J;2)反向求导,得到代价函数J对每一层w、b的导数;3)用上一次计算时的w、b,减去本次计算时的导数;4)不断重复1、2、3步骤。

具体前向传播和方向传播的公式如下,下图左边是前向传播的公式,右图是反向传播的公式(两层神经网络):

四、反向传播的推导

1、logistic的计算

先考虑logistics,其反向的运算,实际上就是先写出输出层的的运算结果a、实际结果y关于损失函数L函数,在对a求导。得到dl/da后,再往前,求dl/dz,由链式法则,dl/dz=dl/da * da/dz,再往前可以求得dl/dw和dl/db,然后在用w=w-αdl/dw,b=b-αdl/db,即完成单次运算的优化。

再重新计算l,再重新反向,多次以后,就得到最优化的结果。

2、双层神经网络

其实本质上,神经网络的bp运算,和上面logistic并没有什么区别。就是运算量的区别,以及链式求导的“链”更长了一些,其他是一样的。

要注意的是,每一层所有神经元总的运算结果,都是作为下一层的输入,因此,每一层都有对应的w、b需要优化。另外,链式求导是不需要计算dl/dx的,因为x是输入的样本,不可能改变其值,对其求导没有意义。

3、总的公式

反向传播,也可以用到向量化。如下图所示,左边是没有向量化的运算,需要对每一层的每个神经元进行计算;右边是向量化的运算,每一层只需要运算一次即可。

五、随机初始化

1、初始化为0存在的问题

还需要考虑一个问题,初始化问题。神经网络,初始化是不能设任何的w为0,否则会导致神经网络的完全对称性。

本质的原因,是z=wx+b,如果w设置成0,则z=b,那么输入样本就完全被消掉了,这样是不合理的。

考虑到二层神经网络,如果w1设置成0,则会导致a1的两个神经元,计算的结果完全一样,这样多个神经元就没有意义了。

2、随机初始化

解决方案,就是对所有的w,初始化的时候,都随机分配一个值,而不能设置成0。

3、注意事项

需要注意的是,随机初始化,是需要保证w被初始化的值较小。考虑到sigmoid或者tanh,由于z很大或很小时,导数太小,因此如果w太大,会导致z太大,进而导致导数太小。导数太小,会直接导致优化速度非常慢。

因此,可以初始化w的时候,可以乘以一个系数,如0.01,让其变得尽量小。对于这个系数的设置,后面的课程会学到。

另外,b初始化成0是可以的,因为b不是x的系数,其初始化的值不会把x的差距消除,因此可以初始化为0。

六、总结

本文主要讲到神经网络的激活函数、正向与反向传播算法,建议大家都去拿笔推导一遍,实际上就是链式求导法则,推导一次后基本就可以理解这个算法了。

非线性激活函数,是保证神经网络的多层之间都有作用的,因此不能用线性激活函数。另外激活函数会控制输出的范围,因此要根据实际情况选择激活函数。

随机初始化,是保证神经网络单层中,每个神经元都能起作用,因此不能把任意一层的w初始化为0。另外为了保证优化速度,初始化时,要保证w尽量小。

——written by linhxx 2018.02.02

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2018-02-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xingoo, 一个梦想做发明家的程序员

AOE关键路径

这个算法来求关键路径,其实就是利用拓扑排序,首先求出,每个节点最晚开始时间,再倒退求每个最早开始的时间。 从而算出活动最早开始的时间和最晚开始的时间,如果这两个...

2517
来自专栏开发与安全

算法:AOV网(Activity on Vextex Network)与拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex ...

2517
来自专栏拭心的安卓进阶之路

Java 集合深入理解(12):古老的 Vector

今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这么相...

2447
来自专栏刘君君

JDK8的HashMap源码学习笔记

3008
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-向量实现《数据结构与算法分析》

#include <iostream> #include <list> #include <string> #include <vector> #include...

1726
来自专栏聊聊技术

原 初学图论-Kahn拓扑排序算法(Kah

2878
来自专栏赵俊的Java专栏

从源码上分析 ArrayList

1171
来自专栏学海无涯

Android开发之奇怪的Fragment

说起Android中的Fragment,在使用的时候稍加注意,就会发现存在以下两种: v4包中的兼容Fragment,android.support.v4.ap...

3165
来自专栏java闲聊

JDK1.8 ArrayList 源码解析

当运行 ArrayList<Integer> list = new ArrayList<>() ; ,因为它没有指定初始容量,所以它调用的是它的无参构造

1192
来自专栏Java Edge

AbstractList源码解析1 实现的方法2 两种内部迭代器3 两种内部类3 SubList 源码分析4 RandomAccessSubList 源码:AbstractList 作为 Lis

它实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换

432

扫码关注云+社区