机器学习(一)——单变量线性回归

监督学习与无监督学习

监督学习(Supervised learning),意指给出一个算法,需要部分数据集已经有正确答案。比如给定房价数据集,对于里面每个数据,算法都知道对应的正确房价,即这房子实际卖出的价格。算法的结果就是算出更多的正确价格。监督学习中的一种即回归问题,意指要预测一个连续值的输出,比如房价。虽然从技术上来说,一般把房价记到美分单位,所以实际还是个离散值,但通常把它看作实际数字,是一个标量值,一个连续值的数,而术语回归,意味着要预测这类连续值属性的种类。另一个监督学习的例子是:你能否估算出一个概率,即肿瘤为恶或为良的概率?专业地说,这是个分类问题。分类是要预测一个离散值输出,这里是恶性或良性。事实证明,在分类问题中,有时输出的值可能超过两种。监督学习中,对于数据集中的每个数据,都有相应的正确答案,(训练集)算法就是基于这些来做出预测。回归问题,即通过回归来预测一个连续值输出。分类问题,目标是预测离散值输出。

在无监督学习(Unsupervised learning)中没有属性或标签这一概念,也就是说所有的数据都是一样的,没有区别,所以在无监督学习中,我们只有一个数据集,没人告诉我们该怎么做,我们也不知道每个数据点究竟是什么意思,相反,它只告诉我们,现在有一个数据集,你能在其中找到某种结构吗?对于给定的数据集,无监督学习算法可能判定,该数据集包含两个不同的聚类,这就是所谓的聚类算法,而聚类只是无监督学习的一种。无监督学习,它是一种学习机制,你给算法大量的数据,要求它找出数据中蕴含的类型结构。

模型与代价函数

在监督学习中我们有一个数据集,这个数据集被称训练集(training set),因此对于房价的例子,我们有一个训练集包含不同的房屋价格,我们的任务就是从这个数据中学习预测房屋价格。现在我们给出经常使用的一些符号定义,我用小写的m来表示训练样本的数目,小写字母x来表示输入变量,往往也被称为特征量,用y来表示输出变量或者目标变量,也就是我的预测结果,使用(x, y)来表示一个训练样本,为了表示某个训练样本,我将使用x(i)与y(i)来表示,并且用这个表示第i个训练样本。所以这个(x(i), y(i))括号里的上标i不是求幂运算,只是一个索引,表示我的训练集里的第i行。一个监督学习算法的工作方式:假设有一个训练集里有房屋价格,我们把它喂给我们的学习算法,然后学习算法开始工作,输出一个函数,按照惯例,通常表示为小写h,h代表hypothesis(假设),h表示一个函数,输入是房屋尺寸大小,h根据输入的x值来得出y值,y值对应房子的价格,因此,h是一个从x到y的函数映射。当设计学习算法的时候,我们接下来需要去思考的是,怎样得到这个假设h,我们将会这么写:hθ(x)=θ01*x,为了方便,有时非书面形式也可以把hθ(x)写成h(x),这是缩写方式,但一般来说我会保留这个下标θ,所有这一切意味着我们要预测一个关于x的线性函数y,这就是数据集和函数的作用,用来预测,这里是y关于x的线性函数hθ(x)=θ01*x,这个模型被称为线性回归(linear regression)模型,另外,这实际上是关于单个变量的线性回归,这个变量就是x,根据x来预测所有的价格函数,同时,对于这种模型有另外一个名称,称作单变量线性回归,单变量是对一个变量的一种特别的表述方式,总而言之,这就是线性回归。

这些θ0、θ1、θi,我把它们称为模型参数,选择不同的参数θ0和θ1,我们会得到不同的假设函数。在线性回归中,我们有一个训练集,我们要做的就是得出θ0 θ1这两个参数的值,来让假设函数表示的直线尽量地与这些数据点很好的拟合。那么我们如何得出θ0 θ1的值,来使它很好地拟合数据的呢?我们的想法是:我们要选择能使h(x),也就是输入x时我们预测的值,最接近该样本对应的y值的参数θ0 θ1。所以,我们要尽量选择参数值,使得在训练集中,给出训练集中的x值,我们能合理准确地预测y的值。

