大量示例+简单图像!带你读懂神经网络
本文旨在揭开神经网络的神秘面纱,介绍神经网络运行的动机和基础。
GitHub 库传送门:https://github.com/mrdragonbear/Neural-Networks
神经网络的动机
未经训练的神经网络模型很像新生儿: 他们被创造出来的时候对世界一无所知(如果考虑到认识论理论的话),而且只有通过接触这个世界,也就是后天的知识,才会慢慢提高它们的认知程度。算法通过数据体验世界——我们试图通过在相关数据集上训练神经网络,来提高其认知程度。衡量进度的方法是通过监测网络产生的误差。
在深入研究神经网络世界之前,了解这些网络背后的动机以及它们工作的原因是很重要的。为了做到这一点,我们必须讨论一下逻辑回归分析。
围绕定量反应变量的建模与预测(例如出租车接送的次数,自行车租赁的次数)的方法被称为回归(Ridge回归,LASSO回归等)。当因变量是明确的,那么这个问题不再被称为回归问题,而是被标记为一个分类问题。
考虑一个二分类问题,目标是根据一组预测变量 x,尝试将每个观察结果分为由 y 定义的类别(例如类别或集群)。
假设我们想根据患者的特征来预测患者是否患有心脏病。这里的因变量是绝对的,存在有限的结果,或者更明确地说是二元的,因为只有两种类型(yes / no)。
这里有很多特性——在此,我们只使用 MaxHR 变量。
为了做出这个预测,我们将使用一种被称为逻辑回归分析的方法。逻辑回归分析解决了预测一个人患有心脏病概率的问题,P(y=1),给定输入值X。
逻辑回归模型使用一个逻辑来对P(y=1)建模 :
因此,该模型将用S形曲线预测 P(y=1) ,S形曲线是逻辑函数的一般形状。
β₀使曲线右移或左移 c=-β₀/ β₁,而β₁控制 s 形曲线的陡度。
注意,如果β₁是正值,那么预测的P(y=1)范围为 从0(当x很小时)到1(当x很大时),如果β₁是负值,则与之相反。
下面以图表形式对此进行总结。
现在我们知道了如何操纵逻辑回归曲线,可以利用一些变量来得到想要的曲线。
可以改变β₀值来移动偏移量。
可以改变β₁的值来扭曲梯度。
动手完成这个过程是相当乏味的,而且不太可能得到最优值。为了解决这个问题,我们使用损失函数来量化归属于当前参数的误差水平。然后找出使这个损失函数最小的系数。对于这种二进制分类,可以使用一个二进制损失函数来优化我们的逻辑回归模型。
因此,神经网络的参数与网络产生的误差有关,当参数变化时,网络产生的误差也随之变化。使用一种叫做梯度下降法的优化算法来改变参数,这种算法对于寻找函数的最小值很有用。我们正在寻求最小化的误差,这也被称为损失函数或目标函数。
那么刚刚做的这些有什么意义呢?这和神经网络有什么关系?实际上,刚刚做的实质上和神经网络算法执行的程序是一样的。
我们只为之前的模型使用了一个特性。相反,我们可以采用多种特性,并用网络的形式来说明这些特性。我们有每个特征的权重,还有一个偏差项,它们共同组成了回归参数。根据问题是分类问题还是回归问题,公式将略有不同。
当我们讨论神经网络中的权重时,实际上讨论的是各种传入函数的回归参数。然后这些信息被传递给激活函数,由它来决定结果是否重要到足以“触发”该节点。
所以现在我们开发了一个非常简单的网络,它由多个具有4个功能的逻辑回归模型组成。
需要从一些任意的数值公式开始,以便更新和优化参数,我们将在每次更新后评估损失函数并使用梯度下降法。
要做的第一件事是随机设置权重。在心脏数据中,该模型很可能会给出错误的答案。
然后通过不良行为处罚的方式来训练这个模型。
然而,仅仅告诉计算机它的性能是好是坏并不是特别有帮助。你需要告诉它如何更改这些权重,以提高模型的性能。
我们已经知道如何告诉计算机它运行良好,只需要咨询损失函数。现在,这个过程更复杂了,因为有5个权重要处理。我们将只考虑一个权重,但所有权重的程序是类似的。
理想情况下,我们希望知道给出使ℒ(w)取最小值的w的值。
为了找到函数ℒ(w)的最优点,可以对权值求导,然后将其设为零。
然后需要找到满足这个方程的w。有时候没有明确的解决方案。
一个更灵活的方法是从任何一点开始,然后确定哪个方向去减少损失(在这种情况下是左边还是右边)。具体来说,可以计算函数在这一点上的斜率。如果斜率是负的,就向右移动,如果斜率是正的,就向左移动。然后重复这个过程直到收敛。
如果步长与斜率成正比,那么你就要避免超过最小值。
如何执行此更新?这是通过一种被称为梯度下降法的方法来完成的,这个方法在前面已经简要提到过。
梯度下降法
梯度下降法是求函数最小值的迭代法。这篇博文(http://ruder.io/optimizing-gradient-descent/)展示了更新权重的不同方法。现在,坚持使用普通的梯度下降法算法,有时也被称为delta规则(http://www.cs.stir.ac.uk/courses/ITNP4B/lectures/kms/3-DeltaRule.pdf)。
我们知道想要走与导数相反的方向(因为我们试图避开误差) ,并且希望步长与导数成比例。这个步长由一个称为学习率的参数控制。新权重是旧权重和新步长的和,步长由损失函数以及相关参数对学习率的影响程度决定。
较快的学习速度意味着对导数赋予较大的权重,这样算法的每次迭代都可以进行较大的步长。较小的学习速度意味着对导数的权重较小,因此每次迭代可以采用较小的步长。
如果步长过小,则算法需要较长时间收敛,如果步长过大,则算法将不断错过最优参数的选择。显然,建立一个神经网络时选择学习率很重要。
使用梯度下降法时有很多考虑因素:
· 仍然需要推导出导数。
· 需要知道学习率是多少或者如何设置它。
· 需要避免局部极小值。
· 最后,全部损失函数包括所有单个"误差"的总和。这可以是成千上万的例子。
现在衍生物都是用自动微分来衍生的,所以不太关心这个问题。然而,确定学习速度是一个重要而复杂的问题。
局部极小值对于神经网络来说是个很大的问题,因为神经网络的形式并不能保证我们将达到全局最小值。
陷入局部极小值意味着有一个局部良好的参数优化,但有一个更好的优化在损失表面的某个地方。神经网络的损耗曲面可以有许多这样的局部优化,这是网络优化的问题。例如下图所示的损失表面。
网络陷入局部极小值。
网络收敛到全局最小值
怎样解决这个问题呢?一方面可以使用批量梯度下降和随机梯度下降的方法。虽然这听起来复杂,但事实上很简单,不要用整个数据集,而是用其中一批(组)数据,在每次迭代过程中,损失平面都会有部分变动。
每一次迭代k都能使用下面的(似然)损失函数来求导数:
这是全部损失函数的近似值,举例说明一下。首先从全部的(似然)损失平面开始,随机分配的网络权值会提供一个初值。
之后选一批数据,比方说全部数据的10%,然后构建一个新的损失平面。
此时位置变了。再次从全部数据中随机选择一组数据,然后构建损失平面。
将梯度下降法应用于这组数据,然后进行更新。
选取一组新数据继续重复以上程序。
然后进行更新。
将上述程序进行多次迭代。
直到网络开始收敛到全局最小值。
现在有足够的知识储备来构建第一个神经网络。
人工神经网络(ANN)
既然已经了解了逻辑回归的原理、评估一个网络的方法以及如何更新网络以提高其性能,那么接下来就可以构建一个神经网络了。
首先,希望大家能知道神经网络名称的由来。也许你已经听说过了,神经网络模仿了神经元即神经细胞的结构,虽然这种结构看起来比神经网络复杂得多,但其实二者的功能是相似的。
图片来源:https://simple.wikipedia.org/wiki/Neuron
实际神经元运作时要积累电势能,当能量超过特定值时,突触前神经元会经轴突放电,继而刺激突触后神经元。
人类有着数以亿计相互连接的神经元,其放电模式无比复杂。哪怕是最先进的神经网络也难以比拟人脑的能力,因此,神经网络在短时间内应该还无法模拟人脑的功能。
可以利用示意图,将神经元结构与神经网络中的人工神经元进行类比。
图片来源:http://cs231n.stanford.edu/slides/2017/cs231n
鉴于人脑的能力,很明显人工神经网络的应用范围是无限的,尤其是在我们将其连接到传感器、执行器和网络资源以后。尽管目前还处于相对不够成熟的阶段,但是由此可以看出神经网络无处不在。
毕竟,还原论者认为,人类不过是经由各部分神经系统,连接到传感器和执行器的神经网络的集合体。
现在,想象我们拥有大量的特征。每一特征都要经过仿射变换,大体来说就是加法(减法)和/或乘法,这就像是一个回归方程。如果在一个多层感知机中有大量节点会聚于一个节点,那么仿射变换就变得十分重要。
而后,将结果送到激活函数,这会为我们提供某种形式的概率值。这个概率值决定了神经元是否放电。然后可以把该结果代入损失函数,从而评估该算法的性能。
从现在开始,将仿射和激活看作一个模块。但是要清楚,仿射变换是上游节点输出的总和,而后将加和的输出传递给激活函数,从而评估决定该量化值(概率值)是否足以使神经元放电的概率。
现在可以回到第一个心脏病数据的例子。取两条逻辑回归曲线加以合并。合并前的曲线如下所示:
由于自由度的提高,将两个网络相连接时,所得网络的灵活性就会增加。
这很好地体现出了神经网络的强大,我们可以将大量来自与众多神经元的函数串(加)在一起,这样就能得到高度非线性函数。有了大量且充足的神经元,就可以得到任意复杂度的连续函数。
这只是神经网络的一个简单的例子,但即使是这样一个简单的网络,我们也已经陷入了一个问题之中。要如何更新权值呢?
我们需要计算与这些权值相关的损失函数的导数。为了了解损失的权值w1、w2和w3,需要用到反向传播算法。
反向传播算法
反向传播算法是神经网络学习的核心机制,它能在预测期间通知网络是否出现错误。反向传播算法的问世是整个神经网络研究中最重要的里程碑之一。
传播是为了在某个特定方向或者经由特定的媒介来传送某种事物(如光、声)。在神经网络的背景下讨论反向传播算法时,我们谈的是信息的传输,神经网络对数据进行预测会产生误差,而这些信息就与所产生的误差相关。
预测期间,神经网络将信号传播到输出层并在此处进行决策,之后网络将误差信息反向传播从而修改各项参数。
图片来源:https://becominghuman.ai/back-propagation-in-convolutional-neural-networks-intuition-and-code-714ef1c38199
反向传播算法用来计算网络中各项参数的导数,从而才能使用梯度下降法。这是反向传播算法和梯度下降法的重要区别,不要将二者混淆。首先用到的是反向传播算法,来获取梯度下降法所需要的信息。
可能你已经发现仍需计算导数。计算机无法进行微分,但是为了在没有网络设计器参与的情况下进行,我们可以建造一个函数库来实现该过程,这被称为自动微分,举例如下。
可以像这样手算,然后对每个网络架构和节点进行修改。
或者,可以定义一个链接到网络结构的函数库,当网络架构更新时会自动实现并更新程序。
如果你真想搞清楚这个自动微分过程用处有多大,试着做一个六节点的多层神经网络,然后编写代码来实现反向传播算法。
更复杂的网络
双节点神经网络对大多数应用都不适用。通常,我们会用神经网络去逼近一个难以用传统方法描述的复杂函数。
神经网络要遵循万能近似定理,这一点十分特殊。该定理称,如果一个神经网络中有无限多个神经元,那么就可以精确地表示出任意复杂度的连续函数。这一表述非常耐人寻味,它的意思是,如果计算能力足够大,我们几乎可以逼近任何函数。
很明显,这一想法在实际中存在一些问题。首先,可利用的数据有限,这就限制了预测类别或者估值时的精确度。其次,计算能力有限。即使是世界上最强大的超级计算机,想要设计一个远超其运载能力的神经网络也不是什么难事。
我们所要设计的网络架构,要凭借最少的数据,用相对较少的计算能力,就能实现高精度。
更令人吃惊的是,仅仅一个隐藏层就足以逼近任意精确度的任意函数。
如果一层就够了,那人们为什么还要使用多层神经网络呢?
多隐藏层神经网络架构
答案很简单。由于浅层神经网络比深层神经网络需要更多的宽度(指数级),因此神经网络的架构要非常宽。此外,浅层神经网络更容易出现过拟合。
这推动了深度学习领域的出现(深度指的是神经网络的多层架构),影响着当代关于机器学习以及涉及数据分类和预测的多数领域的研究文献。
总结
这篇文章围绕神经网络的初衷以及背景进行了讨论,概述了其训练方法。我们谈论了损失函数、误差传播、激活函数和网络架构。下图很好地总结了以上概念及其相互间的联系。
神经网络分步示意图 图片来源:https://medium.com/datathings/neural-networks-and-backpropagation-explained-in-a-simple-way-f540a3611f5e
留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”