李宏毅机器学习课程笔记EP1

李宏毅2021/2022春机器学习课程笔记EP1(P1-P4)

从今天开始我将学习李宏毅教授的机器学习视频,下面是课程的连接(强推)李宏毅2021/2022春机器学习课程_哔哩哔哩_bilibili。一共有155个视频,争取都学习完成吧。

那么首先这门课程需要有一定的代码基础,简单学习一下Python的基本用法,还有里面的NumPy库等等的基本知识。再就是数学方面的基础啦,微积分、线性代数和概率论的基础都是听懂这门课必须的。


下面就正式是Lecture1的内容。

“机器学习约等于寻找函数。”

首先介绍的是机器学习的任务,有下面三种:

第一就是回归(Regression):它解决的就是用函数输出一个标量。

第二就是分类(Classification):简单来说就是给选项,输出机器认为正确的选择。

第三是结构化学习(Structured Learning):它的目的是让机器学会创造。

下面是对于机器学习中的一些名词解释。

首先是模型(Model),它说白了就是一个带有未知数的函数。y = wx + b 这里的y就是一个Model,W(weight)和b(bias)就是待训练的参数。

损失(Loss)是用来评价一套训练的参数值有多好的指标(how good a set of values is)。

训练模型是肯定要有一个正确的指标,在机器学习中Label就是真实正确的值。

上面就是对于Loss的一些解释,值得关注的就是上面提到的新名词MAE和MSE,这里的MSE指的就是均方误差的意思。

那么到这里就可以来介绍机器学习的三个步骤了:

根据上面的step,接下去就是将每一个参数都代进L(w, b)中计算Loss了。我们可以将这些Loss算出来之后画出一幅等高线图,这个就是Error Surface了。

那前面说了,Loss就是评估这些参数代进去之后效果好坏的指标,那么我们肯定希望这个Loss越小越好,所以我们就需要在这个等高线图当中寻找一个最低点,也就是最小的Loss值。这也就是我们步骤三要做的事情,就是Optimization,我们的目标就是找出最好的一组L(w, b)。我们在这里会采用的方法就是大名鼎鼎的梯度下降法(Gradient Descent)了。在这里简单概括一下梯度下降法,首先我们会随机找一个起始点w0,没错这个起始点就是随便找的一个点,当然在后面我们可能会有别的方法去寻找初始点。接着我们就会计算w对于L的微分,也就是在w0这个点计算斜率。接下去就会出现两种情况,第一种是这个斜率是个负数,就说明L正在随着w递减,所以为了求Loss的最小值,我们就会增加w的值;那么反过来也是同理,如果这个斜率是正数,我们就会减少w的值。这里可以顺便提一下的是这个增加w多少的问题,答案其实非常简答啦,就是斜率大,我们的步伐就跨大一点,反过来斜率小,我们的步伐就跨小一点。下面假设只有一个参数的情况下,我们来直观地解释梯度下降法:

看上面的笔记我们首先发现了两个新的名词,我们就先对于他们作出解释。η是学习的速率(Learning rate),可以看到它与斜率相乘才决定了步伐的大小,也就是说η可以决定训练的快慢,与斜率不同的是η这个参数是由我们模型的训练人来决定的,我们可以自己自由控制它的大小。同时引出了新的概念,也就是机器学习中自己设定的参数叫做超参数(hyperparameters)。

接下去说,我们的目标是要找到一个最小的Loss值,我们通过不断计算斜率,得出我们下一步要迈出多大的步伐,也就下一步的w更新在哪个位置。那什么时候程序会停下来呢?有一种情况是我们设定一共更新几轮,比如所在程序当中写计算100次斜率后停止程序,我觉得这样应该是防止有一个非常长的关于L的函数,这个函数一直在下降但下降的速度非常慢,导致我们每一步都迈地非常小,然后程序还不断计算每一步的斜率,感觉就是很小心翼翼地向前,然后Loss的每一次下降的值又非常少,但是程序又会一直不断地跑下去,所以我们通过设定更新的轮数来解决这个问题,这里老师没有讲,其实都是我瞎猜的啦。不过没错,这里我们设置的轮数也是一个超参数(hyperparameters)。那还有一种方式就是当斜率为0的时候,也就是w这个点的左边是递增,右边也是递增的情况,程序没有办法继续走了,因为算出来的步伐是0嘛,这种情况下程序也会停下来。