图片3

让我们给出标准的定义:在线性回归中,我们要解决的是一个最小化问题,所以我要写出关于θ0 θ1的最小化,而且我希望这个式子极其小,我想要h(x)和y之间的差异要小。所以我想要做的是对所有训练样本进行一个求和,对i=1到i=m的样本,将第i号对应的预测结果,减去第i号房子的实际价格,所得的差的平方相加得到总和,而我希望尽量减小这个值,也就是预测值和实际值的差的平方误差和,或者说预测价格和实际卖出价格的差的平方。而为了让表达式的数学意义变得容易理解一点,我们实际上考虑的是这个数的1/m,因此我们要尝试尽量减少我们的平均误差,也就是尽量减少其1/2m,通常是这个数的一半。前面的这些只是为了使数学更直白一点,因此对这个求和值的二分之一求最小值,应该得出相同的θ0值和相同的θ1值来。因此,简单地说,我们正在把这个问题变成:找到能使我的训练集中预测值和真实值的差的平方的和的1/2m最小的θ0和θ1的值。因此,这将是我的线性回归的整体目标函数,为了使它更明确一点,我们要改写这个函数,按照惯例,我要定义一个代价函数。这里的这个公式,我们想要做的就是关于θ0和θ1,对函数J(θ01)求最小值,这就是我的代价函数(cost function),代价函数也被称作平方误差函数,有时也被称为平方误差代价函数。事实上,我们之所以要求出误差的平方和,是因为平方误差代价函数对于大多数问题,特别是回归问题,都是一个合理的选择,还有其他的代价函数也能很好地发挥作用,但是平方误差代价函数可能是解决回归问题最常用的手段了。

为了更好地将代价函数可视化,我将使用一个简化的假设函数,也就是θ1*x,我们可以将这个函数看成是把θ0设为0,所以我只有一个参数,也就是θ1,代价函数看起来与之前的很像,唯一的区别是现在h(x)等于θ1*x,只有一个参数θ1,所以我的优化目标是将J(θ1)最小化,通过利用简化的假设得到的代价函数,我们可以试着更好地理解代价函数这个概念,我们要理解的是这两个重要的函数:第一个是假设函数,第二个是代价函数,注意这个假设函数h(x)对于一个固定的θ1是一个关于x的函数,与此不同的是,代价函数J是一个关于参数θ1的函数,而θ1控制着这条直线的斜率。我将要指出的是,当我描绘出我的假设函数,我的横轴被标定为X轴,要注意的是,因为我的代价函数是关于参数θ1的函数,当我描绘我的代价函数时,横轴就是θ1,结果我们会得到这样一个点。对于不同的θ1你可以计算出这些对应的值,结果你会发现,你算出来的这些值,将得到一条这样的曲线,这就是J(θ)的样子了。学习算法的优化目标,是我们想找到一个θ1的值,来将J(θ1)最小化。

我们将更深入地学习代价函数的作用,还是把θ写成θ0、θ1的形式,便于这里我们要对代价函数进行的可视化,但现在我们有两个参数θ0和θ1,因此图像就会复杂一些了,当只有一个参数θ1的时候,我们画出来是这样一个弓形函数,而现在我们有了两个参数,那么代价函数仍然呈现类似的某种弓形,实际上这取决于训练样本,你可能会得到这样的三维曲面图,两个轴分别表示θ0和θ1,随着你改变θ0和θ1的大小,你便会得到不同的代价函数J(θ01)。对于某个特定的点(θ01),这个曲面的高度,也就是竖直方向的高度,就表示代价函数J(θ01)的值,不难发现这是一个弓形曲面。我们来看看三维图,这是这个曲面的三维图,水平轴是θ0、θ1,竖直方向表示J(θ01)。为了描述方便,我将不再像这样给你用三维曲面图的方式解释代价函数J,而还是用轮廓图来表示,contour plot或contour figure意思一样,下边就是一个轮廓图,两个轴分别表示θ0和θ1,而这些一圈一圈的椭圆形,每一个圈就表示J(θ01)相同的所有点的集合。如果你之前没怎么接触轮廓图的话,你就想象一个弓形的函数从屏幕里冒出来,因此最小值,也就是这个弓形的最低点就是这一系列同心椭圆的中心点。当然,我们真正需要的是一种有效的算法,能够自动地找出这些使代价函数J取最小值的参数θ0和θ1来。事实上,我们会遇到更复杂、更高维度、更多参数的情况,而这些情况是很难画出图的,更无法将其可视化,因此我们真正需要的是编写程序来找出这些最小化代价函数的θ0和θ1的值。

