因为今天买的耳机到了,想玩游戏,懒得自己码字了,大部分都从书上粘过来,但是矩阵部分是必要重要的,因此需要彻底理解
虽然我们的计算机拥有大量的计算元件,有巨大的存储空间,而且这些元件的运行频率比生物大脑快很多,但是即便是像鸽子一样小的大脑,其能力也远超我们的计算机
科学家们发现,传统的计算机按照串行的顺序,相当准确的处理数据,对计算机而言不存在模糊与不准确性。而另一方面,生物大脑看上去以较慢的方式运行,但似乎是以并行的方式处理信号,模糊性是其计算的一种特征
让我们来观察生物大脑中的基本单元—神经元
虽然神经元有各种形式,但是所有的神经元都是将电信号从一端传输到另一端,沿着轴突,将电信号从树突传到树突。
然后,这些信号从一个神经元传递到另一个神经元。这就是身体感知光、声、触压、热等信号的机制。来自专门的感觉神经元的信号沿着神经系统,传输到大脑,而大脑本身主要也是由神经元构成的
因此,我们可以与以前一样,将神经元表示为线性函数吗?虽然这是个好主意,但是不可以这样做。生物神经元与简单的线性函数不一样,不能简单地对输入做出的响应,生成输出。也就是说,它的输出不能采用这种形式:输出=(常数*输入)+(也许另一常数)
观察表明,神经元不会立即反应,而是会抑制输入,直到输入增强,强大到可以触发输出。你可以这样认为,在产生输出之前,输入必须到达一个阈值。就像水在杯中—直到水装满了杯子,才可能溢出。直观上,这是有道理的—神经元不希望传递微小的噪声信号,而只是传递有意识的明显信号。下图说明了这种思想,只有输入超过了阈值(threshold),足够接通电路,才会产生输出信号
虽然这个函数接受了输入信号,产生了输出信号,但是我们要将某种称为激活函数的阈值考虑在内。在数学上,有许多激活函数可以达到这样的效果。
S函数(sigmoid function)。这个函数,比起冷冰冰、硬邦邦的阶跃函数要相对平滑,这使得这个函数更自然、更接近现实。自然界很少有冰冷尖锐的边缘!
S函数,有时也称为逻辑函数
我们使用这种S函数,而不使用其他可以用于神经元输出的S形函数,还有另一个非常重要的原因,那就是,这个S函数比起其他S形函数计算起来容易得多,在后面的实践中,我们会看到为什么。让我们回到神经元,并思考我们如何建模人工神经。
读者要认识到的第一件事情是生物神经元可以接受许多输入,而不仅仅是一个输入。刚才,我们观察了布尔逻辑机器有两个输入,因此,有多个输入的想法并不新鲜,并非不同寻常。对于所有这些输入,我们该做些什么呢?我们只需对它们进行相加,得到最终总和,作为S函数的输入,然后输出结果。这实际上反映了神经元的工作机制。
下图说明了这种组合输入,然后对最终输入总和使用阈值的思路。
如果组合信号不够强大,那么S阈值函数的效果是抑制输出信号。如果总和x足够大,S函数的效果就是激发神经元。有趣的是,如果只有其中一个输入足够大,其他输入都很小,那么这也足够激发神经元。更重要的是,如果其中一些输入,单个而言一般大,但不是非常大,这样由于信号的组合足够大,超过阈值,那么神经元也能激发。这给读者带来了一种直观的感觉,即这些神经元也可以进行一些相对复杂、在某种意义上有点模糊的计算
树突收集了这些电信号,将其组合形成更强的电信号。如果信号足够强,超过阈值,神经元就会发射信号,沿着轴突,到达终端,将信号传递给下一个神经元的树突。下图显示了使用这种方式连接的若干神经元。
将这种自然形式复制到人造模型的一种方法是,构建多层神经元,每一层中的神经元都与在其前后层的神经元互相连接。下图详细描述了这种思想。
你可以看到三层神经元,每一层有三个人工神经元或节点。你还可以看到每个节点都与前一层或后续层的其他每一个节点互相连接。
但是,这看起来很酷的体系架构,哪一部分能够执行学习功能呢?针对训练样本,我们应该如何调整做出反应呢?有没有和先前线性分类器中的斜率类似的参数供我们调整呢?最明显的一点就是调整节点之间的连接强度,即 权重
随着神经网络学习过程的进行,神经网络通过调整优化网络内部的链接权重改进输出,一些权重可能会变为零或接近于零。零或几乎为零的权重意味着这些链接对网络的贡献为零,因为没有传递信号。零权重意味着信号乘以零,结果得到零,因此这个链接实际上是被断开了
但是,计算信号如何经过一层一层的神经元,从输入变成输出,这个过程似乎有点令人生畏,这好像是一种非常艰苦的工作。
因此,我们尝试使用只有两层、每层两个神经元的较小的神经网络,来演示神经网络如何工作,如下图所示
让我们想象一下,两个输入值分别为1.0和0.5。这些值输入到这个较小的神经网络,如下图所示。每个节点使用激活函数,将输入转变成输出。
我们还将使用先前看到的S函数y=1/(1+e -x),其中神经元输入信号的总和为x,神经元输出为y。权重是什么?权重的初始值应该为多少?这是一个很好的问题。
让我们使用一些随机权重:
· w1,1=0.9
· w1,2=0.2
· w2,1=0.3
· w2,2=0.8
让我们开始计算吧!
第一层节点是输入层,这一层不做其他事情,仅表示输入信号。也就是说,输入节点不对输入值应用激活函数。这没有什么其他奇妙的原因,自然而然地,历史就是这样规定的。
神经网络的第一层是输入层,这层所做的所有事情就是表示输入,仅此而已。第一层输入层很容易,此处,无需进行计算。接下来的第二层,我们需要做一些计算。对于这一层的每个节点,我们需要算出组合输入。
还记得S函数y=1 /(1+e-x)吗?这个函数中的x表示一个节点的组合输入。此处组合的是所连接的前一层中的原始输出,但是这些输出得到了链接权重的调节。下图就是我们先前所看到的一幅图,但是现在,这幅图包括使用链接权重调节输入信号的过程。
因此,首先让我们关注第二层的节点1。第一层输入层中的两个节点连接到了这个节点。这些输入节点具有1.0和0.5的原始值。来自第一个节点的链接具有0.9的相关权重,来自第二个节点的链接具有0.3的权重。
因此,现在,我们已经得到了x=1.05,这是第二层第一个节点的组合调节输入。最终,我们可以使用激活函数y=1 /(1+e -x)计算该节点的输出。你可以使用计算器来进行这个计算。答案为y=1 /(1+0.3499)=1 / 1.3499。y=0.7408
因此,现在我们可以使用S激活函数y=1/(1+0.5488)=1/1.5488计算节点输出,得到y=0.6457。
下图展示了我们的计算结果
从一个非常简化的网络得到两个输出值,这个工作量相对较小。对于一个相对较大的网络,我不希望使用手工进行计算!好在计算机在进行大量计算方面表现非常出色,并且不知疲倦和厌烦。
即便如此,对于具有多于两层,每一层有4、8甚至100个节点的网络,我也不希望编写计算机指令来对这样的网络进行计算。即使只是写出所有层次和节点的计算指令,也会让我感到枯燥,让我犯错,更不用说手工进行这些计算了。
好在,即使是面对一个具有很多层、众多节点的神经网络,数学可以帮助我们以非常简洁的方式写下计算出所有输出值的指令。由于这种简洁性,指令变得非常短,执行起来也更有效率,因此这种简洁性不仅仅对人类读者有益处,对计算机而言,也一样大有裨益。
这一简洁方法就是使用矩阵,接下来,我们就来看看矩阵如何表达神经元
下图显示了具有3层、每层具有3个节点的神经网络示例。为了保证图的清晰,我们并没有标上所有的权重
此处,我们要向大家介绍一些常用的术语。正如我们所知道的,第一层为输入层,最后一层为输出层,中间层我们称之为隐藏层。虽然隐藏层听起来很神秘、很黑暗,但是很遗憾,我们这样称呼中间层,其理由并不神秘。中间层的输出不需要很明显地表示为输出,因此我们称之为“隐藏”层。当然,这个解释有点牵强,然而,我们对这个名称没有更好的解释了
让我们演示一下图中所描述的示例网络。我们观察到了3个输入是0.9、0.1和0.8。因此,输入矩阵I为:
正如我们刚才看到的,输入到中间层的组合调节信号为X=W·I,其中I为输入信号矩阵,W为权重矩阵。这个神经网络的I、W是什么样的呢?图中显示了这个神经网络的一些权重,但是并没有显示所有的权重。下图显示了所有的权重,同样,这些数字是随机列举的。在这个示例中,权重没有什么特殊的含义。
你可以看到,第一个输入节点和中间隐藏层第一个节点之间的权重为w1,1=0.9,正如上图中的神经网络所示。同样,你可以看到输入的第二节点和隐藏层的第二节点之间的链接的权重为w2,2=0.8。图中并没有显示输入层的第三个节点和隐藏层的第一个节点之间的链接,我们随机编了一个权重w3,1=0.4。
但是等等,为什么这个W的下标我们写的是“input_hidden”呢?这是因为Winput_hidden是输入层和隐藏层之间的权重。我们需要另一个权重矩阵来表示隐藏层和输出层之间的链接,这个矩阵我们称之为Whidden_output。
下图显示的是第二个矩阵Whidden_output,如先前一样,矩阵中填写了权重。举个例子,同样你可以看到,隐藏层第三个节点和输出层第三个节点之间链接的权重为w3,3=0.9。
让我们一起继续算出输入到隐藏层的组合调节输入值。我们应该给这个输入值一个名称,考虑到这个组合输入是到中间层,而不是最终层,因此,我们将它称为Xhidden。
此处我们不打算进行完整的矩阵乘法运算,因为那正是矩阵的用武之地。我们希望使用计算机进行费力的数字运算。计算出的答案如下图所示
我们已经拥有了输入到中间隐藏层的组合调节输入值,它们为1.16、0.42和0.62。我们使用矩阵这个工具来完成这种复杂的工作,这是值得我们自豪的一个成就。
让我们可视化这些输入到第二层隐藏层的组合调节输入
虽然到目前为止,一切都还顺利,但是,我们还有更多的工作要做。我们对这些节点应用了S激活函数,使得节点对信号的反应更像自然界中节点的反应,你应该记得这一点吧!因此,现在,我们进行这个操作
也就是说我们计算出了中间层的输出值。这个过程是非常清晰的,也就是应用激活函数到中间层的组合输入信号上。让我们使用这个新信息,更新下图。
如果这只是一个两层的神经网络,那么这些就是第二层的输出值,我们现在就可以停止计算了。但是,由于还有第三层,我们不能在此处停止计算。
我们如何处理通过第三层的信号呢?我们可以采用与处理第二层信号相同的方式进行处理,这没有任何实质的区别
因此,使用同样的方式计算出这个矩阵,这样我们得到了最后一层输出层的组合调节输出信号
现在,更新示意图,展示我们的进展,从初始输入信号开始,前馈信号,并得到了最终层的组合输入信号
剩下的工作就是应用S激活函数,这是很容易的一件事情
成功就是这么的容易!我们得到了神经网络的最终输出信号。
让我们也将其显示在图上。因此,这个三层示例神经网络的最终输出信号为0.726、0.708和0.778。
我们成功追踪了神经网络中的信号,从信号进入神经网络,通过神经网络的各层,并得到了最终输出层的输出信号
下一步,将神经网络的输出值与训练样本中的输出值进行比较,计算出误差。我们需要使用这个误差值来调整神经网络本身,进而改进神经网络的输出值。