前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高中生也能看懂的 “ 梯度下降 ” 算法 (线性回归篇)

高中生也能看懂的 “ 梯度下降 ” 算法 (线性回归篇)

作者头像
用户1564362
发布2019-10-15 15:31:30
6220
发布2019-10-15 15:31:30
举报
文章被收录于专栏:飞总聊IT

文章背景

鄙人最近在研究机器学习的相关算法,查阅很多专业书籍、csdn文章、知乎大神回答、youtube视频,都发现一个高度统一的 “ 问题 ”(严格意义上不能说是问题):大家在介绍算法的时候,总是喜欢陈列各种复杂的公式、各种见都没见过的符号,虽然这样在“数学上”是严谨的,看起来专业感十足,但不给详细的解释,着实给我这样的小白学习者非常不友好,带来了很多负担。。。(似乎在传达着“这是你应该知道的东西”, 于是作为文科生的我,耗尽毕生精力将“谷歌大法”发挥到极致,才对“梯度下降”算法有了一定程度的理解)当我发现“梯度下降”算法也不过如此的时候,我在想:会不会有些人也和我一样是 “ 非科班出身 ”的,还惆怅于数学公式带来的“距离感”,望而生畏?

说明

这篇文章将从文科生小白的视角细细说来,本着让 “ 初中生 ” 也能看懂的精神,力求使用“最直白”、“最简洁”的话术来解释!(可能在数学专业者看来不严谨,但我觉得对读者“亲切”、“友好” 比 “为了严谨而曲高和寡更重要”。)若大神觉得我哪里表达得不到位,欢迎指正~~(`・ω・´)

正文开始

既然你诚心诚意地想知道 “ 梯度下降 ” 的算法到底是什么样的,相信你应该也了解到了:“线性回归” 是 “梯度下降” 的基础。

那么,我自然是要先给各位童鞋介绍一下:什么是线性回归咯~~在机器学习的现实应用领域,就是用一条直线来近似地表示“自变量” 和 “因变量” 的关系。

第 ① 步

举个例子:一天, 隔壁老王用 1两 的面粉, 做了 2个 大饼。(这里, 面粉的数量是自变量, 大饼的数量是因变量, 将自变量作为x轴, 因变量作为y轴, 可以用1 个红点来表示 “面粉——大饼” 的数量关系,如下图)

而如果我们尝试着用一条线来描述 “面粉——大饼” 的数量关系,我们自然而然会想到从原点O出发, 画一条过红点的线, 如下:

用一条直线来描述现实中收集到的数据——“1两面粉, 2个大饼”你看, 这就是线性回归,简单到令人发指吧??哈哈哈~

第 ② 步

住在我家隔壁的不仅仅有老王,还有小王:第二天, 隔壁小王用 2两 的面粉, 做了1 个大饼。此时,我们连线后,有下图:

既然画了两条线,那么我们到底取哪条线,才能更恰当地描述 “面粉——大饼” 的数量关系呢?

好像这两条线都不合适吧,似乎中庸一点比较好,那就取它俩中间的线吧~如下,我多画了两条线夹在中间:

但是,他俩中间理论上可以画出无数条线,那我到底取哪条线最好?(换句话说,就是我这条线的斜率a到底取多大的值最好?)

第 ③ 步

下面开始介绍简单的算法:我们可以直观地认为,当这条线离那两个红点的距离越近,那么这条线就越能够准确地描述 “面粉——大饼” 的数量关系。而这条线,恰恰也就是我们的目标回归线,我们可以用:

来表示这条未知的目标直线。

注意:

代码语言:javascript
复制
 a:表示“斜率”下标{p}:predicted value, 表示“预测值”下标{a}:actual value, 表示“实际值”(此处一定不要把a和下标{a}混淆了)

为了找到那条最合适的直线,我们现在的最终目标就是找到最合适的斜率a, 或者说参数a

根据上面的定义,我们要找到同时距离那两个红点最近的直线,我们也把“每个红点到直线的距离” 叫做 “损失” (e)。而所有 “损失之和” ,记作:∑e

目标:找到一个 参数a ,使得 ∑e 最小。(换句话说就是:通过算出 ∑e 的最小值,找到我们需要的 参数a )( ∑e 的值越小越好,巴不得它等于0, 这样的话算出的 参数a 就是刚好同时经过那两个红点)

注:

e:error, 表示“损失” 数学上,∑ 是求和符号。即:把每个红点的 e 相加求和。

而对于 e 的表示,我们有以下几个思路:

思路 1:

(实际值 - 预测值)

把两个小红点代入上式,计算如下:

为了使∑e 的值尽可能的小,那我们岂不是a取无穷大就好了吗?但这明显不符合常理, 因为“距离”在数学中要用绝对值来表示,所以推翻思路1。

思路 2:

(实际值 - 预测值)

把两个小红点代入上式,计算如下:

此时,我们需要分类讨论:

代码语言:javascript
复制
①  当 2-a >= 0 且 1-2a >= 0 , 即 a <= 1/2时, ∑e = -3a + 3  →→→  此时,a = 1/2 时, ∑e最小,为 3/2;②  当 2-a >= 0 且 1-2a <= 0 , 即 1/2 <= a <= 2时, ∑e = a + 1  →→→  此时,a = 1/2 时, ∑e最小,为 3/2;③  当 a >= 2 , ∑e = 3a - 3  →→→  此时,a = 2 时, ∑e最小,为 3;

综上, a = 1/2时, ∑e 最小为 3/2 .但是,我想大家也觉这样的分类讨论太麻烦了,在数学上不好处理~

思路 3:

既然绝对值在数学上不好处理,我们发现有个东西可以结合前面思路的优点,那就是 “平方和”

于是乎:

(实际值 - 预测值)

我们可以简单地认为,以这种形式去计算我们的 损失函数 是比较合理的!

计算如下:(把俩小红点代入下式)

对上述损失函数进行求导,得到:

(导函数上的每一个点,代表着原函数每一个点上的斜率)(高中就有学求导啦,应该不需要我过多解释吧?哈哈)

如下图:

蓝曲线:原损失函数红直线:导函数(导函数的值越接近0, 损失函数的斜率越平,当它躺平的时候,我们可以说此时就是我们要找的损失函数的最小值点)

综上, 解:10a -8 = 0,a = 8/10 时, 导数为0, 斜率为0, ∑e 为5/9。

聪明如你, 你肯定发现了:此思路下的 a的取值 与 “思路2” 中的 a的取值 不一样。这是因为,“平方” 有放大、缩小的功能。对偏差值大的数,平方后更大了;而偏差值小的数, 平方后显得更没啥偏差了........

我们平时更常使用的正是 “ 思路3 ” 中对 损失函数e 的表示方法。

我认为优点有二:① 可导,方便计算。② 不会为了得到最小的损失函数,而一味地贴近某一点,平方在这里就显得更具备全局观,似乎也有助于避免过拟合。

第 ④ 步

实际上,住在我家隔壁的远不止老王、小王,还有小吕、小布 等等......:

第三天, 隔壁小吕用 3两 的面粉, 做了 3个大饼。第四天, 隔壁小布用 4两 的面粉, 做了 3个大饼。第五天, 隔壁小孙用 5两 的面粉, 做了 6个大饼。第六天, 隔壁小艺用 6两 的面粉, 做了 8个大饼。第七天, 隔壁小珍用 8两 的面粉, 做了 7个大饼。

此时,我们也依旧用红点来表示“面粉——大饼”的“自变量——因变量”组合,有下图:

上图总共7个红点,我们依旧希望用一条直线来做回归,使损失函数∑e的值最小。即:最合适的直线,来描述 “面粉——大饼” 的数量关系。

依据 “ 第 ③ 步 ” 中“ 思路 3 ” 所说,我们的 e 首先选择:

将上面的7个红点的坐标,分别代入上面的 e 中,得到损失函数 ∑e的表达式:∑e = 155a^2 - 318a + 172;它的导函数为:310a - 318

所以, 当导函数为0,即 a = 318/310 时, ∑e 约等于8.90。于是,在此案例中, 最佳的回归拟合直线就是:y = 318/310 * x

至此, 回过头看一下,我们已经一步步演示了线性回归当中的一元线性回归。(" 一元 ":指只有一个自变量“面粉”,一个因变量“大饼”)而在一元线性回归中, 我们又分步骤讲解了“单样本”、“双样本”、“多样本” 的情况。(" 样本 ":指邻居的个数,“老王”、“小王”、“ 小吕 ”.......)

好了,看到这里,你已经大体明白了什么是“ 线性回归 ”。但是鼠标滚轮拨回文章的第①步,我说过:尝试着用一条线来描述 “面粉——大饼” 的数量关系。但是,为什么一定要从原点出发呢?我可以任意画一条直线啊!!这就意味着,我直接把那两个小红点连成一条直线不就好了嘛,这样不是更能描述两个红点的数量关系吗?!!

第 ⑤ 步

现在,我们把直线的函数表示形式从y = a*x 升级成y = a*x + b的形式。通过参数“ b ” 的调整,我们可以在XOY这个平面画出任意的直线。(此函数拥有了 a , b 这两个参数,但还是算一元函数,因为一元指的是自变量的个数,还是只有一个x。参数b可以理解为常数1的系数。)

接下来,我想要引入“ 模型 ” 的概念。这个两个函数的不同表达形式,就可以说成是两个数学模型,表示你认为用什么模样、什么类型的直线去描述 “面粉——大饼” 的数量关系 是最合理的。

注:

代码语言:javascript
复制
我们现在讨论的是直线,当然还可以用曲线模型,以后再作深入探讨。比如:y = x^2  或者  y = x^3 + bx^2 等等,你想到更天马行空都可以。(但你要有依据,比如通过xxx东西让你觉得xxx模型更好....)

依旧根据 “ 第 ③ 步 ” 中 “ 思路 3 ” 所说,我们的 e 首先选择:

把模型“ y = a*x + b ” 代入上面 e 表示的损失函数中,可以得到:

这里的y和x都是实际的小红点,真正要求的未知数是a、b 这两个家伙。

把两个小红点代入上式,计算如下:

我们可以直观地看到,将求和函数中的两个“二项式”展开、合并同类项后,我们惊喜地发现“未知数”项 从2个 变成了 5个,这让我咋整呢?一元二次函数求个导,再等于一下0,就算出 e 的最小值了,但上面这个二元二次六项式咋求解最小值呢?(哈哈哈,被标题“忽悠”的高中生会不会哭晕在厕所呢)

当然,我们可以用一个比较简单的思维:先确定好一个未知数的值,然后求解另一个未知数。

举几种情况:(大家也可以跟着我一起动笔写一写,加深理解~)

代码语言:javascript
复制
当 b = 0 时, ∑e = 5a^2 - 8a + 5;  易得:a = 0.8时,∑e有最小值= 1.8 。当 b = 1 时, ∑e = 5a^2 - 2a + 1;  易得:a = 0.2时,∑e有最小值= 0.8 。当 b = 2 时, ∑e = 5a^2 + 4a + 1;  易得:a = -0.4时,∑e有最小值= 0.2 。当 b = 3 时, ∑e = 5a^2 + 10a + 5;  易得:a = -1时,∑e有最小值= 0 。当 b = 4 时, ∑e = 5a^2 + 16a + 13;  易得:a = -1.6时,∑e有最小值= 0.2 。当 b = 5 时, ∑e = 5a^2 + 22a + 25;  易得:a = -2.2时,∑e有最小值= 0.8 。

哟 ,真巧 ~ 才列举了5种情况,就发现了 “ ∑e = 0 ”的情况了。即:当 a = -1, b = 3时,损失函数存在最小值,且损失为0,也就是“完美拟合”,没有误差 。再把 a = -1, b = 3 代入 之前的 “ y = a*x + b ” 模型 中可得最终的模型:y = -a + 3(以上列举的只是一种思路,不可能真的让你穷举所有情况,会死人的)(当然,你要是会编程的话,穷举也不是不可以,一个循环就搞定了,让机器帮你做这蠢事~~)

你会发现, y = -a + 3 就是那两个红点的连线啊,那干嘛这么费事?因为我这里只给了老王、小王两个“样本”,如果把后面的“小吕”、“小布” 都画上,你不可能再用直接连线的方法了吧?再如果说,上面的例子没有那么巧合,可能你手动列举很多种情况都没有找到最优解。这时候,使用上面的损失函数,并且用科学的数学算法就显得异常重要。(** 偏导、最小二乘、梯度下降)

注:

代码语言:javascript
复制
刚才说的一元函数,是指我们的 “假设模型”。(a、b为参数,函数的值为“预测的大饼数量”)而后面说的二元函数,是指把模型代入损失函数后的函数 (此时,a、b变为未知数,函数的值为“所有损失值e的和”)既然有两个未知数,那么这个坐标系就从{X轴表示“未知数”,Y表示“损失值 e ”} 变成了 →→→→→→→ { X轴、Y轴的两个“未知数”共同来表示一个“样本”,而用Z轴来表示样本的“损失值 e”}也就是说,我们现在需要一个三维的坐标系,来表示上面的二元函数。而连接z轴上的所有点,就会织成一个“面”。即:“ ∑e ” 现在是一个“面”,而不是“线”。(为了更生动地描述这个具有“立体感”的二元函数,我可能会再写一篇文章,用图形来说明)


尾声

本来想把上面二元函数的正规求解过程介绍一下的,但是担心文章太长,大家会懒得看,于是决定把“偏导”、“梯度下降”、“最小二乘”、“曲线模型”等内容放到后面的文章~~(我会用更多的“图形”来介绍,让大家更容易理解“高维”的概念) 如果发现文章哪里出现问题,请告诉我,我会第一时间更改!!如果觉得这篇文章给了你一定的启发,请顺手点个赞,让我知道这篇文章对大家是否有帮助!! 如果大家还有兴趣进一步了解的话,也请留言告诉我,我会加快速度编写下一篇!! 写文章的目的很纯粹,把自己所学与各位分享,是对是错可以一起交流~ 致敬,程序员的伟大革命。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 飞总聊IT 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章背景
  • 说明
  • 正文开始
  • 第 ① 步
  • 第 ② 步
  • 第 ③ 步
    • 思路 2:
      • 思路 3:
      • 第 ④ 步
      • 第 ⑤ 步
      • 尾声
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档