参数学习

我们已经定义了代价函数J,我想向你们介绍梯度下降(gradient descent)这种算法,这种算法可以将代价函数J最小化。梯度下降是很常用的算法,它不仅被用在线性回归上,它实际上被广泛的应用于机器学习领域中的众多领域。下面是问题概述,我们有一个函数J(θ0, θ1),也许这是一个线性回归的代价函数,也许是一些其他函数,要使其最小化,我们需要用一个算法来最小化函数J(θ0, θ1),就像刚才说的,事实证明,梯度下降算法可应用于多种多样的函数求解,所以想象一下如果你有一个函数J(θ0, θ1, θ2, …,θn) ,你希望可以通过最小化θ0到θn来最小化此代价函数J(θ0到θn),用n个θ是为了证明梯度下降算法可以解决更一般的问题,但为了简洁起见,我只用两个参数。下面就是关于梯度下降的构想:我们要做的是,要开始对θ0和θ1进行一些初步猜测,它们到底是什么其实并不重要,但通常的选择是将θ0设为0,将θ1也设为0,将它们都初始化为0,我们在梯度下降算法中要做的,就是不停地一点点地改变θ0和θ1,试图通过这种改变使得J(θ0, θ1)变小,直到我们找到J的最小值,或许是局部最小值。让我们通过一些图片来看看梯度下降法是如何工作的,我们希望最小化这个函数,所以我们从θ0和θ1的某个值出发,想象一下对θ0和θ1赋以某个初值,也就是对应于从这个函数表面上的某个起始点出发,所以不管θ0和θ1的取值是多少,我将它们初始化为0,但有时你也可把它初始化为其他值,现在我希望大家把这个图像想像类似这样的景色:公园中有两座山,想象一下你正站立在你想象的公园这座红色山上,在梯度下降算法中,我们要做的就是旋转360度,看看我们的周围并问自己,我要在某个方向上用小碎步尽快下山,如果我想尽快走下山,这些小碎步需要朝什么方向?如果我们站在山坡上的这一点,你看一下周围,​你会发现最佳的下山方向,大约是那个方向,好的,现在你在山上的新起点上,你再看看周围,然后再一次想想,我应该从什么方向迈着小碎步下山?然后你按照自己的判断又迈出一步,往那个方向走了一步,然后重复上面的步骤,从这个新的点,你环顾四周并决定从什么方向将会最快下山,然后又迈进了一小步,又是一小步,并依此类推,直到你接近局部最低点的位置。此外,这种下降有一个有趣的特点,第一次我们是从这个点开始进行梯度下降算法的,在这一点上从这里开始,现在想象一下,我们在刚才的右边一些的位置,对梯度下降进行初始化,想象我们在右边高一些的这个点,开始使用梯度下降,如果你重复上述步骤,停留在该点并环顾四周,往下降最快的方向迈出一小步,然后环顾四周又迈出一步,然后如此往复,如果你从右边不远处开始,梯度下降算法将会带你来到这个右边的第二个局部最优处。如果从刚才的第一个点出发,你会得到这个局部最优解,但如果你的起始点偏移了一些,起始点的位置略有不同,你会得到一个非常不同的局部最优解,这就是梯度下降算法的一个特点。

图片4

