李宏毅机器学习笔记第二章:回归案例分析
这章内容真的太多了(灬ꈍ ꈍ灬)
回归的定义和应用实例
回归定义:
回归(regression)就是找到一个函数function,通过输入特征x,输出一个数值scalar
应用实例:
a)股市预测(Stock Market Forecast):
输入:过去10年股票的变动、新闻咨询、公司并购咨询等
输出:预测股市明天的平均值 。
b)自动驾驶(Self-driving Car):
输入:无人车上的各个sensor的数据,例如路况、测出的车距等
输出:方向盘的角度
c)商品推荐(Recommendation)
输入:商品A的特性,商品B的特性 输出:购买商品B的可能性
d)Pokemon精灵攻击力预测(Combat Power of a pokemon):
输入:进化前的CP值、物种(Bulbasaur)、血量(HP)、重量(Weight)、高度(Height)
输出:进化后的CP值
案例应用研究
Estimating the Combat Power(CP) of a pokemon after evolution(预测宝可梦进化后的CP值)
确定Scenario、Task和Model
首先根据已有的data来确定Scenario,我们拥有宝可梦进化前后CP值的这样一笔数据,input是进化前的宝可梦(包括它的各种属性),output是进化后的宝可梦的CP值;因此我们的data是labeled,使用的Scenario是Supervised Learning。
然后根据我们想要function的输出类型来确定Task,我们预期得到的是宝可梦进化后的cp值,是一个scalar,因此使用的Task是Regression。
关于Model,选择很多,这里采用的是Non-linear Model。
:表示一只宝可梦,用下标表示该宝可梦的某种属性
:表示该宝可梦进化前的cp值
: 表示该宝可梦是属于哪一种物种,比如妙瓜种子、皮卡丘...
:表示该宝可梦的hp值即生命值是多少
: 代表该宝可梦的重重量
:: 代表该宝可梦的高度
: 表示我们要找的function
:: 表示function的output,即宝可梦进化后的cp值,是一个scalar
机器学习的三个步骤
Step1:Model找到一个模型(function set)
一元线性模型(单个特征)y=b+w·x
多元线性模型(多个特征)例如:y=b+w1·a+w2·b······
我们假设进化后的宝可梦的CP值y和进化前的宝可梦的CP值满足 :
,w和b称之为模型的参数,可以是任何值。根据w和b采用不同的值我们会得到不同的function,把这些function合起来我们就得到了function set。
实际上这是一种Linear Model,但只考虑了宝可梦进化前的CP值,但进化后的CP值也有可能跟其他条件有关系,如宝可梦的身高、体重等,因而我们可以将其扩展为:
,其中
可以是
、
、
、
……
称之为weight(权重),b称为偏置bias。
Step2:Goodness of Function模型的评估, 如何判断众多模型的好坏(损失函数)
:用上标来表示一个完整的object的编号,第一笔资料上标就是1、第二笔资料上标就是2……下标表示该object中的特征如
:表示一个现实中实际观察到的object输出(真正的data),上标为i表示是第i个object。
为了衡量function set中的某个function的好坏,我们需要一个评估函数既Loss Function,一般用L来表示Loss Function。
Input: a function output: how bad it is
是实际观察到的结果,
是function预测出的结果。同时由于f()是w和b的函数,因此Loss function 也可以用w和b的函数表示:
L(f)的值越大,说明loss function的表现越不好;L(f)的值越小,loss function的表现越好。
Step3:Best Function模型的优化,如何筛选最优的模型(梯度下降)
最后一步是在function set 中找到一个最好的function,我们把这个最好的function称为。
=
,
=
利用线性代数的知识,可以解得这个closed-form solution,但这里采用的是一种更为普遍的方法——gradient descent(梯度下降法)
Loss function可视化处理
下图中是loss function的可视化,该图中的每一个点都代表一组(w,b),也就是对应着一个function;而该点的颜色对应着的loss function的结果L(w,b),它表示该点对应function的表现有多糟糕,颜色越偏红色代表Loss的数值越大,这个function的表现越不好,越偏蓝色代表Loss的数值越小,这个function的表现越好。比如图中用红色箭头标注的点就代表了b=-180 , w=-2对应的function,即,该点所在的颜色偏向于红色区域,因此这个function的loss比较大,表现并不好。
Gradient Descent梯度下降算法
【单个参数问题】
Consider loss function L(w) with one parameter w:
以只带单个参数w的Loss Function L(w)为例,首先保证L(w)是可微的。我们的目标就是找到这个使Loss最小的
,实际上就是寻找切线L斜率为0的global minima最小值点(注意,存在一些local minima极小值点,其斜率也是0)。
有一个暴力的方法是,穷举所有的w值,看哪一个w可以使loss最小,但是这样做是没有效率的;而gradient descent就是用来解决这个效率问题的。
-
随机选一个初始值
- 计算loss函数对w=
的微分,既
,也就是在w=
这一点处loss曲线的斜率。
- 如果这一点切线的斜率是负值(Negative),也就说明曲线左边高右边低,这个时候你就应该把你的参数增加往右边移动(Increase w),从而使得loss的值变小;如果斜率是正的(positive),那么就应该使w变小,即往左踏一步,每一步的步长step size就是w的改变量。
Tips:w的改变量(step size)取决于两个方面:
一是 的值,微分值越大说明斜率越大,曲线就越陡峭,这时你的step size就要小一些,不然可能会越过minima这一点。
二是常数项η,称之为learning rate(学习率),它使得梯度下降的step size不仅仅取决于当前曲线的斜率,还取决于你事先设定好的常数值,如果learning rate越大,w的变化量就越大,既更新幅度越大,反之越小。
learning rate设置的大一些,机器学习的速度就会比较快;但是learning rate如果太大,可能就会跳过最合适的global minima的点。
4.因此每次更新的大小为η ,为了满足微分为正值时w减小,为负值时w增大,step size=-η
,既:
直到=0 时结束,此时的
当时,曲线斜率为0,我们找到了一个极小值,但有可能不是最小值,也就是说我们找到的是local minima 而不是global minima。因此通过但是Gradient Descent找出来的solution可能不是最好的,含有运气的成分在里面。
【两个参数问题】
-
随机选一个
,
-
让loss函数分别对
,
进行偏微分
- 更新w和b
当时,
我们一般将loss函数对w和b的偏微分表示成向量的形式,也就是所说的gradient,用▽L=δLδwδLδb gradient来表示。
可视化效果如下:横坐标是b,纵坐标是w,颜色代表loss的值,越偏蓝色表示loss越小,越偏红色表示loss越大。
注:这里两个方向的η(learning rate)必须保持一致,这样每次更新坐标的step size是等比例缩放的,保证坐标前进的方向始终和梯度下降的方向一致;否则坐标前进的方向将会发生偏移。
Gradient Descent的缺点
1.local minima:每次迭代完之后,梯度为0点一定是极小值点,但不一定是最小值点。也就是说可能是local minima(局部最小值),不一定是global minima(全局最小值)。
2.saddle point:当遇到梯度比较平缓(gradient≈0)的时候会出现saddle point(鞍点),鞍点处微分是0但却不是极值点。
但是在做liner regression(线性回归)的时候你不需要太担心这些问题,因为liner regression的loss function是convex(凸面的),是碗状的,把一个球放在碗的任何一个地方他它都会滑到碗的底部中心位置。但是如果你今天用的是更复杂的model,你就需要考虑这些问题。
宝可梦实例:
偏微分计算
假设data里有10只宝可梦(,
),(
,
),(
,
)……进行偏微分的计算:
How is the result?
我们目前定的function是,在做穷举的时候已经知道当b=-188.8,w=2.7的时候loss是最小的,也就是
是最好的function。我们需要有一套评估系统来评价我们得到的最后这个function和实际值的误差error的大小;这里我们将training data里每一只宝可梦进化后的实际CP值与预测值之差的绝对值叫做
,而这些误差之和Average Error on Training Data为
=31.9
但是我们真正在意的并不是我们已经抓到的宝可梦进化后的CP值是多少,因为我们已经知道他们进化前后的CP值,都在我们data里面,我们在意的应该是如何预测没见过的宝可梦在进化后的CP值。因此我们需要抓另外10只宝可梦,但不去进化他们,直接把他们的CP值带入到function当中得到预测出的进化后的CP值。
但是如何判断这个function预测额是否准确呢?我们还需要把这些新抓到的10只宝可梦拿去进化,并记录他们进化后的实际的CP值与function的预测值进行比较。求得误差之和Average Error on Testing Data为=35.0;可见training data里得到的误差一般是要比testing data要小,这也符合常识,因为你这个最好的function是根据training data找出来的,从来没有看过这些testing data。
How can we do better?
我们目前的function是,预测值y只与宝可梦进化前的CP值
有关系,并且是直线的关系,但根据上图10只宝可梦的进化前后CP值得分布来看,很有可能不是直线的关系。但是假设一下可能是
的二次方的关系,因此假设
+
,解出来的 best function(最好的function)中,b=-10.3,
,
=2.7
,这时求得的Average Error on Training Data为
=15.4, Average Error on Testing Data为
=18.4看起来是好了很多,但其仍然是一个liner的model。可以把
看做一个单独的指标,把
看做是另一个单独的指标。
但是能够观察到testing data也还是没有很好的分布在二次曲线上,所以就假设可不可能是三次方的关系。因此假设+
+
,解出来的best function 中b=6.4 、
、
、
,这时求得的Average Error on Training Data为
=15.3,Average Error on Testing Data为
=18.1。跟二次曲线的结果相比又好了一点。
接下来在再试一下四次曲线,设+
+
,求得的Average Error on Training Data为
=14.9,Average Error on Testing Data为
=28.8,换成更复杂的model后,在training data上的误差进一步减小了,但是在testing data上的误差却增大了。
我们再来试一下五次方曲线设+
+
,求得的Average Error on Training Data为
=12.8,Average Error on Testing Data为
=232.1
5个model的对比
这5个model的training data的表现:随着的高次项的增加,对应的average error会不断地减小;实际上这件事情非常容易解释,实际上低次的式子是高次的式子的特殊情况(令高次项
对应的
为0,高次式就转化成低次式。
也就是说,在gradient descent可以找到best function的前提下(多次式为Non-linear model,存在local optimal局部最优解,gradient descent不一定能找到global minima),function所包含的项的次数越高,越复杂,error在training data上的表现就会越来越小;但是,我们关心的不是model在training data上的error表现,而是model在testing data上的error表现。
一个复杂的模型是不一定总在testing data上面有很好的performance。在training data上,model越复杂,error就会越低;但是在testing data上,model复杂到一定程度之后,error非但不会减小,反而会暴增,在该例中,从含有项的model开始往后的model,testing data上的error出现了大幅增长的现象,这通常被称为 overfitting 过拟合。
overfitting 过拟合
如何解决过拟合的问题,最好的办法就是收集更多的data,我们抓了60只宝可梦。 可以从图中看出宝可梦进化后的CP值显然不仅仅和进化前的CP值有关,有另外的隐藏因素我们没有考虑到,不然不会出现同一个进化前的CP值会对应两个差距很大的进化后的CP值。
我们把不同宝可梦的品种画出来,用不同的颜色表示不同的品种,你会发现宝可梦的种类影响了进化后的CP值。
因此回到第一步:重新设计我们的function
=species of x
表示不同的宝可梦种类
If = Pidgey : y =
+
·
If = Weedle : y =
+
·
If = Caterpie : y = b3
+
·
If = Eevee : y =
+
·
根据不同的物种设计不同的liner model,那如何四个liner model 组合成一个liner model?我们用另外一个式子来写上面的四个式子。在这里我们引入δ(条件表达式),当条件表达式为true,则δ为1;当条件表达式为false,则δ为0。因此可以通过下图的方式,将4个if语句转化成同一个linear model。
有了上面的model之后,我们分别计算了这个model在training data和testing data上面的error。
可以发现无论是在training data还是testing data上面,我们的error都比之前的model好。那么还有没有其他的factor(因素)影响进化后的CP值,比如weight、hight、HP,我们目前也不确定,所以把所有的factor都加进来。
计算出来的training error=1.9 testing error=102.3(overfitting!)我们的model很复杂,能够很好地与training data进行吻合,但可能并不适合实际的预测,在testing data上的结果可能就不会很好。
我们不知道哪些factor是真正起到影响的,因此我们也没有办法过滤掉那些没有作用的因素。但是有另外一种方式对很多不同的test都有用的方法,这种方法叫做Regularization。这里Regularization要做的就是去改原来的loss function。
我们原来的function只是去看testing data 的error有多大,新的function除了看error有多大之外,还多加了一项 ,这一项是
乘以所有参数的平方和。
为什么要选择一个smooth的function?我们相信在多数情况下smooth的function比较有可能是正确的。如果你找出来的function是抖动非常厉害的,像上面四次的function,这个function很有可能是不对的。
中的λ其实是需要手调的,λ的大小取决于你希望你的function有多平滑,λ越大function就越平滑。
其次你还会发现只考虑了w而没有考虑b(bias),因为bias的大小跟function的平滑程度是没有关系的,bias值的大小只是把function上下移动而已,与function的平滑度没有关系。
那为什么我们喜欢比较平滑的function呢?如果我们有一个比较平滑的function,由于输出对输入是不敏感的,测试的时候,一些noises噪声对这个平滑的function的影响就会比较小,而给我们一个比较好的结果。
观察上图可知,当我们的λ越大的时候,在training data上得到的error其实是越大的,但是这件事情是非常合理的,因为当λ越大的时候,我们就越倾向于考虑w的值而越少考虑error的大小;但是有趣的是,虽然在training data上得到的error越大,但是在testing data上得到的error可能会是比较小的。
图中,当λ从0到100变大的时候,training error不断变大,testing error反而不断变小;但是当λ太大的时候(>100),在testing data上的error就会越来越大
我们喜欢比较平滑的function,因为它对noise不那么sensitive;但是我们又不喜欢太平滑的function,因为它就失去了对data拟合的能力;而function的平滑程度,就需要通过调整λ来决定,就像图中,当λ=100时,在testing data上的error最小,因此我们选择λ=100。