我们在设计机器学习系统时,特别希望能够建立类似人脑的一种机制。神经网络就是其中一种。但是考虑到实际情况,一般的神经网络(BP网络)不需要设计的那么复杂,不需要包含反馈和递归。
人工智能的一大重要应用,是分类问题。本文通过分类的例子,来介绍神经网络。
1.最简单的线性分类
一个最简单的分类,是在平面上画一条直线,左边为类0,右边为类1,直线表示为
这是一个分类器,输入(x,y),那么,要求的参数有三个:a,b,c。另外注意c的作用,如果没有c,这条直线一定会过原点。
因此,我们可以设计一个简单的神经网络,包含两层,输入层有三个节点,代表x,y,1,三条线分别代表a,b,cg(z)对传入的值x进行判别,并输出结果。
![](https://i-blog.csdnimg.cn/blog_migrate/338f1055a1334c1905f870a568a87557.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0d4dda0f8cd5fec324739215178bde5f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/45955df936cd89e726ae226df87cb8e4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8b2cb2b2ca0937287acbf1eaa98410c9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0d4dda0f8cd5fec324739215178bde5f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/becd78c0944b08d714432cd4e150ec6d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f94e120c029d77526fd319dfdc9981c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/becd78c0944b08d714432cd4e150ec6d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8b2cb2b2ca0937287acbf1eaa98410c9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0d4dda0f8cd5fec324739215178bde5f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e98ebe837d1fd8126c2c39c9823aa305.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f94e120c029d77526fd319dfdc9981c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e98ebe837d1fd8126c2c39c9823aa305.png)
但是,由于z的值可能为[
![](https://i-blog.csdnimg.cn/blog_migrate/caec8a25c90cc1c44dc58bc6e8a65c8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/22a73d9d60578044c27c563965713c84.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e65772aa812105ef8508cf64d1fd482d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8b2cb2b2ca0937287acbf1eaa98410c9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/22a73d9d60578044c27c563965713c84.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8e674a5a2981c286f31fb8bd325d43ff.png)
![](https://i-blog.csdnimg.cn/blog_migrate/76dccd98123055d17b6c35c314e81901.png)
![](https://i-blog.csdnimg.cn/blog_migrate/338f1055a1334c1905f870a568a87557.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d733635b0594e601d4728551240d3d44.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c56dad2551f4e96aff4fd10e80e4d74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c56dad2551f4e96aff4fd10e80e4d74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/caec8a25c90cc1c44dc58bc6e8a65c8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/82548a8215e7d4e4e1027a9769b8cded.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0937562ac377136e6edbe66f8f43aba8.png)
这样的激励函数,能够将刚才的区间,压缩到
![](https://i-blog.csdnimg.cn/blog_migrate/810d6f5b4a3982dff54f17887337e9a1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/10cba0ffe69cd900c24c5299a8d08feb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e65772aa812105ef8508cf64d1fd482d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c56dad2551f4e96aff4fd10e80e4d74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d3f843a526a3ad43f0d1414ee2615c93.png)
至于如何训练,会在之后的章节中讲解。
2.多层级神经网络
刚才展示了最简单的二分类,如果有四个分类,那一条线就无法满足要求了。想象两条直线,就会将平面划分为四个区域,一个三角区域相当于两个子平面求交集。
因此直觉告诉我们,如果有多个神经元,那么这样的问题能表现为问题的“逻辑与”操作。将第一节中介绍的神经网络的输出,再做一个判断层,即多层网络。
但是,如何实现逻辑与呢?用下面的图一目了然:
仔细看下,这相当于创建一条线,除非
和
都等于1,否则
。
进一步地,如果我们能够对区域求并集,那么总可以对不同的子区域求并。而实现并操作和与操作是类似的:
此处就能看到sigmoid函数的作用了,如果没有它对数值的放缩,并和与的操作就无法实现了。
输出还能作为下一级的输入,从而增加了一个隐层,产生了单隐层神经网络,再复杂一些,如果网络层数特别多,则叫做深度学习网络,简称深度学习。
之前针对一个线性不可分的区域,需要将其变换到更高维度的空间去处理。但如果用神经网络,你总可以通过n条直线,将整个区间围起来。只要直线数量够多,总能绘制出任意复杂的区域。每一个子区域都是凸域:
简直不能更酷!下面这张图总结了不同类型的神经网络具备的功能:
数学家证明了,双隐层神经网络能够解决任意复杂的分类问题。但我们的问题到此为止了吗?不见得!
这里还有几个问题:
- 异或如何实现?异或肯定是不能通过一条直线区分的,因此单层网络无法实现异或,但两层(包含一个隐层)就可以了。
- 过拟合问题:过多的隐层节点,可能会将训练集里的点全部围进去,这样系统就没有扩展性了。如何防止过拟合?
- 如何训练:如何计算出合理的神经网络参数?(隐层节点数)
3.如何训练神经网络
如果一个平面,有6个点,分成三类。如何设计呢?
一种最狂暴的方法,是对每一个点都用四条线围起来,之后,再对六个区域两两取并集。形成下面这张超复杂的图:
解释一下为什么要有这么多个节点:
第一层:x,y再加bias,三个
第二层:每个点需要四条线围起来,加上bias,总共4*6+1=25个
第三层:一个节点处于该类的条件是在四条线的中间(交集),因此每四个点汇成一个点,24/4+1=7个
第四层:三分类问题,需要对每两个区域求并集,因此需要6/2+1=4个
但这样的解法,使用了3+25+7+4=39个节点,需要111个参数。这样的系统非常复杂,对未知节点几乎没有任何扩展性。
仔细思考这个问题, 我们能够通过更少的节点和层数,来简化这个问题嘛?只要三条直线就可以!节点数量大大减少。不仅训练效率更高,而且可扩展能力很强。对更复杂的例子,我们又不是神仙,怎么知道设计几个隐层和多少个节点呢?
所谓超参数,就是模型之外的参数,在这个例子中,就是隐层的数量和节点的数量。通常来说,线性分类器(回归)只需要两层即可,对于一般的分类问题,三层足够。
一个三层的神经网络,输入和输出节点的数量已经确定,那如何确定中间层(隐层)的节点数量呢?一般有几个经验:
- 隐层节点数量一定要小于N-1(N为样本数)
- 训练样本数应当是连接权(输入到第一隐层的权值数目+第一隐层到第二隐层的权值数目+...第N隐层到输出层的权值数目,不就是边的数量么)的2-10倍(也有讲5-10倍的),另外,最好将样本进行分组,对模型训练多次,也比一次性全部送入训练强很多。
- 节点数量尽可能少,简单的网络泛化能力往往更强
- 确定隐层节点的下限和上限,依次遍历,找到收敛速度较快,且性能较高的节点数
如何表示一个神经网络?网络有m层,每层的节点分别为
,节点最多的层,有m个节点,那么我们可以将其表达为一个矩阵W,规模为
,内部有些值是没有定义的。
4.训练算法
线性可分
如果输入和输出是线性关系(或者是正相关),那么想象我们在调节一个参数时,当输出过大,那就把输入调小一些,反之调大一些,最后当输出和我们想要的非常接近时,训练结束。这个就好比,在平面上,如果一个点被分配到了错误的输出,就应该对直线平移和扭转,减少该直线到这个点的距离,从而实现重新分区。
进一步地,如果向量的多个分量互相独立,那么方法也和上面的类似
,分别调节
和
的参数,最终让结果接近,训练结束。
而一个感知器结构可表示如下:
反思上面的过程,我们实际上是在衡量误差,根据误差来修改权重。
线性不可分
如果输入和输出的关系比较复杂,如二次函数
,那当超过x=0的位置之后,反而成了递增了,此时一个线性的判断函数就不起作用了。因此,上面的方法,不能推广到所有的前馈网络中。
怎么办?那就只能使用梯度(LMS)法了。
梯度法,是对于样本集
,找到一个
,使得
与输出
尽可能接近,其中
是激励函数。误差表示为:
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c56dad2551f4e96aff4fd10e80e4d74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/00911c28641048c64f52ff1846062d6a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7c22319837200c06e760053654df8df9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ec30adfc9d2be6b536dd717474e1fc1d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/326a7db216f91e224114472bc45873f3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/becd78c0944b08d714432cd4e150ec6d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/29f5a7b88dc02ac269fa1ed57cf03aff.png)
![](https://i-blog.csdnimg.cn/blog_migrate/76dccd98123055d17b6c35c314e81901.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9afec4583e5367e89dc9e4f2b97443f6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ec30adfc9d2be6b536dd717474e1fc1d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/caec8a25c90cc1c44dc58bc6e8a65c8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9afec4583e5367e89dc9e4f2b97443f6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1a7d60759fd2041ac3412bf6e5fb16a7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ec30adfc9d2be6b536dd717474e1fc1d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d733635b0594e601d4728551240d3d44.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e98ebe837d1fd8126c2c39c9823aa305.png)
为了能够调节误差e,使之尽可能小,则需要求其导数,发现其下降的方向:
![](https://i-blog.csdnimg.cn/blog_migrate/7bc68beb72b8b4ef8fda61133418b57c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a99f5272920c4b42a20094c49103757d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8e674a5a2981c286f31fb8bd325d43ff.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b3c532ab0fba44e613f92882b4a75959.png)
![](https://i-blog.csdnimg.cn/blog_migrate/634a0db55638c6736e25334de145c536.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d3ccfeb91802fd660c57a5495e99d0dd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d3ccfeb91802fd660c57a5495e99d0dd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f57800d76e05bffa76e7aa7526b0857d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7c22319837200c06e760053654df8df9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/326a7db216f91e224114472bc45873f3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/becd78c0944b08d714432cd4e150ec6d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/29f5a7b88dc02ac269fa1ed57cf03aff.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d3ccfeb91802fd660c57a5495e99d0dd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d3ccfeb91802fd660c57a5495e99d0dd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f57800d76e05bffa76e7aa7526b0857d.png)
其中:
![](https://i-blog.csdnimg.cn/blog_migrate/bea4967978e15bb3abb50a286d5ef68e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f77ee0e67bf691be5bd110737181ae6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c56dad2551f4e96aff4fd10e80e4d74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/00911c28641048c64f52ff1846062d6a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/76dccd98123055d17b6c35c314e81901.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9afec4583e5367e89dc9e4f2b97443f6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/caec8a25c90cc1c44dc58bc6e8a65c8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9afec4583e5367e89dc9e4f2b97443f6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/82548a8215e7d4e4e1027a9769b8cded.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d733635b0594e601d4728551240d3d44.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e98ebe837d1fd8126c2c39c9823aa305.png)
对偏导进行求解:
每次迭代的计算公式为:
最终:
其几何意义就是,误差的偏导,等于在
![](https://i-blog.csdnimg.cn/blog_migrate/f94e120c029d77526fd319dfdc9981c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55175c8cabe82ad9604878679e9161a2.png)
所以,每次的权重矩阵
![](https://i-blog.csdnimg.cn/blog_migrate/f57800d76e05bffa76e7aa7526b0857d.png)
但是,这样的梯度法,对于实际学习来说,效率还是太慢,我们需要更快的收敛方法。
BP算法
BP算法就是所谓的反向传播算法,它将误差进行反向传播,从而获取更高的学习效率。这很像烽火台,如果前线战败了,那么消息就通过烽火台传递回指挥部,指挥部去反思问题,最终改变策略。
但这带来一个问题,中间层的误差怎么计算?我们能简单地将权重和残差的乘积,返回给上一层节点(这种想法真暴力,从左到右和从右到左是一样的)。
这相当于三次传播:
-第一步:从前向后传播FP
-第二步:得到值z,误差为y,将误差反向传播,获得每个节点的偏差$\sigma$
-第三步:再次正向传播,通过上一步的$\sigma$,再乘以步长,修改每一个神经元突触的权重。
下面一张图展示了完整的BP算法的过程,我看了不下20遍:
更有趣的是,sigmoid求导之后,特别像高斯(正态)分布,而且sigmoid求导非常容易。
5.总结
这样的一篇文章真是够长了,原本还想再介绍一个神经网络的Python实现,可是考虑到篇幅的限制,最终作罢。在下一期继续介绍如何实现BP神经网络和RNN(递归神经网络)。