再来仔细看图中的这个函数,我们会发现wT是我们最后停下来的点,但是我们会发现真正L的最小值是在wT的右边,也就是说我们其实并没有找到我们需要的L的最小值点!我们将这个会停下来的点称为局部最优(Local minima),然后将这个真正的最优点称为全局最优(Global minima)。那么接下去我们并不会去讨论如何去寻找这个全局最优点,因为其实这个问题并不是我们这个方法最主要的痛点,后面的课程里应该会再去详细地讨论。接下去我们再来看两个参数时候的情况:

这里的步骤其实和刚刚说的差不多,我们会随机选取的参数变成了两个,分别是w0和b0,然后我们在计算斜率的时候会分别对w和b求对于L的微分。这里值得一提的是,两个参数的微分计算,通常可以在深度学习框架中用一句代码完成。

完成了以上三步,可以说我们完成了一次机器学习,但真正的机器学习肯定没有那么简单,实际上比这要复杂的多。让我们回到step1的Model上面,刚才我们选取的模型是 y = b + wx1 这个函数,下面老师将这个模型用在真实生活中会产生的数据上面,这个数据是老师的YouTube账号的观看人数假设,那么算出来了2017-2020年观看人数,这个数据对于我们这个场景下来说是已知的数据,我们可以将这些数据称之为训练集,那我们算出对于训练集来说的L的值,假设说是0.48k。然后我们在计算一下2021年(假设这里2021年的数据是未知的)的L,那这里2021年的数据也就是我们的预测值,这里假设我们得到的损失值L’是0.58k。那刚才的情况是以天为单位的,我们知道每天观看YouTube视频的人数肯定会有不同,比如说星期一到星期五观看老师课程视频的人数就会多一些,因为是教学视频嘛,那到周末的时候观看教学视频的人数就会少一些,这样比较符合常理嘛,因为大家可能在周末休息。虽然说每一天的数据会有很大差异,但是以周为单位这样的差距就会小一些了。所以我们可以使用刚才说的有两个参数的Model,通过调整函数中的w和b的值可以制造出新的函数,这里我们调整w的值(具体如下图所示),我们先以7天为一个单位来看,通过计算我们发现2017-2020的L是0.38k,2021的L’是0.49k。我们发现比刚才得到的损失要小了一些,说明我们的模型效果变得更好了一些!那既然以周为单位效果变好了,那我们以月为单位,甚至以年为单位呢,按理来说我们的模型效果会变得更好一些。没错,根据实际问题一步步修改我们的Model,可以使L逐渐减小,也就是让我们的模型变得更好。顺带一说,刚才提到的这些Model都叫做Linear model,字面意思,他们都是直线函数。

以上我们说的Model都叫做Linear model,它们不仅不完美,还有非常多限制,比如说下面这个例子,就是无论怎样调整w和b的值,我们都不可能制造出下面这条红色的折线函数。

这是来自于Model本身的限制,我们叫做Model Bias。请注意,这里的Bias和我们之前model(函数)里的b不是一个意思。于是,想要我们的模型更加完美,我们需要写出更加复杂的函数。上面的这条红色函数既然不能用一个函数完美表示,那么我们是不是可以用很多一个function(函数)去表示它呢?没错,这就是解决的办法,这条红线的线可以由常数和许多function的总和加起来得到,这个function的样子还有点特别啦,像反转过来的Z,具体我们可以看下图。

我们通过将常数和许多function加起来得到了更加复杂的函数,All piecewise linear curve都可以由常数加上许多function的总和得到,再进一步说,我们可以用piecewise linear curve去逼近任何像上面红色函数那样的曲线。这样无论多复杂的曲线都可以表示出来了,无非就是function用的多少而已,用的越多自然表示出来的函数就越复杂。那么问题又回来了,我们该如何去表示这个function呢?下面就该机器学习中大名鼎鼎的sigmoid函数出场了!

sigmoid函数在机器学习中非常重要,很多地方都会再提到,上面这个虚线就是sigmoid函数本体了,它的表达式是下面这样,后面我们通常会简写成 y = c sigmoid(b + wx1):

