神经网络硬科普,非专业出身的福利

kennyliu 8年前
   <p>最近“神经网络”非常火,各种关于神经网络的文章满天飞,但可能对于非专业领域出身的人来说接触这些文章就会云里雾里了。究其原因主要是缺少适合大部分人理解的神经网络的科普文章,其实吴军老师的《数学之美》在科普神经网络这方面做的就比较通俗易懂,感兴趣的朋友可以去读一下吴老师的书。本文与吴老师的讲解方式不同,笔者希望能从神经网络的起源揭开神经网络的面纱,从而帮助更多的对神经网络感兴趣但却没有相关理论基础的朋友们。</p>    <p>说起人工神经网络的起源肯定要追溯到生物的神经网络。</p>    <p>具体总结一下就是,神经元细由一个细胞体、一些树突、一根轴突及许多突触组成。神经细胞体是神经元的主体,内含细胞核。树突是从细胞体向外延伸出许多神经纤维,用来接收来自其它神经元的输入信号。轴突通过分支的神经末梢向外发出信号,与其他神经细胞的树突相接触形成所谓的突触。下图是人脑中的神经元细胞,大家可以对应神经元细胞图着再理解一下。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/b1407bd42671635785f8eae3450230fb.jpg"></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/c29deeff526a95283e5fda67322a225a.jpg"></p>    <p>为了便于大家对应理解人工神经网络,这里再分别总结一下神经元细胞重要组成部分的特点:</p>    <p>1.树突、轴突、突触分别相当于细胞体的输入端、输出端及输入/输出接口(I/O),并且多输入单输出;</p>    <p>2.兴奋型和抑制型突触决定神经细胞兴奋和抑制(分别对应输出脉冲串频率高低),其中脉冲串代表神经元的信息;</p>    <ol>     <li> <p>细胞体膜内外电位差(由突触输入信号总和)的升高超过阈值产生脉冲,神经细胞进入兴奋状态;</p> </li>     <li> <p>突触延迟使输入与输出间有固定时滞。</p> </li>    </ol>    <p>开始进入人工神经网络的分割线</p>    <p>1943年,基于生物神经网络莫克罗-彼特氏神经模型(McCulloch-Pitts′neuronmodel)诞生。它由心理学家Warren McCulloch和数学家Walter Pitts合作提出。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/e2b2499ee42ab4ce18a25b689ef69b66.jpg"></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/7df0dcfef7c21f5e2973418c751b70b1.jpg"></p>    <p>McCulloch-Pitts模型的基本思想是抽象和简化生物神经元的特征性成分。这个模型不需要捕捉神经元的所有属性和行为,但要足以捕获它执行计算的方式。McCulloch-Pitts模型的6个特点中前面4点和之前总结的生物神经元一致,具体对应请见下图:</p>    <p>1.每个神经元都是一个多输入单输出的信息处理单元;</p>    <p>2.神经元输入分兴奋性输入和抑制性输入两种类型;</p>    <p>3.神经元具有空间整合特性和阈值特性;</p>    <p>4.神经元输入与输出间有固定的时滞,主要取决于突触延搁;</p>    <p>5.忽略时间整合作用和不应期;</p>    <p>6.神经元本身是非时变的,即其突触时延和突触强度均为常数。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/3690bfe9c5dc844f826f4448b252bc3f.png"></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/b23118d208a7c1372d8d112cfc6d328f.png"></p>    <p>McCulloch-Pitts模型公式如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2a9047c5dab54b3427ca71540a431d98.png"></p>    <p><img src="https://simg.open-open.com/show/ff500501ad0d08ab4a2a07d7b415799f.png"></p>    <p>这项伟大的建模可了不得,从人的角度来看将颜色、形状分为两类只需要靠眼睛辨别,但是对于机器而言它能辨别只是一堆数据。如果平面上有两组数据(如下图所示),机器怎么把两组数据区分开,由图可见平面上的直线方程就可以数据分为两类,而Warren McCulloch和Walter Pitts所构建的人工神经元就是这么一个模型,它的实质就是把特征空间一切两半,认为两半分别属两个类。你恐怕再也想不到比这更简单的分类器了。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2f0bfe64e3d292280136d731f422d33f.png"></p>    <p>但是McCulloch-Pitts模型缺乏一个对人工智能而言至关重要的学习机制。因此这里还需要为大家普及一下“历史”。1949年唐纳德·赫布(DonaldHebb)称知识和学习发生在大脑主要是通过神经元间突触的形成与变化,这个出人意料并影响深远的想法简称赫布法则:</p>    <p>当细胞A的轴突足以接近以激发细胞B,并反复持续地对细胞B放电,一些生长过程或代谢变化将发生在某一个或这两个细胞内,以致A作为对B放电的细胞中的一个效率增加。</p>    <p>通俗来讲就是两个神经细胞交流越多,它们连接的效率就越高,反之就越低。罗森布拉特(Frank Rosenblatt)受到赫布基础性工作的启发,于1957年提出了"感知器" (Perceptron)。这是第一个用算法来精确定义神经网络的,感知器由两层神经元组成,输入层接收外界信号,输出层是McCulloch-Pitts神经元,即阈值逻辑单元。</p>    <p>1969 年,Marvin Minsky和Seymour Papert出版了新书《感知器:计算几何简介》。书中论证了感知器模型的两个关键问题:其一,单层的神经网络无法解决不可线性分割的问题,典型例子如同或(XNOR,两个输入如果相同,输出为1;两个输入如果是不同,输出为0。)其二,受硬件水平的限制,当时的电脑完全没有能力完成神经网络模型所需要的超大的计算量。</p>    <p>在此笔者就以单层神经元为例解释人工神经元是如何工作的。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/350e3302d6ad5fa6439fff7fd8bc2bd1.png"></p>    <p>x1,x2,…, xN:神经元的输入。这些可以从输入层实际观测或者是一个隐藏层的中间值(隐藏层即介于输入与输出之间的所有节点组成的一层。帮助神经网络学习数据间的复杂关系。大家不理解没关系,后面讲到多层神经网络是会再跟大家解释的)。</p>    <p>X0:偏置单元。这是常值添加到激活函数的输入(类似数学里y=ax+b中使直线不过原点的常数b)。即截距项,通常有+1值。</p>    <p>w0,w1,w2,…,wN:对应每个输入的权重。甚至偏置单元也是有权重的。</p>    <p>a:神经元的输出。计算如下:</p>    <p><img src="https://simg.open-open.com/show/12631ebe42a361c7a7e4c62db09d363c.png"></p>    <p>需要解释一下的是,式子里的f是已知的激活函数,f使神经网络(单层乃至多层)非常灵活并且具有能估计复杂的非线性关系的能力。在简单情况下可以是一个高斯函数、逻辑函数、双曲线函数或者甚至上是一个线性函数。利用神经网络可让其实现三个基本功能:与、或、非(AND, OR, NOT)。</p>    <p>这里介绍一个基本的f函数,其实就是我们熟知的阶跃函数:</p>    <p><img src="https://simg.open-open.com/show/4a61c98491037c231c3924c5c9596981.png"></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/1f98a974fbbb8a0edd62d29f864b9497.png"></p>    <p>例1:and功能实现如下:**</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2699ff67ce962337416b3211396bf256.png"></p>    <p>神经元输出:a = f( -1.5 + x1 + x2 )</p>    <p>真值表如下,可见列“a”与列“X1 AND X2”一致:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4c7f7c4c696cde5e2ca6326e3da203f4.png"></p>    <p>例2:or功能实现如下:**</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/34b69268a19d4cbe2dc473c3e70037d6.jpg"></p>    <p>神经元输出为:</p>    <p>a = f(-0.5 + x1 + x2 )</p>    <p>真值表如下,其中列“a”与“X1 OR X2”一致:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/da184512153dc008530f82c019399675.png"></p>    <p>通过例1和例2我们可以看到,只要改变偏置单元的权重,我们就可以实现or功能。如果x1或x2任何一个为正则权重总值为正。</p>    <p>例3:not功能实现如下:**</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/a1977da43db8fab2c08224e06672e0ee.jpg"></p>    <p>神经元输出为:a = f( 1 - 2 * x1 )</p>    <p>真值表如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/9144eedb4aefb18abac5df46abb5cf9b.png"></p>    <p>笔者希望通过这些例子大家能直观的理解一个神经元在神经网络中是如何工作的。当然神经网络中的函数有多种选择,除了以上例子所用的函数,这里我们再介绍一种常用的函数——sigmoid函数,帮助大家灵活的理解。函数图像如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4496ae737afb67832b28a3eddaa13762.png"></p>    <p>由图可见sigmoid函数的优点在于输出范围有限,所以数据在传递的过程中不容易发散,并且其输出范围为(0,1),可以在输出层表示概率。当然其也有相应的缺点,就是饱和的时候梯度太小。大家可以对应下面的and例子理解一下。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/7a0aa969c9d8e1bb7d6fd829ac24d930.png"></p>    <p>之前我们看到的例子中与、或、非功能都是线性可分的,感知器只有输出层神经元进行激活函数处理,即只拥有一层功能神经元,学习能力非常有限(这就是本文之前提到的感知器模型关键问题之一)。因此非线性可分要用到多层神经元,下面笔者先介绍一下多层神经网络。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/75cceff5ce53d9aae24751775c8a7285.png"></p>    <p>神经网络分为三种类型的层:</p>    <p>输入层:神经网络最左边的一层,通过这些神经元输入需要训练观察的样本。</p>    <p>隐藏层:介于输入与输出之间的所有节点组成的一层。帮助神经网络学习数据间的复杂关系。</p>    <p>输出层:由前两层得到神经网络最后一层。5个分类的情况下输出层将有5个神经元。</p>    <p>为什么多层网络是有用的?下面大家试着去了解神经网络如何用多层来模拟复杂关系。要进一步理解这个,需要举一个同或函数的例子。其真值表如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/63ed23cd64e558b6bfd4b7a7b9663f12.png"></p>    <p>这里我们可以看到当输入都相同时,输出为1,否则为0。这种关系不能由一个神经元独立完成,因此需要一个多层网络。使用多层的背后思想是:复杂关系功能可以被分解为简单的功能及其组合。让我们分解同或函数:</p>    <p>X1 XNOR X2 = NOT ( X1 XOR X2 )</p>    <p>= NOT [(A+B).(A'+B') ]</p>    <p>= (A+B)'+ (A'+B')'</p>    <p>=(A'.B') + (A.B)</p>    <p>(注意: 这里符号“+”代表或 ,符号“.”代表与,符号“'”“-”代表非)</p>    <p>这样我们可以用之前讲解的简单的例子实现。</p>    <p>方法1: X1 XNOR X2 = (A’.B’) + (A.B)</p>    <p>设计神经元模拟A’.B’是一项挑战,可通过以下实现:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2305ffe9ce3d323bcaa3ce93b874b086.png"></p>    <p>神经元输出:a = f( 0.5 – x1 – x2 )</p>    <p>真值表为:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4aa0dc31781bddf050b9163600af9a83.png"></p>    <p>现在,大家可以分别把A’.B’和A.B当作两个独立的部分,并结合为多层网络。网络的语义图如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/04fc1ce8b3ae61ff794c6a418c27b4ff.jpg"></p>    <p>在这里大家可以看到,在第一层,我们分别确定A’.B’和A.B。在第二层,我们将输出并且在顶部实现OR功能。最后整体的网络实现如下图所示:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/f5ab1053d1ae98a8eaf5bdbb2ee0a313.png"></p>    <p>大家仔细看会发现这不过是我们之前画的神经元的组合:</p>    <p>a1:实现了A’.B’;</p>    <p>a2:实现了A.B;</p>    <p>a3:建立在a1和a2上实现OR,从而有效的实现(A’.B’ + A.B)。</p>    <p>通过真值表验证其功能:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/08dd273e4e16459068368f2957e2228f.png"></p>    <p>现在大家应该大概能直观地理解多层网络是如何工作的了。在上面的例子中,我们不得不分别计算A’.B’和A.B。如果我们想仅仅是基于基本的AND, OR, NOT函数实现同或功能的话,大家请看下面的方法2。</p>    <p>方法2: X1 XNOR X2 = NOT[ (A+B).(A’+B’) ]</p>    <p>这里我们用之前分解的第二步得到的式子来实现,网络的语义图如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/85571f736d756120625580380cb69e54.png"></p>    <p>大家可以看到在这里神经网络不得不使用三个隐藏层。整体网络的实现和我们之前所做的相似:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/ef07071a4cb3dfe43e6a850e4633f456.png"></p>    <p>a1:等同于 A ;</p>    <p>a2:实现了 A’;</p>    <p>a3:等同于 B ;</p>    <p>a4:实现了 B’;</p>    <p>a5:实现了OR, 实际上是 A+B ;</p>    <p>a6:实现了OR, 实际上是 A’+B’;</p>    <p>a7:实现了AND, 实际上是(A+B).(A’+B’) ;</p>    <p>a8:实现了NOT, 实际上是 NOT [ (A+B).(A’+B’)],即最终XNOR的输出</p>    <p>真值表如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/29d9155a663fb2523de371434711afe5.png"></p>    <p>注意:典型的一个神经元(除了偏置单元)为下一层的每个神经元提供数据。在这种情况下,我们已经避免了从第一层到第二层的几个连接,这是因为它们的权重是0,并且加入它们容易影响大家清晰的理解神经元间的计算。所以这里没有画成下图这种:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/526199828ad411f174954f87277d67a4.png"></p>    <p>可见方法2我们成功的实现了同或功能,方法2的思想是如何将复杂的函数分解为多个层。但这种方法比方法1更复杂,因此大家应该会更喜欢方法1。</p>    <p>笔者之前学习神经网络时也是看了很多资料,有些资料讲的云里雾里的。笔者希望大家阅读本文后能少走弯路,理解神经网络。最后,引用吴老师书中的话做结尾:“有不少专业术语乍一听很唬人,‘人工神经网络’就属于这一类,至少我第一次听到这个词就被唬住了。你想啊,在大家的印象当中,人们对人脑的结构都还根本没有搞清楚,这就冒出来一个‘人工的’神经网络,似乎是在用计算机来模拟人脑。想到人脑的结构那么复杂,大家的第一反应一定是人工神经网络肯定非常高深。如果我们有幸遇到一个好心同时又善于表达的科学家或教授,他愿意花一两个小时的时间,深入浅出地把人工神经网络的底细告诉你,你便会发现,‘哦,原来是这么回事’。如果我们不幸遇到一个爱卖弄的人,他会很郑重地告诉你‘我在使用人工神经网络’或者‘我研究的课题是人工神经网络’,然后就没有下文了,如此,你除了对他肃然起敬外,不由得可能还会感到自卑。当然还有好心却不善于表达的人试图将这个概念给你讲清楚,但是他用了一些更难懂的名词,讲得云山雾罩,最后你发现听他讲了好几个小时,结果是更加糊涂了,你除了浪费时间外一无所获,于是你得出一个结论:反正我这辈子不需要搞懂它了。</p>    <p>大家可别以为我是在说笑话,这些都是我的亲身经历。首先,我没有遇到过一两小时给我讲懂的好心人,其次我遇到了一批在我前面卖弄的人,作为年轻人,总是希望把自己不明白的东西搞懂,于是我决定去旁听一门课。不过,我听了大约两三次便不再去了,因为除了浪费时间,似乎我并没得到什么收获。好在我自己做研究暂时用不到它,也就不再关心了。后来在美国读博士期间,我喜欢在睡觉前躺着看书,没事儿就捧着几本关于人工神经网络的教科书在床上看,居然也看懂了。然后再用它做了两三个项目,算是学会了。到这时回过头来再看‘人工神经网络’,其实并不复杂,入门也不难,只是我走了弯路。”</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/078bba15fdb0</p>    <p> </p>