我深感在学习机器学习的路上,很多人最大的拦路虎其实都是数学。也有很多人因此而放弃学习这门美妙的科学。但实际上,根据我的经验,除了直接硬啃许多繁琐的数学推导,通过头脑里的图像来理解问题也是一个非常好的方法。而且你也可以在知道了他的来龙去脉以后再去学习那些数学推导。这一条对许多理工科都是有用的。 比如混沌运动在背后需要的是非常繁琐的数学方法。典型案例是动力系统。但是我多年以前读过一本法国人写的书。从实验现象入手讲解这个问题。解释的效果是非常好的。 我决定要写这篇文章。其实正是因为我发现很多同学是很难理解BP神经网络的。我努力从让你先在大脑里产生一个big picture入手,来讲请这个问题。你所需要掌握的其实就是一点矩阵和微积分。 希望你能看完这篇文章以后”啊,原来如此简单!“我是在大三头一次接触到这个东西的。那个时候我还是材料物理系的本科生,机器学习正好是爆发前夜,那是2014年。我那个时候苦于找不到合适的资料,对这个东西的理解当时感觉也很苦恼。我希望能用这篇文章帮助很多像当时的我那样的人。 BP(Back-propagation,反向传播)神经网络是最传统的神经网络。也就是使用了Back-propagation算法的神经网络。请注意他不是时下流行的那一套深度学习。要训练深度学习level的网络你是不可以使用这种算法的。原因我们后面解释。而其实机器学习的bottleneck就是成功的突破了非常深的神经网络无法用BP算法来训练的问题。 大家记住,反复的念这句话:反向传播,反向传播,反向传播。那么反向传播的东西是什么呢?答案是:误差。就是在模拟过程中(这是一个循环,我们在训练神经网络的时候是要不断的去重复这个过程的)收集系统所产生的误差,并且返回这些误差到输出值,之后用这些误差来调整神经元的权重,这样生成一个可以模拟出原始问题的人工神经网络系统。 2. 生物神经的运作原理 我在这里不讨论那些复杂的生物学和神经科学。其实很简单的一件事,我们人类之所以可以让飞机上天,是因为”学习“了从理论力学,信号系统再到导航控制的一系列知识。作家之所以可以写出伟大的著作,那是因为他学习了语言,比如英语汉语德语法语,也学习过李白杜甫,莎士比亚。其实狗狗之所以能知道要听见主人喊一个苹果加一个苹果要喊两声(之后可以得到一块炖牛肉),也是学习的结果。 那么学习的过程,核心问题是什么?答案是误差。比如你是一个备考高三数学的学生。你本身就会1+1=2,你把这个训练一万遍有用么?没用。你要做的就是找到自己不行的地方,找到自己的漏洞,有针对性的去突破和训练。这就是用误差来学习。 人类的过程也是一样的。学习,有误差然后有反馈,我们通过这些误差反馈来学习。 3. 神经网络的基础架构 凡是对这个事情有最基础了解和认识的朋友都知道神经网络其实就是几层神经元,每层神经元里有几个神经元点。不同layer之间的神经元相互连接。其实就是如此: 我不管生物或者神经学里在讲什么。在这,每一个神经元就是三件事:输入,判断和输出。输入层的神经元(就是那个圆形的圈,代表一个神经元或者一个神经细胞)是读入你输入的数据的。只要你有数据,这个玩意就能跑。这就好比你只要有汽油,汽车就能开是一个道理。中间则是”隐含层。“你可以控制这个隐含层的层数,以及每一层里有多少个神经元或者神经细胞。当然在实际操作里为了方便我们一般都直接认为你不管用几层,每层的神经元或者神经细胞数目都是一样的。因为这样的话写代码会比较方便。 每一层神经元内部都不互相连接。而相邻层的神经元点之间则互相连接。在我们这个问题里,两个相邻层,所有的神经元都是相互连接的。你说可不可以通过让这些神经元之间不互相连接来起到效果?的确,历史上的连接学派就是这样想的。但实际上你可以都给他联上。其实道理非常简单。如果我们真的要取消某两个点之间的连接的话,那么很显然只要设定这条连线上的数值为零即可。这好比一个网络电路,阻值本身就是无限大的。 除了神经元,你还需要关注一个东西,那便是神经线。在所有的神经线(两个神经元一连就是)上你可以赋予不同的权重。而这个则是训练的核心要务,说白了你就是那一套最接近完美答案的权重就可以了。 4. 运算过程:矩阵乘法 我们要把输入在这个数学结构上传递到输出,要怎么办呢?答案是,使用矩阵乘法。 其实这样的思路一开始是非常简单的。 我们以这个例子来说明。 在这幅图里,我们把上一层的第i个神经元和下一层的第j个神经元之间的权重(在3里讲的很明白)记为w(ij)。而把上一层传入的三个input,分别记为S(1),S(2)和S(3)。 因为数据肯定是在不同的层之间流动的。我们所做的就是通过一个矩阵乘法求解下一层的输出数值。 这个过程其实也非常简单。我们把输出记为O(1),O(2)和O(3)。 结合权重,这个其实不就是一个高中生都可以理解的思想吗?以O(1)举例。O(1)里的输出自然有来自S1,2,3的。那么分别按照权重去乘就可以了。权重自然就是一个大于等于零的实数嘛。 O(1)=S(1)*w(11)+S(2)*w(21)+S(3)*w(31) 类似的我们可以求解出O(2)和O(3)。我们把这一部分,留作练习题。希望你看到这里也自己写一下。 其实答案也很简单: O(2)=S(1)*w(12)+S(2)*w(22)+S(3)*w(32) O(3)=S(1)*w(13)+S(2)*w(23)+S(3)*w(33) 写到这里,熟悉矩阵乘法的同学肯定要恍然大悟了。没错,这就是一个矩阵的乘法!最基础的那种。写成矩阵他应该是什么样呢?这个又是一个思考题,希望你来写一下。 其实答案便是: 我们知道,数学家对矩阵已经有了几百年的研究,积累了大量的方法。这也是物理学家和工程师非常熟悉的工具。我们其实用这种方法,自然可以一层一层的把最左边输入的数据送到最右边来。 我们自然可以得到一个结果。但是这个结果有可能是错的吧!所以怎么办呢?我们用真实的结果去和这个结果去比如求差,自然就可以把误差求解出来了。 同样的道理,我们可以把误差按照矩阵乘法一路返回。而且在这个过程中,每个神经元和神经线自然可以得到一些”信息。“我们可以用这些信息来修正神经网络,其实也就是给所有的边去赋予不同的权重。 如法炮制。在你有误差E(1),E(2),E(3)的时候,自然可以用这些误差返回上一层,得到上一层应该被返回的误差。其实也是一个矩阵乘法的内容。 5. 如何去调参数:微积分 其实这就是我们使用了人工神经网络来模拟学习的过程。理论上,这个算法可以处理世界上的任何问题。无论是股票交易还是生物信息,无论是飞机上天还是潜艇下水。当然了,工程就是另一回事了。 那么这些权重是如何被求解出来的呢? 答案便是:微积分。 更进一步:微积分里的链式求导法则。 再进一步:在矩阵上的微分链式求导法则。 在矩阵上求微分是大学数学教育的一个盲点。不过,作为搞计算机的,我们可以直接去用那些数学家做出的结论! 未完待续。
|