sigmoid式子里的c是个常数,可以由我们自由调整它的大小,后面会具体说明它的用处。观察式子,我们可以发现sigmoid函数的一些特征。如果x1取无穷大,那么这个sigmoid函数就会收敛于高度是c的地方;如果x1取无穷小,下面的分母就会无穷大,最后这个sigmoid函数就会收敛于0。这里我们会发现c、b和w这些参数都是我们可以去修改的,通过修改这些参数我们就可以制造出各种不同的function。这里顺带一提的是,刚才我们组成那条红色函数用到的function就是一种特殊的sigmoid函数,我们将其称之为Hard sigmoid。下面是c、b和w改动后对于sigmoid函数的效果:

从上面的图中我们就可以看到改动这些参数后的效果:

w控制函数的斜率

b控制函数的左右移动

c控制函数的上下移动

这里为了方便记忆sigmoid函数的形状,我们从sigmoid这词的意思角度出发,sigmoid这个单词有S形、乙状的意思,和上面的图像结合起来看还是挺形象的。

于是,通过sigmoid函数,我们改进我们的模型,让我们的模型实现了线性到非线性的飞跃。这里请注意在图中标的一个未知数和两个未知数都表示的是w下标的个数,并不是指参数的个数。

那这里的I式子可能看起来会比较复杂,下面我们对它做出详细的解释:

这里的i表示不同的sigmoid函数,j表示feature的编号,为了方便理解,我们还是用上面那个YouTube的例子,假设这里的j表示的就是前i天,然后我们输入的xi就表示前i天的频道观看人数。上图黑色圈里的编号就表示这是第i个sigmoid函数。式子中的wij表示的是第i个sigmoid函数里乘给第j个feature的weight。为了方便起见,我们将sigmoid括号里的式子表示为ri。接下去的理解可能需要一些线性代数方面的知识,下面为了方便和简洁性,我们用线性代数的角度去解释上面关于r的式子。

注意上面的式子并没有进行计算,只是在线性代数的角度解释了r的计算。值得注意的是,这里的r、b和x都是一个向量,w是一个矩阵。再然后根据式子,就该将r代入sigmoid函数中进行运算了。

这里为了方便起见,我们将sigmoid函数运算后的结果简写成ai。然后我们继续看式子接下去的运算。

接下去就应该比较好理解了,就是将sigmoid计算出来的ai乘上常数ci全部加起来,最后再加一个常数b就可以得到我们的输出结果y啦!这里在用向量矩阵的方式表示的时候有一个需要注意的点,就是我们将常数ci组成的向量进行了行列转置,在右上角写个大写的T就表示行列转置,因为一开始我们定义的向量c和a都是列向量,两个列向量的形状决定了它们不可以相乘,于是行列转换之后它们的形状变成了1 * 3 和 3 * 1,这样两个形状的向量就可以进行相乘了。

最后是对于I式子解释的一个总结,下面是一个式子的计算流程图:

这样子我们就对step1做出了改进,接下去我们看到step2,Loss的计算也应该相应的进行改进。

在继续接下来的内容之前,我们先来重新明确一下各个参数的定义。

首先这里的x表示的是feature。其次是我们的四个未知数W、c和两个b,请注意这里绿色的b和灰色的b表示的含义是不同的。我们将矩阵w的每一列或者行拿出来变成一堆向量,然后我们将这堆向量和两个b和cT向量共同定义为θ,也就是说我们将所有未知数统一称为θ,这个向量θ里的θ1、θ2、θ3…的数值都来自于w、两个b和c当中,但是在这里我们就不加以区分了。

这样Loss的function就可以写作L(θ),它表示未知数θ是一组什么样的值时,model会有多好或者多不好。那接下去Loss的计算就和前面说的差不多了。

就是我们将数值分别代进这些未知数θ的w、c和两个b当中计算出y的值,然后再和y_hat也就是label作差的绝对值求出e,接下去就是带入Loss的计算公式了,和前面的做法一样。

这样我们就对step2做出了改进,接下去就该改进step3 Optimization了,也就是找Loss的最小值。

