实现人工智能的方法有很多种,当前最热门的一种就是通过深度学习来训练神经网络。深度学习这个词指的是训练大型神经网络。深代表着非常大的神经网络。那么神经网络到底是什么呢?
如下图:
假设你有一个数据集(包含了六个房屋的面积和价格数据)。你想要找到一个方法(即构建一个函数)来通过面积预测出价格。如果你熟悉线性回归(不熟悉也没关系,你就把它看作是一个数学理论),那么可以根据这个理论在实际数据附近画出一条直线,如上图中红色的线,它附近的蓝色的小圆圈代表着六个房子的面积与房价对应的点,即根据这条线(这个函数)来找某一个面积对应的房价,那么除了些误差外,基本上是准的。
理解:大量的数据通过一个函数进行处理分析,找到相同得规则,然后再根据其他得数据分析出最可能得结果,这就是机器学习得一个大概得流程。
监督学习:判断是否是监督学习,就看输入数据是否有标签。输入数据有标签,则为有监督学习,没标签则为无监督学习。
分类(classification)这种机器学习算法就是一种监督学习。对于分类,输入的训练数据有特征(feature),有标签(label)。也就是我们前面文章中的输入x和输出y。每一个x样本都对应着一个y(输出)标签。所谓的学习,其本质就是找到特征和标签间的关系(mapping),也就是找规律。这样当有特征而无标签的未知数据输入时,我们就可以通过已有的关系得到未知数据标签,即根据新数据进行预测。在上述的分类过程中,如果所有训练数据都有标签,则为有监督学习(supervised learning)。如果数据没有标签,显然就是无监督学习(unsupervised learning),即聚类(clustering)。
目前分类算法(监督学习)的效果还是不错的,而相对来讲,聚类算法(无监督学习)就有些惨不忍睹了。确实,无监督学习本身的特点使其难以得到如分类一样近乎完美的结果。这也正如我们在高中做题,答案(标签)是非常重要的,假设两个完全相同的人进入高中,一个正常学习,另一人做的所有题目都没有答案,那么想必第一个人高考会发挥很好,第二个人会发…….疯。
这时各位可能要问,既然监督学习如此之好,非监督学习如此之不靠谱,那为何我们还可以容忍非监督学习的存在?因为在实际应用中,标签的获取常常需要极大的人工工作量,有时甚至非常困难。
神经学习另一个分类:神经网络除了按监督学习和非监督学习来分类外,还按结构来分类。不同结构的神经网络被用于不同的应用程序中。例如,在之前看到的房价预测应用中,我们使用的是标准的神经网络结构,广告预测也是一个相对标准的神经网络。对于图像应用程序,我们经常使用卷积神经网络CNN。对于序列数据应用程序一般使用递归神经网络RNN(例如音频就属于序列数据,是随着时间一段一段表述的,例如英语、汉语都是随着时间一个字一个单词来表述的)。对于更复杂的应用,比如自动驾驶,里面有图像所以需要CNN卷积神经网络,而雷达信息则需要其它类型的神经网络,这就导致了混合的神经网络架构。
为了更具体一点,上面分别给出了各种不同神经网络的结构图。依次是,标准神经网络SNN, 卷积神经网络CNN,递归神经网络RNN。卷积网络通常被用于图像数据。递归神经网络被用于序列数据。
机器学习中将数据分为结构化数据和非结构化数据。结构化数据主要表示数据库数据。例如,在房价预测中,您可能会有一个数据库告诉您卧室的大小和数量。又如预测用户是否点击广告时,您可能会获得有关用户的信息,例如年龄,广告的一些信息。所谓结构化数据,意味着每个特征,如房子的大小,卧室的数量或用户的年龄,是具有非常明确的含义的。相比之下,非结构化数据指的是音频,图像。这里的特征可能是图像中的像素值或文本中的单个单词,没有明确的含义。与结构化数据相比,计算机更难以理解非结构化数据。而人类已经进化得非常善于理解音频和图像这些非结构化数据。但这一两年由于深度学习的兴起,计算机对非结构化的理解能力越来越强了。人们在听到有关神经网络对非结构化数据的成功时,例如当神经网络识别出一只猫时,人们都很兴奋。但事实证明,神经网络正在创造的许多短期经济价值其实是在结构化数据上的,比如广告系统。所以在这个课程中,我将介绍的很多技术都将适用于结构化数据和非结构化数据。为了解释算法,在示例中我将会更多的使用非结构化数据。但是,将来在您自己的团队中应用神经网络时,我希望您应该对结构化和非结构化数据都重视。
深度学习为什么火了?
深度学习这个技术其实几十年前就已经存在了。但为什么直到近几年才火起来了? 在这篇文章中,让我们来看看使深度学习火起来的一些因素。
上图横轴代表训练数据的数量,纵轴代表算法性能(如广告点击预测的准确性)。从图中可以看出,当我们给出越多的训练数据时,各种算法的性能都会越高。但是各个算法之间有所区别。对于传统的机器学习算法(黑色的曲线),最开始它的性能也在提升,但是后来,无论你再怎么添加训练数据它的性能都不再提升了。再多的数据也是浪费。而对于小型神经网络,它的性能是会随着数据量不断提升的,但是提升的幅度不大,中型网络幅度要大些,大型网络幅度就更大些…
之前我们一直因为没有足够量的数据而无法提升神经网络的性能。但后来我们进入了电子社会,摄像头、电脑、手机越来越便宜,同时人们花费了大量时间在电脑在网页在手机上面,以及后来出现的物联网,各种穿戴设备各种传感器产生了越来越多的数据。这使得神经网络得以大展拳脚。
既然深度学习是需要将大量得数据经过算法进行分析,那么首先第一步,需要将大量得数据输入到神经网络中;
1:如何将数据输入到神经网路中:
假设我们希望神经网络能分辨出图片中是否有猫,结果只有两个――有或者没有,这被称为二元分类问题。我将拿这个例子给大家介绍如何将待预测数据输入到神经网络中。
此例中,待预测的数据是一张图像。为了存储图像,计算机要存储三个独立的矩阵(矩阵可以理解成二维数组),分别与此图像的红色、绿色和蓝色相对应(世界上的所有颜色都可以通过红绿蓝三种颜色调配出来)。如果你的输入图像的大小是64x64个像素(一个像素就是一个颜色点,一个颜色点由红绿蓝三个值来表示,例如,红绿蓝为255,255,255,那么这个颜色点就是白色),所以3个64×64大小的矩阵在计算机中代表了一张图像,对应于图像的红绿蓝的强度值。上图中只画了个5×4的矩阵,而不是64×64,为什么呢?第一是因为我很懒,第二还是因为我很懒,第三是因为没有必要,意思意思你能明白就可以了!做人不能太认真了。
为了更加方便后面的处理,我们一般把上面那3个矩阵转化成1个向量(向量可以理解成1*n或n*1的数组,前者为行向量,后者为列向量)。那么这个向量x的总维数就是64x64x3,结果是12288。在人工智能中,每一个输入到神经网络的数据都被叫做一个特征,那么上面的一张图像中就有12288个特征。这个12288维的向量也被叫做特征向量。神经网络接收这个特征向量x作为输入,并进行预测,然后给出相应的标签y,y为1或0,即是有猫的图像还是无猫的图像。
待预测数据就是这样被输入到神经网络中的。虽然对于不同的应用,需要识别的对象不同,有些是语音有些是图像有些是传感器数据,但是它们在计算机中都有对应的数字表示形式,通常我们会把这些数字表现形式转化成一个特征向量,然后将其输入到神经网络中
2:神经网络如何进行预测:
第一步已经介绍了如何将数据输入到神经网络中,第二步就是对数据进行预测:
给定一个输入特征向量x(例如你想要识别的图像――是否有猫),你需要一个能输出预测结果的算法(在这里我们用的是逻辑回归算法)。这个被输出的预测结果我们称为y^,假设y是1,如果预测得很准的话y^可能会是0.99)。
上面第一个公式中的x是个(n,1)维的矩阵,表示一个训练样本,里面的n表示一个训练样本中的特征数量,例如一张图片就是一个训练样本,图片中每个颜色强度值就是一个特征;w也是一个(n,1)维的矩阵,它表示权重(weight),它一一对应于每个输入的特征,也可以说它指示了某个特征的重要程度;b是一个实数,在这里可以将其看作为一个阀值。(输入数据x与权重w得数据格式是相等得,例如都是(n,1)维的矩阵)。
如何理解w和b呢?我举个例子来帮助大家理解。可以把上面的算法过程看作是一种通过权衡输入然后再做出决定的一个过程。假设周末即将到来,你听说在你的城市将会有一个音乐节。你要决定是否去参加这个节日。你需要通过权衡3个因素(3个特征)来做出决定:1,天气好吗? 2,你的女友是否愿意陪你去?3,举办地点离地铁近吗?这3个因素就对应着上图中的x1、x2,x3(它们是x这个训练样本中的3个特征)。我们可以给它们赋个值,如果天气好,那么x1为1,否则为0,x2和x3雷同。假设你很讨厌坏天气,如果天气不好,你就不会去参加这个节日。对其它两个因素要求不高(这里假设你是个老司机,女人多得是,不怕冷落了女友)。那么我们分别给3个权重赋值为7,2,2。w1的值大很多,这表明天气对你来说很重要,比你的女友是否愿意去,以及交通的便利性更重要。而b我们可以看作一个阀值,假设我们给b赋值为-5,那么也就是说,只要天气好,即使女友不陪你去、交通也不方便,你也会去参加这个节日――x1 * w1 + x2 * w2 + x3 * w3 = 1 * 7 + 0 * 2 + 0 * 2 = 7(这里的*代表乘法)(我们这里先不考虑σ函数),而7 +(-5)> 0,结果是你会去那个音乐节。如果我们选择不同的w和b值,那么对于同一个输入x,会有不同的结果输出。例如有些苦逼,非常在意女友的感受,女友不去,他不敢去,那么w可能就变成了2,7,2。训练神经网络的目的就是通过训练过程来得到这些w和b值(后面会教大家如何来训练得到它们)。这些w和b值可以让神经网络得到一项判断能力,一项预测能力――输入一张图片,神经网络根据训练好的w和b,通过上面的公式根据每个像素的值以及与其对应的权重值以及阈值来判定这张图里是否有猫。神经网络就是这样来进行预测的。它和我们人类的思考方式是一样的。虽然我们人可以做出非常复杂的判断,但是基本原理是很简单的。人为什么能轻松分辨出一个图片中是否有猫?因为我们人就是一个巨型的神经网络,这个神经网络里面包含了数亿甚至更多的神经元(上图蓝色的圆圈就表示一个神经元),每个神经元都可以接受多个输入,在日常生活中,小孩子通过大人的教导,
下面再来说一下σ,它代表了sigmoid函数,上面是它的定义公式以及图形。我们为什么需要它?在上面我们举的去参加节日的例子中,我们得出的结果为2,其实对于不同的x和w值,结果可能会更大。所以这并不适用于二元分类问题,因为在二元分类问题中你想要得到的y^y^应该表示一个概率,一个输入是否等于它真实标签的概率(例如输入的图像里面是否有猫)。所以y^y^的值应该在0和1之间。sigmoid函数的作用就是把计算结果转换为0和1之间的值。通过看它的图形就可以明白,往sigmoid函数里输入的值z越大,那么y^y^就越靠近1,也就是里面有猫的概率就越大。
为了找到那些适合的w和b值,我们还需要一个损失函数。下一篇文章我将给大家介绍它。
3:神经网络如何知道自己预测的是否准确:
所以要验证学习成果,要判断预测结果是否准确,本篇文章介绍的损失函数(loss function)就是干这事的。
(i)(i)的预测结果。
实践中我们使用的损失函数的公式如下。
上面对单个训练样本我们定义了损失函数。下面的公式用于衡量预测算法对整个训练集的预测精度。其实就是对每个样本的“损失”进行累加,然后求平均值。这种针对于整个训练集的损失函数我们称它为成本函数(cost function)。它的计算结果越大,说明成本越大,即预测越不准确。
4:神经网络如何进行学习:
大家已经学过如何将待预测数据输入到神经网络中,也明白了神经网络是如何对这些数据进行预测的,还知道了神经网络是如何判断自己预测得是否准确的。那么如果结果预测得不准确,是不是要想办法让预测变得准确呢?这个努力让自己预测得更准确的过程就是学习。
在前面的文章中,我们已经知道,预测得是否准确是由w和b决定的,所以神经网络学习的目的就是要找到合适的w和b。通过一个叫做梯度下降(gradient descent)的算法可以达到这个目的。梯度下降算法会一步一步地改变w和b的值,新的w和b会使损失函数的输出结果更小,即一步一步让预测更加精准。
上面的公式是我们之前学到的逻辑回归算法(用于预测),以及损失函数(用于判断预测是否准确)。结合上面两个公式,输入x和实际结果y都是固定的,所以损失函数其实是一个关于w和b的函数(w和b是变量)。所谓“学习”或“训练神经网络”,就是找到一组w和b,使这个损失函数最小,即使预测结果更精准。
如上图所示,损失函数J的形状是一个漏斗状。我们训练的目的就是找到在漏斗底部的一组w和b。这种漏斗状的函数被称为凸函数(向下凸起的函数)。我们选择J为损失函数的原因正是因为J是一个凸函数。而我们之前遇到的平方差函数不是一个凸函数,那么就很难找到最小值,这就是为什么我们不采用平方差函数作为损失函数的原因。
如上图所示,梯度下降算法会一步一步地更新w和b,使损失函数一步一步地变得更小,最终找到最小值或接近最小值的地方。
那么到底这个神秘的梯度下降算法是如何来更新w和b的呢?为了简化问题,让大家更容易理解其中的理论,我们先假设损失函数J只有一个参数w(实际上J是一个关于w和b的函数),并且假设w只是一个实数(实际上w是一个向量/一组实数)。如上图,梯度下降算法一步一步地在改变着w的值,在使损失函数的结果越来越小(将w的值一步一步的移到红点处)。我们是通过下面的公式来改变w的值的。
梯度下降算法就是重复的执行上面的公式来不停的更新w的值。新的w的值(w’)等于旧的w减去学习率r与偏导数dw的乘积。不要怕,我一步一步地给你解释它们。r表示学习步进/学习率(learning rate),假设w是10,又假设dw为1,r为4时,那么在第一次梯度下降后,w’的值将变成6,而当r为2时,那么第一次下降后,w’将是8,从10变成了8比起从10变成6,变化得没有那么大,因为变化率r比较小。r是我们用来控制w的变化步进的参数。dw是参数w关于损失函数J的偏导数,偏导数是数学微积分里面的一个概念,不懂不用怕,我会慢慢让你懂。偏导数说白了就是斜率。斜率就是变化比例,即当w改变一点点后J会相应的改变多少。看上图中的黄色的小三角,在w的初始值(假设为6)的位置的偏导数/斜率/变化比例就是小三角的高除以低边(J的变化除以w的变化),也就是在当w为6时J函数的变化与w的变化之比,曲线越陡,那么三角形越陡,那么斜率越大,那么当w的值改变一丁点后(例如减1)那么J相应的改变就会越大(假设会减小3),在下面那个小三角的位置(假设那里的w是4),这个位置的曲线不是那么的陡,即斜率比较小,那么在那里w的值改变一点后(例如也减小1)但J相应的改变却没有那么大了(可能只减小1.5)。这个斜率dw就是J的变化与w的变化的比例,就是说,我们按照这个比例去使w越来越小那么它相应的J也会越来越小,最终达到我们的目的,找到J最小值时w的值是多少。损失函数J的值越小,表示预测越精准。神经网络就是通过这种方法来进行学习的,通过梯度下降算法来一步一步改变w和b的值,使损失函数越来越小,使预测越来越精准。其实原理还是很简单的!另外这里要说一下,w越来越小是一种相对的说法,例如看上面绿色的小三角的地方,这里的斜率是为负数的,所以w减去一个负数,等于w变大了,由于dw/斜率/变化比例是负数,所以w变大,那么J就变小,最终还是会移到J的最小值处。
有人会说,那我每次都使w改变很多,那么就会更快的到达J的最小值处。是可以。但是,要控制好“度”,因为如果你每次让w改变太多,那么可能会错过了J的最小值处,例如上图中你可能会从w的初始位置直接到了绿色小三角的位置(跳过了J的最小值处),之后你会左右来回跳,永远到不了J的最小值处。这就是r的用武之地,用它来控制w改变的步进,所以选择一个正确的学习率很重要。选错了,那么你的神经网络可能会永远找不到损失函数的最小值处,即你的神经网络预测得永远不会很准。后面后面的文章我会教大家如何来选择正确的学习率。
5:计算图
计算图,它是我们在研究神经网络时经常用到的一个重要手段,因为在实际工作中神经网络是很复杂的,要借助于计算图才能使其条理清晰,让复杂的事情变得直观便于研究。这里要吐槽一下不少人的坏习惯,不喜欢画图,觉得自己是天才,画图会显得自己智商低,这是自欺欺人的表现,多少大师、教授、真正的天才他们都一丝不苟地画图,可见画图是很重要的。
神经网络的计算是由一个前向传播以及一个反向传播构成的。先通过前向传播计算出预测结果以及损失;然后再通过反向传播计算出损失函数关于每一个参数(w、b)的偏导数,并对这些参数进行梯度下降,然后用新的参数进行新一轮的前向传播计算,这样来回不停地进行前向传播反向传播计算来训练(更新)参数使损失函数越来越小使预测越来越精准。
通过计算图可以把上面所述的计算过程非常直观地展示出来。
为了便于理解,本篇文章先用一个简单的计算过程来讲解计算图,下一篇文章再将神经网络计算过程和计算图结合起来讲。
我们将用函数J(a,b,c)=3(a+bc)来讲解计算图。这个函数有三个计算步骤组成。若第一步用U来表示,则U=bc;第二步用V来表示,则V=a+U;最后是J=3V。如果用计算图表示函数J的计算过程,那么将有下图(其中假设a、b、c分别为5、3、2)
如上图所示,通过前向传播一步一步地最终即可算出函数J的值,在神经网络的计算中,通过前向传播我们可以最终算出预测值和损失值。
下面我们再来介绍一下反向传播。反向传播用于计算函数J关于各个参数的偏导数,然后对参数进行梯度下降。
首先我们来计算J关于中间量V的偏导数, 我们将其记为dJ/dV。前面的文章有讲到过“偏导数说白了就是斜率。斜率就是变化比例,即w改变一点后J会相应的改变多少”。所以为了计算关于V的偏导数,我们可以假设改变V一点点,比如让V加上0.001,即V从11变成了11.001。然后看J改变了多少,J从33变成了33.003(J=3V=3*11.001)。J的变化量除以V的变化量(0.003÷0.001)等于3,即变化比例等于3,即斜率、偏导数等于3。同理我们可以计算出中间量V关于中间量U的偏导数dV/dU为1。也可以算出中间量U关于参数b的偏导数dU/db为2。那么J关于中间量U的偏导数是多少呢?其实道理一样,我们让U改变一点点,从6变成6.001,这会导致V从11变成11.001,而V的改变会导致J从30变成33.003,J的改变量除以U的改变量等于3(0.003÷0.001),即偏导数dJ/dU为3。其实J关于U的偏导数等于J关于V的偏导数与V关于U的偏导数的乘积,即dJ/dU=dJ/dV*dV/dU=3*1=3。这种传导性计算在微积分里面我们称之为链式法则。同理,J关于参数b的偏导数dJ/db=dJ/dU*dU/db=3*2=6。dJ/db这个偏导数才是我们最终需要的,我们需要的是函数J关于参数a、b、c的偏导数。为了得到这三个偏导数,我们需要先计算出关于中间量V的偏导数然后再计算出关于中间量U的偏导数,最后计算出关于参数的偏导数,一步一步反向推进,这个过程就是一个反向传播的过程。大家可以自己计算一下关于a和c的偏导数,看自己掌握了没有,dJ/da等于3,dJ/dc等于9。
通常我们会将最终函数(在这里是J)的偏导数的符号进行简化,例如dJ/da可以写成da,将dJ/dU写成dU,当你看到db时你会知道它是dJ/db而不是dU/db。
6:如何计算偏导数:
本篇文章我将结合计算图来为大家讲解如何计算逻辑回归的偏导数。
通过这样不停的前向反向传播来训练参数。
上面讲述的是单个训练样本时如何计算逻辑回归的偏导数(训练样本―例如在训练识别猫的神经网络中,一张猫的图片就是一个训练样本),下面我给大家介绍多个训练样本时如何计算偏导数。
通过对前面文章的学习我们已经知道――成本其实就是多个样本的损失的平均值――m个样本的损失累加起来然后除以m就是成本。同理,多个样本时的偏导数等于每个样本的偏导数的平均值。
下图给出m个样本时计算偏导数的伪码。先将各个变量初始化为0,然后用一个for