这是梯度下降算法的定义,我们将会反复做这些,直到收敛,我们要更新参数θj,方法是用θj减去α乘以这一部分。这个公式有很多细节问题,首先,注意这个符号:=,我们使用:=表示赋值,这是一个赋值运算符。具体地说,如果我写a:=b,在计算机专业内,这意味着不管a的值是什么,取b的值,并将其赋给a,这意味着我们让a等于b的值,这就是赋值。与此不同的是,如果我使用等号=,并且写出a=b,那么这是一个判断为真的声明,就是在断言a的值是等于b的值。这里的α是一个数字,被称为学习速率(learning rate),在梯度下降算法中,它控制了我们下山时会迈出多大的步子,因此如果α值很大,那么相应的梯度下降过程中,我们会试图用大步子下山,如果α值很小,那么我们会迈着很小的小碎步下山。最后,是公式的这一部分,这是一个微分项。现在,在梯度下降算法中,还有一个更微妙的问题,我们要更新θ0和θ1,当j=0和j=1时会产生更新,所以你将更新J、θ0还有θ1,实现梯度下降算法的微妙之处是,在这个表达式中,如果你要更新这个等式,你需要同时更新θ0和θ1。我的意思是在这个等式中,我们要这样更新:θ0:=θ0 – 一些东西,并更新:θ1:=θ1 – 一些东西。实现方法是,你应该计算公式右边的部分,通过那一部分计算出θ0和θ1的值,然后同时更新θ0和θ1

图片5

让我进一步阐述这个过程,在梯度下降算法中,这是正确实现同时更新的方法:我要设temp0等于这些,设temp1等于那些,所以首先计算出公式右边这一部分,然后将计算出的结果一起存入temp0和temp1之中,然后同时更新θ0和θ1,因为这才是正确的实现方法,与此相反,右面是不正确的实现方法,因为它没有做到同步更新,在这种不正确的实现方法中,我们计算temp0,然后我们更新θ0,然后我们计算temp1,然后我们将temp1赋给θ1。右边的方法和左边的区别是:让我们看这里,就是这一步,如果这个时候你已经更新了θ0,那么你会使用θ0的新的值来计算这个微分项,所以由于你已经在这个公式中使用了新的θ0的值,那么这会产生一个与左边不同的temp1的值,所以右边并不是正确地实现梯度下降的做法。实际上同步更新是更自然的实现方法,当人们谈到梯度下降时,他们的意思就是同步更新,如果用非同步更新去实现算法,代码可能也会正确工作,但是右边的方法并不是人们所指的那个梯度下降算法,而是具有不同性质的其他算法,由于各种原因,这其中会表现出微小的差别,你应该做的是,在梯度下降中真正实现同时更新。

