我们将看到模型是什么样子,而更重要的是我们将看到监督学习整体逻辑是什么样子。
现在我们来定义一些机器学习中常用的符号。
我们使用小写字母m来表示训练样本的样本总数。
我们使用小写字母x来表示输入变量,不过通常我们称之为特征。
最后,我们使用小写字母y来表示输出变量或者叫做目标变量。
使用这三个符号标记,我们可以使用(x,y)来表示一个训练样本。
在我们右侧这个表格中,每一行代表的就是一个训练样本,而如果我们具体指某一个样本时,我们可以使用(x(i), y(i))来表示。这里的上标i,表示的是第i个样本。请注意,在数学中,上标常常用于表示幂运算,即x的i次方,所以这里我们特意使用了括号,特指我们这个是第i个样本,而不是要进行什么幂运算。
我们来看看整个监督学习的基本结构。
首先我们得有一个训练集,比如我们的夫子庙房价的训练集。然后我们将训练集提供给我们的学习算法。
而我们的学习算法的职责就是输出一个确定的函数,这里称之为"假设",但它实际上是一个函数,可以使用英文小写字母h表示,它是英文假设hypothesis的首字母。而这个最终的假设,实际上就是一个函数,它的作用在于,接受输入变量,比如输入房子的面积,然后输出房价的预测值。
所以,所谓假设h,实际上就是将输入变量x映射到输出变量y的一个函数。
假设这个词的含义可能有些让人觉得不是那么自然。这种不自然并非错觉,这个名字确实不是在这个场合中最贴切的名字,这实际上是历史原因,因为输入变量到输出变量的映射,是线性的?还是二次的?甚至是其他多项式的?这个是不确定的,也就是说这个映射本身的形式实际上是不知道的,那么我们使用线性函数实际上就是在做一种假设,亦即我们假设输入变量到输出变量的映射是线性的。
这是一种解释,而且在现在的机器学习中,假设一词已经算是标准的称呼了。我希望这能够缓解大家对于假设一词的不自然感受。不过至于究竟为什么大家这么称呼,其实并不重要。
重要的是,我们如何表示假设呢?或者说如何表示这个映射呢?比如,我们的这个房价预测的例子,我们认为它应该是一条直线,更标准的说法是线性。
那么我们为什么选择这么个线性模型呢?实际上在现实工作中,我们可能会选择更加复杂的函数,比如非线性函数。但是我们的这个例子是个非常简单的例子,而且仅有一个输入变量,因此我们以简单的例子作为入门还是非常合适的。当然,我们后面的课程会使用更加复杂的模型,也会介绍更加复杂的学习算法。
对于我们目前这个简单的模型,我们称之为线性回归,而进一步,对于我们这种仅仅有一个输入变量的情况,我们称之为一元线性回归,或者单变量线性回归。
代价函数(英文术语是cost function)的东西。它将帮助我们找到最能拟合我们数据的直线。
在线性回归中,我们有一个训练集,比如一直在说的夫子庙房价的数据集。我们简单回顾下,小写字母m表示训练集中的样本量,我们这里是20.
而我们选择的假设,也就是函数形式是线性的,就是我们这里的这个式子。
我们式子中的θ0和θ1被称为模型的参数,因为它们一定被确定了,那么整个模型也就确定了,那么也就可以用来对新的样本进行预测了。
那么,我们现在要讨论的是,如何选择合适的参数值,也就是θ0和θ1的值。
使用不同的θ0和θ1,我们会得到不同的假设或者函数。
在线性回归中,我们有一个训练集,比如我们在左侧中绘制的这个散点图。
我们想要做的是,找到适当的的θ0和θ1,使得我们的直线能够很好地拟合我们的数据。
那么问题在于,我们如何才能找到这条线呢?更具体地说,我们如何才能找到这条线对应的θ0和θ1呢?
解决这个问题的思路非常直观,我们选择的θ0和θ1,从而定义的直线,对于样本集中的x而言,其得出的y值应当尽量地接近训练集中该x对应的真实y值。不过考虑到,我们的训练集中并非只有一个样本,因此在我们需要考虑所有的样本,比如我们希望通过θ0和θ1确定的直线对于训练集中的所有x产生的y值,和它们真实的y值总体相差最小。
我相信这个想法是直观的,也是符合直觉的。不过如果我们希望计算机能够理解,我们必须将这个想法正式化一些。
我们来看它的正式化表达式。这一堆看上去很多,很复杂,但实际上它仅仅是表达了我们解决线性回归问题的想法而已。
所以整个式子想要表达的含义就是:
找到θ0和θ1的值,使得预测值和真实值之间的平均差异最小。
这个式子确实有点庞大,我们可以稍微简练一些地这么写,即我们定义J(theta0, theta1),表示整体的损失,它更加学术范的名称叫做均方误差。然后我们的目标是找到使得J最小化的theta0和theta1.
再顺便说一下,我们这里使用了均方误差来作为我们衡量预测值和真实值之间差异的指标,但它并非唯一的,这一点请大家不要有任何想当然。事实上,我们可以定义任何一种能够衡量预测值和真实值之间差异的指标作为损失函数,而均方误差是最简单的一种,而且对于大多数回归场景而言都能表现出不错的性能。不过后面我们还会介绍其他类型的损失函数。
好,现在我们已经正式化了回归问题的代价函数了。但可能大家对它还没有特别直观的认识,我们接下来讨论下它到底是在计算什么东西,以及为什么我们想要使用它,
前面我们给出了代价函数的数学定义。
接下来我们将细致且直观地研究下代价函数到底是在干什么,而且我们为什么要使用它。
我们想要使用一条直线来拟合我们的数据,所以我们有这样的假设,也就是函数形式,它有两个参数,分别是θ0和θ1。不同的θ0和θ1取值会使得我们得到不同的直线。
那么不同的直线对数据的拟合效果我们使用这个代价函数来表示,而它也是我们的优化目标,就是想让它最小化。
为了能够更好地可视化表达代价函数J,我们把我们的假设进一步简化,就像下面这个式子。在这个式子中,我们忽略掉θ0,实际上就是将θ0设置成0。然后我们的假设函数就是简单的θ1乘以x。
所以,现在我们仅有一个参数θ1,而我们的代价函数和之前差别不大,仅仅是hx现在等于θ1乘以x罢了。也正因此,我们的优化目标就是找到可以最小化j的theta1.
在图形上,我们简化了的假设即theta0等于0,其实就是穿过原点的一条直线。通过这个简化了的假设以及它所对应的代价函数,让我们来看看这些式子实际上都在干什么。
我们这里其实想要理解的是两个关键的函数:
第一个就是假设函数,而第二个则是代价函数。
所以大家请注意,在左侧,是我们的假设hx。对于一个固定的θ1,它是关于x的函数。所以假设是关于房子大小x的一个函数。
相对的,代价函数J,它是关于参数theta1的函数,而这个theta1其实是假设函数hx的斜率。
我们下面来看看不同的theta1对二者都会有怎样的影响。
我们先来看假设函数。在左侧,假如我们的训练集只有三个点,分别是(1,1), (2,2)和(3,3)。我们如果选择theta1等于1,那么我们的直线就像这里画的一样,完美地经过每一个点。我们这里强调一下,我们画的这条线的含义是房子大小和房价之间的关系。那么在有了这条直线后,我们想要做的其实是,这条直线对应的代价J是多少?
所以,我们来计算一下当theta1等于1的时候,J的取值是什么。我们的代价函数的定义是:
所以当theta1等于1的时候,J(theta1) = J(1) = 0。对应回假设函数,这也符合我们的认识,因为直线完美地穿过了所有三个样本点(1,1) (2,2) (3,3),所以拟合值和真实值完全相等,这样的拟合不存在损失,所以J(1) = 0。
这里再次强调一下,右侧的这个图是代价函数J,它是关于参数theta1的函数,因此它的横轴是theta1,纵轴是J。左右两侧表达的东西在概念上是完全不同的两个东西,千万不能搞混。
我们theta1取1,是随机选择的,运气不错使得我们的代价函数是0。不过theta1的值域当然不仅仅是1。
那么假如我们运气不是那么好,theta1取值是0.5呢?
如果我们的theta1取值是0.5,那么假设函数的直线的斜率就是0.5,那么它在图形上会经过(2,1)点。那这时,这条直线对应的拟合代价函数值又是多少呢?
我们可以不断地变更theta1的取值,我们就可以得到不同theta1对应的拟合直线,并且也可以得到其对应的拟合代价函数J的值。比如,如果我们取theta1等于-0.5,那么相应的J的值大约是5.25。我们持续不断地这么做,我们就能够大概画出J的图形。
现在,请大家回想一下J是什么。J是代价函数,它表征的是假设函数对训练集样本数据拟合的均方误差,也就是说它的值越小越好。所以J是我们最小化的目标。而能影响J的仅有参数theta而已,在这里theta只有一个,那就是theta1。
对于我们这个简单的例子而言,我们在theta1=1的时候,J最小,等于0,也就是theta1=1产生的假设函数能够最好地拟合我们的数据。所以,通过这个例子,我们看到通过调整theta最小化J,是能够找到最优的拟合函数的。
这就是假设函数和代价函数之间的关系了。
我们前面理解了下简化的代价函数的意义是什么。在接下来,我们来理解下原来的那个代价函数。
我们简单地来回顾下我们的假设,
这次我们不再将theta0设置成0了,我们现在将同时可视化theta0和theta1. 和理解简化版时一样,我们希望理解假设函数H和代价函数J。
左侧仍然是我们房价的训练集。我们这里的直线对应的方程是如图所示,也就是theta0等于50,theta1等于0.06。
现在,我们想计算这种设置条件下的代价函数,像之前一样,我们在右侧来画画看。在平面上,我们的横轴是theta1,纵轴是代价函数J,我们没办法表示theta0了!因为我们有三个变量:theta0,theta1和J,然而二维平面只有两个轴,没办法同时表示三个变量。所以这种时候就不得不在三维空间中绘制它们了。
现在,我们有两个参数了,这使得我们的代价函数在三维图形上类似一个碗型。根据不同的训练集,我们会得到不同的碗型,可能是个完美的碗型,也有可能是个狭长的碗。
比如我们现在看到的这个三维图形,
所以,底部平面的任何一个点表示了一个theta0和theta1,而我们的这个三维图形在该点上的垂直高度即代表了相应的代价函数值J。
不过虽然这样的三维图形看上去很好,但,我们可以借助康托图,也就是等高线图来描述。
我们现在来看看具体的例子。左边是我们的训练集以及随便画的一条拟合直线,右侧则是代价函数J的等高线图。
我们注意到,这幅图的两个轴分别是我们的两个参数:theta0和theta1. 然后这里有一些椭圆形的线条。这里的每一个椭圆形的线条表示的是,它们的J值都是相等的[随便找一个椭圆线,画三个点,解释不通的theta对应的J都相等]。
这些曲线实际上是前一张ppt中的碗型三维图形的投影,在看到这张等高线图的时候我们可以想象一个三维的碗型图形,它稍微有些窄,越往里J值越小。而最小点就是这个点。
这就是等高线图,这种图相较于三维立体图更加易于可视化我们的代价函数J。
我希望大家已经对代价函数J有了比较好的理解,他们是如何与不同的假设函数联系在一起的,拟合越好的假设函数对应在等高线上的J值点离最小值点也就越近。
当然,这些只是让我们直观上理解了代价函数与假设函数之间的关系,或者说是代价函数与模型参数之间的关系。而我们的学习算法所需要做的,实际上就是找到能够使我们代价函数J取值最小的那些参数。
虽然,直接绘图似乎能够直接找到最优的参数,但对于复杂问题,特别是参数更多的情况,我们实际上是无法绘图的,而且即使是仅含有两个参数的情况,我们在绘图之后仍然需要人工读取对应的参数值。而这显然不是我们想要做的。我们想要做的是:通过迭代能够不断地修正参数的值,使得J的取值不断向最小值渐进。最后在最小值点或者离最小值点不远的点停下来,并直接告知我们参数的取值。
Parameter learning
Gradient Descent
我们在前面已经定义了代价函数J。现在我们开始介绍一个被称为梯度下降,用于最小化代价函数的算法。
实际上,梯度下降是一种通用的算法,而且并不仅仅用于线性回归。它在整个机器学习中都被广泛地使用。
在后面的课程中,我们还会使用梯度下降来最小化其他类型的函数,而不是仅仅是线性回归的代价函数J。
我们首先介绍对于任意函数,梯度下降的含义是什么,然后我们针对一直讨论的线性回归问题应用梯度下降。
首先,这里是我们问题。
我们这里假设有某个函数J(theta0, theta1),它可能是某个线性回归问题的代价函数,也有可能是其他什么我们想要最小化的函数。
那么我们的目标是希望有一个算法能够求得最小化J(theta0,theta1)的参数theta0和theta1.
这里我们说一下,梯度下降可以被用于更加广泛地函数。所以我们可以想象,我们可以有一个以theta0,theta1,theta2一直到theta n为参数的函数,然后我们希望最小化这个函数。而梯度下降算法也可以被用于求解它。所以,梯度下降实际上可以被认为是用于求解函数最小值的一种通用算法。
为了便于理解,我们这里假设我们的函数仅仅有两个参数。
那么所谓的梯度下降的逻辑是什么呢?简单来说它只有两条:
1. 初始时,猜一下theta0和theta1的取值,其实就是随机生成一个theta0和theta1.
2. 接着,要做的是,不断地小幅改变theta0和theta1的值,试着降低J(theta0, theta1),直到收敛到最小值点,或者是一个局部最小值点。
梯度下降的基本思路,我们可以以图的形式更加直观地看看梯度下降到底在干什么。
比如我们想要最小化的是这么一个函数。注意下坐标轴,这是theta0,这是theta1,它们在水平平面上,垂直的坐标轴是我们想要最小化的函数J。这里的彩色曲面就是函数J在不同的theta0和theta1时的值,即曲面里水平面的距离就是J的取值。
现在,我们暂时抛开函数。可以试着想象一下,这是一片户外休闲的山林。这里大约有两座小山,这里似乎是一小片、一小片的平原,然后还有几处洼地。
那么我们想要做的是下山。实际上,在梯度下降算法中,我们做的就是环顾四周,试着找到能够最快下山的方向,然后小步地移动一下,然后再次环顾找到最快下山的方向。这里我们需要注意,在下山的时候我们实际上并不知道整个环境的情况,我们只能看到周围非常有限的一块很小的区域,你可以认为整片区域实际上被雾气所笼罩。
所以,我们并不知道有两座山,有几处洼地,否则的话我们直接朝着洼地方向走就好了。
所以,因为浓雾,我们对整个地形都没有什么认识,我们只能看到周围比如一米的环境。在这种时候,我们如何才能最快地下山呢?
用俗话说就是:走一步看一步。只是我们怎么看呢?我们肯定是看当前所处一米附近,哪个方向下山最快,对不对?即,在一米范围内哪个方向下山最快,我们就沿着哪个方向走一步。我们走完这一步以后就能看见新的一米范围的情况了,然后再看看四周哪个方向下山最快,然后再走一步。
这个策略实际上就是所谓的贪心,在当前状态下尽可能地朝着目标前进。这个过程也就是梯度下降算法的最核心思想。
梯度下降有一个很有趣的性质。
这是我们第一次运行梯度下降的起始点。现在呢,我们假如在另一个地方,以这一点作为起始点,那么我们重复之前的贪心策略,走一步看一步地尽力最快速地下山。这次我们不再到达上一次的洼地,而是到了一个新的洼地,或者说是另一个局部最小点。
所以,如果我们从第一次的点出发,我们最终会到达这个局部最小点,但是如果我们稍微从一个不同位置出发,我们又会到达一个完全不同的局部最小点。这其实就是梯度下降的一个性质,我们后面会再提到。
这就是梯度下降的直观解释了,我希望这种图形的方式能够帮你很好地理解什么是梯度下降,以及它的核心思想。
让我们来看看梯度下降对应的数学知识,毕竟直观理解并不能让计算机理解,想让计算机理解,我们需要更加形式化地描述这个过程。
其实梯度下降算法非常简单,我们仅仅需要不断地重复一种操作,直到收敛即可。这个简单的操作就是不断以这个式子更新theta j即可。这个式子实际上有不少细节,我们一点点来看。
首先,这个符号":=",指的是赋值操作。所以简单地说,a := b,它的含义就是使用b的值来覆盖a原有的值。这个操作完成以后,a的值就是b的值,就是所谓的赋值了。如果我们省略了:号,那么它在计算机领域内的含义就是判断二者是否相同了。所以,这就是赋值。
接下来的这个alpha,它其实是一个数字,被称为学习率。alpha干的事情基本上就是控制下我们下山时的每一步的步长。因此,如果alpha非常大,那么它会使得我们梯度下降过程变得非常激进,因为每一步都会走的比较大。而如果alpha比较小,那么会导致较为保守的步长,使得我们梯度下降的速度较慢。我们后面还会回来讨论下alpha,以及如何设置alpha。
最后,我们再来看看这一项,这是一个微分项。暂时我们不讨论它,后面我会导出这个微分项,并且告诉大家它到底是什么。
对于梯度下降我们再额外需要说的就是我们要更新的是什么。当然是theta0和theta1了,对不对。所以这个式子里面的j的取值就是0和1了。所以,我们要更新两个值,theta0和theta1。在更新的时候,正确的方式是同步地更新二者。同步的含义在于,我们使用theta0减去某些东西来更新theta0,一并使用theta1减去某些东西来更新theta1.看看左下角的实现可以更加明确地表达什么是同步更新。
这里注意到,我们更新了theta0以后,在更新theta1的时候,J(theta0,theta1)并没有改变,所以当我们更新theta1的时候并不受theta0更新的影响。当我们明确了theta0和theta1会变更成什么数值以后,我们再实际地更新theta0和theta1.
注意,当我们先更新theta0以后,对于theta1的更新而言,J已经变了,它的theta0已经发生了变更,这就不再是同步更新了。实际上这种非同步更新,并不是对于下山的时候找到最佳方向的正确实现。所以,一般我们说梯度下降,我们潜在地都在说同步更新。
如果非要使用非同步更新,可能算法也能走运地工作起来,但它是缺乏坚实的理论支持的。甚至,这种非同步更新的算法都不是梯度下降。所以,仅仅是这一点点小的区别也会使得我们的代码做的事情完全不同。
好,这就是整个梯度下降算法的轮廓了。除了微分项以外,我希望大家对整个梯度下降有了至少概括性地了解。而微分项,实际上可以被理解为下山的方向。
Gradient Descent Intuition
前面我们讨论了梯度下降的数学定义。现在让我们深入地来看看这个算法到底在干什么,以及梯度下降的策略为什么是合理的。
我们前面对这个微分项没有做足够的解释,所以大家现在可能对它还有点陌生。不过我们现在要做的就是解释他。
为了更加方便直观地解释他们,我们使用一个稍微简单一点点的例子,那就是我们最小化一个只有一个参数的函数。
所以,比方说,我们有一个代价函数J,它仅有一个参数,theta1,就像我们之前讨论代价函数时简化的一样。这样,我们就可以非常容易地在二维平面上绘图来直观地理解梯度。
比如这是我们的函数,J(theta1)。横轴是我们的theta1.纵轴是我们的代价函数J。
但是微分在这一点上的含义其实是,其切线的斜率,其实就是取他的tan值。在高中数学知识中,我们称它为求导。
所以,微分其实就是该点的切线的斜率。斜率的计算非常简单,就是这个高度除以这个水平长度。现在我们看,这条直线的斜率是一个正数,所以在该点上的微分是一个正数。因此,我们这里更新theta1,也就是theta1原来的值减去alpha乘以一个正数。我们的学习率alpha一直都是正数,所以总体而言,我们的更新就是theta1减去某个正数,即theta1会变小,在图上也就是它会向左移动。这么做是正确的,因为我们就是希望theta1向这个方向移动,这样会使得我们的J变小,向最小值点靠近。
因此,这么看,我们的梯度下降算法干的不错,确实能帮我们通过修改theta1来降低代价函数J,不断地向着J的最小值推进。
那么我们再来看看另一种情况。
这一次,我们假如theta1取值在J的最小值点的左侧。微分项的定义没有变,仍然是这一点的切线的斜率。不过跟前一次不同的是,这次它的斜率是一个负值了。也就是说,在该点,微分项是一个负值。因此,梯度下降算法在更新theta1的时候,是theta1减去alpha乘以一个负值。这意味着我们会增大theta1. 因为负负得正,更新的时候实际上是给原来的theta1增加了一些。所以,theta1会向着右侧推进。也就是越来越接近我们的最小值点。这当然就是我们希望的。
所以不管参数theta1是在最小值点的哪一侧,梯度下降算法都能够向着最小值点靠近。
以上就是我们对梯度下降算法中的微分项的直观解释。
如果alpha很小,我们的算法更新会使得我们的更新项很小,也就是更新步长很小。这会导致我们每次只更新一点点。原本只需要一步的更新,现在因为alpha很小,可能需要好几步才能走完。所以,整个梯度下降就会需要非常多次更新才能到达最小值点,所以从程序运行来看,它需要非常多的时间来迭代,会非常耗时。
那么,如果alpha太大呢?alpha太大导致的情况比alpha太小更加严重,它可能会错过最小值点,无法收敛,甚至使得J的值发散,变得越来越大。
假如,它其实离最小值点已经很近了,它的梯度让我们的更新方向向右,但是如果我们的学习率alpha太大,这导致我们的步长非常大,可能就直接越过了我们的最小值点,然后在新的这一点,我们的梯度比之前大一些,这样,alpha乘以这里的梯度,得到的步长就更大,这样就再一次跨越了最小值点,而且比原先那个点离最小值点更远了,这个过程会不断地重复,使得我们离最小值点越来越远,代价函数J的值越来越大。
我们现在来看一个有点意思的问题。假设我们运气很好,初始化的时候theta1直接就是一个局部最小点了,那么这时候梯度下降会怎么做呢?
比如我们初始化在了这个点,而这个点恰好就是一个局部最小点。
其实,在局部最小点,我们的微分项就是0,因为它的切线实际上是跟水平轴平行的,它的斜率是0。所以更新步长就是0,那么theta1就不会更新。这意味着,如果theta1已经在局部最小点了,那么它就不会被更新。所以,如果我们的参数已经使得代价函数J的值最小了,那么梯度下降就不会更新这些参数,会将我们的参数一直留在局部最小点。
这也解释了为什么梯度下降可以收敛到局部最小值点。
比如我们右侧有一个代价函数,我们希望最小化他。
比如我们初始化了在这一点,如果我们使用梯度下降往前走一步,也会我们会到这一点。然后我们再迭代一下,会往下再走一点。不过每一步都会比前一步的幅度要小一些。
这是因为随着迭代,我们不断地接近最小值点,切线的斜率是越来越小的,也就是我们的梯度下降中的微分项的值是在不断减小的,因此如果学习率alpha是固定的,那么这里的更新步长其实是越来越小的。
所以,越接近最小值点,我们的步长就越小,慢慢地向最小值点挺近。最终到达最小值点。而当我们达到最小值点以后,梯度就是0了,即切线斜率就是0,所以参数theta1就不再更新了,就停在了最小值点。
到这里,我们对通用梯度下降就介绍完了。
接下来,我们来看看对于显现回归问题的代价函数的最小化,梯度下降算法是怎么工作的。
Gradient Descent For Linear Regression
前面我们讨论了梯度下降算法,我们也讨论了线性回归模型以及均方误差代价函数。
现在我们已经有了足够的知识,可以将它们放在一起,这样我们就有了一个用于线性回归的算法了。
这里是我们之前一直讨论的东西。左侧是梯度下降算法,右侧是线性回归的假设函数h以及它的代价函数J。
我们将采用梯度下降算法来最小化我们的均方误差代价函数。
梯度下降:
线性回归:
为了能够把我们梯度下降算法的这个式子转成代码,我们重点是需要把这里的微分项给算一下。所以我们需要搞明白对于我们这个均方误差代价函数而言,它的微分项是什么,然后将它放到梯度下降算法中。
我们来看看梯度下降在这里是怎么工作的。
我们之前在讨论梯度下降的时候说过这个算法的一个问题在于,初始点的不同会造成最终可能会收敛到不同的局部最小值点。
不过对于线性回归问题的代价函数而言,它的代价函数总是一个碗型的,专业术语叫做凸函数。
这里我不打算深入讨论凸函数这个概念。不过凸函数的一种非正式理解就是它是一个类似这样的碗型,它不会有任何局部最小点,而只会有全局最小点。所以,梯度下降在这种代价函数上,我们最终总会收敛到全局最小点。那么,现在让我们看看它的具体表现把。
像我们之前做的一样,左侧是我们的假设函数hx,它是关于特征x的函数。右侧是代价函数J的等高线图。
在这里,我们看到初始化的时候,这条线的斜率大约是-0.2,y轴的截距是150,它们对应的代价函数J的取值以小红叉的标志显示在这里。它距离全局最小点差距不小,所以这个代价还是很大的,当然我们在左侧的图中也能看出来,这条直线的拟合效果非常差。
这时候,我们的梯度下降算法会要求我们的theta0和theta1沿着梯度最大的方向移动,可能就移动到了这个小红叉所在的点。这时候theta0的取值大约是100,theta1的取值是-0.15,它们对应的拟合直线如左图。
这里我需要提醒一下大家,在梯度下降的时候,我们的算法其实对左图没有任何认知,它一直在右图上工作,一直试图在对theta0和theta1进行修正使得J越来越小,直至到达最小值点。
所以,这里如果非要将两个图联系起来的话,我倾向于说梯度下降在右图上工作,并导致了左图中直线的变化,这个变化是积极的,因为它使得直线对数据的拟合更加好了。虽然当前的这条直线对数据的拟合仍然不够好,但至少比前一条直线要好。
代价函数的值更小了,相对应的直线相较前两条直线也更加能够拟合数据了。但仍然不够。梯度下降算法还会继续迭代。
直到迭代到接近最好到拟合直线。
最后,我们说一下, 我们这里使用的梯度下降,它更加确切地名字叫做批量梯度下降(batch gradient descent)。它的函已是,每一次我们梯度下降的更新都需要计算所有样本的梯度。这对于拥有很大训练集的问题而言可能存在性能问题,因为我们的算法是迭代型的,每次迭代需要计算所有的样本。
不过,实际应用中,梯度下降的每一步并非必须要依赖全体训练样本,每走一步只看一小部分样本也是可以的,这种常常被称为小批量梯度下降(mini-batch gradient descent)。
当然,每次也可以只计算一个样本,这样迭代得更快,但也会使得迭代显得更加不稳定。这种被称为随机梯度下降。
我们会在程序练习中看到批量梯度下降和随机梯度下降的区别。
好,以上就是线性回归梯度下降的全部内容了。
如果你以前学习过更高级一点的线性代数的话,那么你可能知道有一些可以直接求解代价函数J最小值的方法,而不需要通过一个类似于梯度下降的迭代算法来解。
在后面的课程中我们也会讨论到这样的方法,这种方法被称为正规方程。但是梯度下降相较于这种方法在更大的数据集上拥有更好的伸缩性。
而且,梯度下降是一种通用的求函数最小值的方案,它在不同的领域中都可以被使用,而且也在不同的机器学习算法中被大量使用。
不管怎样,都恭喜大家掌握了第一个机器学习算法,而且可以确定的是你已经理解了本质。