方法其实和之前两个参数的时候也差不多啦。我们的目的还是找Loss的最小值,我们用θ*来表示Loss最小时候的θ值。然后还是和之前一样随机取一个起始的值θ0,接下取就是和之前一样求微分,只不过这里我们的参数不止一个了,所以我们需要对所有未知数都求微分,所有未知参数的微分就组成了向量g,这里的g有个专有的名词叫做梯度(gradient)。g的通常写法在上图有写,就是一个倒三角加上L(θ)。更新θ的方法也和之前一样,只不过多了很多参数,和之前一样,将现在的θ值减去学习率乘上梯度的值就得到了新的θ值,这样我们就完成了对θ的更新。接下去就是一直重复更新参数直到找到斜率为0的点或者我们主动停止程序了,这里因为参数变多,计算量也是成倍增加,所以一般来说我们是不太可能找到斜率是0的点,一般来说都需要我们自己去手动设定程序什么时候暂停。

但是实际上这样和之前一样的更新θ的方法并没有可行性,因为这样做的计算量太大了。实际上,我们会将一个大的资料(数据)也就是未知参数的值分成好多组,然后选总数值中的每一组数据求L,也就是求g。

具体来说明,假设这里有N笔用于训练的数据,我们将这些数据随便平均分成一组一组的数据,每一个batch中有B笔资料假设说。然后我们每次选一个batch的数据求L,也就是求梯度g,然后将求出来的g用于θ的更新,以此类推我们不断更新θ。将所有batch都计算完更新完参数后,我们称之为1 epoch;每一次的更新参数θ,我们都称之为一次update。所以实际上我们并不是用大的N的L去更新参数,而是分成一个一个batch去更新参数。这里值得说明的是,epoch和batch size 都是我们可以自己定义的超参数。

就这样我们对机器学习的三个步骤都完成了改进。但其实还有许多可以代进的地方。

我们之前使用sigmoid函数去逼近Hard sigmoid 函数,但其实还有别的方法去表示Hard sigmoid函数,就是Rectified Linear Unit(ReLU)函数。

下面这个就是ReLU函数的表达式:

通过观察上面的函数,我们可以发现ReLU函数的一些特征。ReLU函数从左到右,先是一个固定不变的值,然后到了某一点再增大或者减小。

这样实际上我们用两个ReLU函数就可以表示出刚刚的Hard sigmoid函数。这里就引出了继续学习中著名的名词——激活函数(Activation function)了,sigmoid函数和ReLU函数都是激活函数,激活函数的意义其实也在一开始就体现了,就是表示不同的function。

到了这一步,我们依旧可以进行优化,我们除了将sigmoid函数替换为ReLU函数外(一般ReLU函数的效果都要比sigmoid函数的效果要好,不过这两个函数都是当今常用的激活函数),还可以输入x后将输出的值(这里我们假设为a)a再作为输入的值放入我们的函数中进行计算得到输出值,我们可以这样不断加深计算层数。这样也可以达到优化model的目的,顺带一提,这里的计算层数也是我们可以自己决定的超参数。从结果来看,这样做的效果非常好!

这样子就引出了本次课程的精髓——神经网络。

上面每一个激活函数都叫做神经元(Neuron),它们组成的网络就叫做神经网络(Neuron Network)。里面的每一层计算都是神经网络中的一层隐藏层(hidden layer)。有许多层就意味着Deep(深),所以这种技术就叫做深度学习(Deep Learning)。深度学习是机器学习的一个部分,本次李宏毅教授的机器学习课程主要就是对深度学习这门技术的学习。

但是是否这就表示只要我们一直加深层数,我们深度学习的效果就会一直变好呢?

在这个例子当中,我们发现虽然加深到4层的时候,在2017-2020(训练集)中的数据效果比3层要好,但是在2021的预测当中的效果不如3层的神经网络,这种现象就称之为过拟合(Overfitting)。Deep Learning的意义就在于用现有的数据预测未来,所以在这个例子中4层网络对于我们的意义就不如3层。也就是说,我们不可以一直加深层数来达到一直优化模型效果的目的,我们需要抑制过拟合的产生。


以上就是P1-P4课程的内容,也就是Lecture 1 的主要内容。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