参数α术语称为学习速率,它控制我们以多大的幅度更新这个参数θj,第二部分是导数项,而我要做的就是,给你一个更直观的认识,这两部分有什么用,以及为什么当把这两部分放一起时,整个更新过程是有意义的。为了更好地让你明白,我要做是用一个稍微简单的例子,比如我们想最小化的那个函数只有一个参数的情形,所以假如我们有一个代价函数J,只有一个参数θ1,那么我们可以画出一维的曲线。现在我们已经对这个点上用于梯度下降法的θ1进行了初始化,想象一下在我的函数图像上,从那个点出发,那么梯度下降要做的事情是不断更新θ1等于θ1减α倍的d/dθ1J(θ1)这个项,可能你想问为什么我改变了符号,之前用的是偏导数的符号,在数学中,我们称这是一个偏导数,这是一个导数,这取决于函数J的参数数量。好的,那么我们来看这个方程,我们要计算这个导数,求导的目的,基本上可以说取这一点的切线,也就是说直线的斜率,现在,这条线有一个正斜率,也就是说它有正导数,因此我得到的新的θ1更新后等于θ1减去一个正数乘以α,α也就是学习速率是一个正数,所以我要使θ1减去一个东西,相当于我将θ1向左移,使θ1变小了,我们可以看到这么做是对的,因为实际上我往这个方向移动确实让我更接近那边的最低点,所以,梯度下降到目前为止似乎是在做正确的事。让我们同样再画出函数J(θ1)的图像,而这次,我们把参数初始化到左边这点,同样把这点对应到曲线上,现在,导数项d/dθ1J(θ1)在这点上计算时,这个导数是这条线的斜率,但是这条线向下倾斜,所以这条线具有负斜率,或者说,这个函数有负导数,因此,这个导数项小于等于零,所以当我更新θ时,θ被更新为θ减去α乘以一个负数,因此我是在用θ1减去一个负数,这意味着我实际上是在增加θ1。因此,我们将从这里开始增加θ,似乎这也是我希望得到的,也就是让我更接近最小值了。让我们接下来再看一看学习速率α,如果α太小或α太大,会出现什么情况?如果α太小了,那么我要做的是要去用一个比较小的数乘以更新的值,所以最终它就像一个小宝宝的步伐,这是一步,然后从这个新的起点开始,迈出另一步,但是由于α太小,因此只能迈出另一个小碎步,所以如果我的学习速率太小,结果就是只能这样像小宝宝一样一点点地挪动,去努力接近最低点,这样就需要很多步才能到达最低点,所以如果α太小的话,可能会很慢,因为它会一点点挪动,它会需要很多步才能到达全局最低点。如果α太大,那么梯度下降法可能会越过最低点,甚至可能无法收敛。 假设你将θ1初始化在局部最低点,结果是局部最优点的导数将等于零,因为它是那条切线的斜率,而这条线的斜率将等于零,因此,此导数项等于0,所以,在你的梯度下降更新过程中,你有一个θ1,然后用θ1减α乘以0来更新θ1,所以这意味着你已经在局部最优点,它使得θ1不再改变,也就是新的θ1等于原来的θ1。因此,如果你的参数已经处于局部最低点,那么梯度下降法更新其实什么都没做,它不会改变参数的值,这也正是你想要的,因为它使你的解始终保持在局部最优点,这也解释了为什么即使学习速率α保持不变时,梯度下降也可以收敛到局部最低点。在梯度下降法中,当我们接近局部最低点时,梯度下降法会自动采取更小的幅度,这是因为当我们接近局部最低点时,导数值会自动变得越来越小,所以梯度下降将自动采取较小的幅度,这就是梯度下降的做法,所以实际上没有必要再另外减小α。

我们要将梯度下降和代价函数结合,我们将要做的就是,用梯度下降的方法,来最小化平方误差代价函数。为了使梯度下降,我们需要的关键项是这里这个微分项,所以,我们需要弄清楚这个偏导数项是什么,这两项分别是j=0和j=1的情况,因此我们要弄清楚θ0和θ1对应的偏导数项是什么,我只把答案写出来。

图片6

在我们算出这些微分项以后,现在可以将它们放回我们的梯度下降算法,所以这就是专用于线性回归的梯度下降,反复执行括号中的式子直到收敛,θ0和θ1不断被更新,都是加上一个-α/m乘上后面的求和项。所以这就是我们的线性回归算法:

图片7

我们用梯度下降解决问题的一个原因是,它更容易得到局部最优值。但是,事实证明,用于线性回归的代价函数总是这样一个弓形的样子,这个函数的专业术语是凸函数(convex function)。不正式的说法是,它就是一个弓形的函数,因此这个函数,没有任何局部最优解,只有一个全局最优解,并且无论什么时候,你对这种代价函数使用线性回归梯度下降法得到的结果,总是收敛到全局最优值,因为没有全局最优以外的其他局部最优点。实际上,我们刚刚使用的算法,有时也称为批量梯度下降,这个名字“批量梯度下降”指的是在梯度下降的每一步中,我们都用到了所有的训​​练样本,在计算微分求导项时,我们需要进行求和运算,所以在每一个单独的梯度下降中,我们最终都要计算这样一个东西,这个项需要对所有m个训练样本求和,因此,批量梯度下降法这个名字说明了,我们需要考虑所有这一“批”训练样本。而事实上,有时也有其他类型的梯度下降法,不是这种“批量”型的,不考虑整个的训练集,而是每次只关注训练集中的一些小的子集。如果你之前学过线性代数,你应该知道有一种计算代价函数J最小值的数值解法,不需要梯度下降这种迭代算法,这是另一种称为正规方程(normal equations)的方法,实际上在数据量较大的情况下,梯度下降法比正规方程要更适用一些。



发表评论

电子邮件地址不会被公开。 必填项已用*标注