前言
如果遇到排版问题,请点击 阅读原文
这个课程是来自于 YouTube 上 NTU 李宏毅老师的视频课程,老师的课讲得非常有趣,通过引入 Pokémon 来生动的讲解机器学习中一些技术的应用,只要你有一定的高数、线代以及概率基础,看这个课程无压力。
我在学习的同时将其搬运并做简单的英文翻译,并加上自己的理解与更通俗的解释。加深自己印象的同时希望能对国内不能使用 YouTube 的读者们提供一个方便。
Regression 回归运算
回归运算其实就是用一个函数去拟合当前给出的数据,如下图:
图中蓝色点代表数据,我们假设这组数据是 Linear Regression 线性回归的,那我们就需要用一条直线去拟合它们,也就是那条红色的线。
Regression 的使用范围也是很广的:
- 股票预测:
$$ \begin{eqnarray} f ( 以往多年股票的走势情况 ) = 明天的点数 \end{eqnarray} $$
当然真正的股市也不可能这么简单,你能预测你就发了?
- 自动驾驶
$$ \begin{eqnarray} f ( 传感器得到的数据 ) = 方向盘与油门的控制 \end{eqnarray} $$
-
推荐系统
像淘宝、京东等的购物网站,会推送一些商品给你,这些商品肯定要是你喜欢的或者需要的,你才可能去购买。一个好的推荐系统可能会让这些网站的利润成倍提高。$$ \begin{eqnarray} \ f ( 用户 A,商品 B ) = 用户 A 购买商品 B 的可能性 \end{eqnarray} $$
如果这个可能性很大的话,购物网站就会更倾向于向用户 A 推荐此商品
但今天,我们要做的是一件更加实际的事情。
用数据估测宝可梦的攻击力(CP值)
比如,下面是一只妙蛙种子,你给他吃一些糖果或者星辰,它就会进化成妙蛙草,进化以后,它的 CP 值就变了。
如果我们有能力预测它进化后 CP 值的变化的话,我们就能够事先决定是否进化这只宝可梦。如果它 CP 值比较低的话,有可能你就把它拿去做糖果了? 就不进化它了,这就可以节省一些糖果用来进化更强的宝可梦。
那我们现在要做的就是,找到这么一个 function,我们输入这只宝可梦的相关数据,他就能返回给我们,进化过后,可能的 CP 值是多少。
$$ \begin{eqnarray} \ f ( 宝可梦的信息 ) = 进化后的 CP 值 \end{eqnarray} $$
这里,我们用 $x$ 代表这只宝可梦,则:
- $ x_{cp} $ 代表其进化前的 CP 值,为
14
- $ x_s $ 代表它所属的物种,为
妙蛙种子
- $ x_{hp} $ 代表它进化前的生命值,为
10
- $ x_w $ 代表它进化前的重量,为
11.62 kg
- $ x_{hp} $ 代表它进化前的生命值,为
0.88 m
- $y$ 则代表进化后的 CP 值
这里 $x$ 的下标表示:这些都是 $x$ 这个个体的某个属性(比如 $小明\_{体重}$、$小明\_{身高}$)。
那我们怎么来解这个问题呢,我们知道,ML 其实就是寻找一个 Model(模型)
,将我们的数据代进去,经过复杂的运算后就能得到我们想要的结果。
所以我们首先需要找到这个 Model
。
第一步:Model
一个 Model
其实就是一个 Function set(一组方法)
。那我们要寻找的这个 Model,它应该长什么样子呢?
我们当然还是期望它能简单点,所以呢,我们就假设它是这么一个方程组:
$$ y = b + w \cdot x_{cp} $$
就是一个常数 $b$ 和一个数 $w$,它们组合起来,$x$ 与 $y$ 就构成一种线性关系。当然,我们现在的 $b$ 和 $w$ 都是不确定的,它可以是任何的数字,不过我们能从直觉上排除一些组合,比如 $w$ 和 $b$ 都为负数:
$$ f_1: y = -1 - 2 \cdot x $$
这样子 $y$ 就成了负数,我们知道,一个宝可梦的 CP 值是不可能为负数的,所以我们能够直接排除这类组合。
前面提到,我们假设的这个方程是一个线性的函数,所以我们这个 Model 就是一个 Linear Model(线性模型)
:
$$ \ Linear\ Model: y = b + \sum w_i x_i \\\ x_i:输入\ x\ 的某个属性(如 CP) \\\ b:bias(误差) \\\ w:weight(权重) $$
有了 Model
我们就需要考虑下一个问题:
第二步:Training Data
我们需要训练数据,因为 ML
就像人一样,本来就是通过一定量的基础练习,才能够学到这类数据的共通点。像下面这个图,左侧是杰尼龟
,右侧则是杰尼龟
进化后,变成的卡咪龟
:
那现在,整个 Model
的 输入就是这只杰尼龟
,我们用 $x^1$ 来表示,那这只 卡咪龟
我们就用 $\widehat{y}^1$ 来表示。这里 $x$ 和 $\widehat{y}$ 的上标表示:这是一个完整的个体,1 只是它的编号(比如 $学生^1$ 、$学生^2$),至于 hat(就是 $\widehat{y}$ 头上的那个尖尖符号),它代表这是一个准确的值(因为这是真实的数据,为了和后面预测出来的数据 $y$ 做区分)。
只有一只肯定不够呀,我们需要很多的数据,就要抓足够多的宝可梦,比如这只 伊布
,它进化过后就是 雷精灵
:
那我们同样就能够得到$x^2$ 和 $\widehat{y}^2$,就像这样:
嗯,我们搜集了十只宝可梦?????????? ,数据可以从这里找到。
我们就有了 10
组 Training Data(训练数据)
:
$$ (x^1,\widehat{y}^1) \\\ (x^2,\widehat{y}^2) \\\ \vdots \\\ (x^{10},\widehat{y}^10) $$
我们将其进化前的 CP 值和进化后的 CP 值画在一个二维坐标图上(横轴为进化前的 CP 值),那每个蓝色的点都代表一只宝可梦:
现在我们有了 Model
和 Training Data
,但是我们还需要一个函数来将它们连接起来,这个函数就是接下来要讲的:
第三步:Loss Function
中间蓝色的块就是 Loss Function(误差函数)
。为什么需要这个函数呢,因为我们现在需要根据这 10 只已知宝可梦数据,代入 Model
推测出它们进化后的 CP 值,然后再与实际的 CP 值进行比较,来慢慢调整 Model
中的 weight
和 bias
。所以,我们需要有一个函数来评判这次推测的误差度,这就是 Loss Function
:
$$ \begin{cases} L(f) = L(w,b) = \sum\_{n=1}^{10} (\widehat{y}^n - y^n)^2 \\\ y^n = b + w\cdot x\_{cp}^n \end{cases} \\\ \Downarrow \\\ L(f) = \sum\_{n=1}^{10} (\widehat{y}^n - (b + w\cdot x\_{cp}^n))^2 $$
上面的方程其实就是将 $\widehat{y}$ 准确值减去$y$估测值,然后将其平方,再将 10 只宝可梦都这样计算并加起来。
我们要做的就是从我们的 Model
中挑选出一个 function
$f$,它能够让 Loss Function
$L(f)$ 的计算结果最小,这个 function
我们就将它命名为 $f^*$:
$$ f^* = arg \min_f L(f) $$
或者从另一个角度考虑,我们的 function
其实就只由 weight
$w$ 和 bias
$b$ 来确定的,那上面的公式还可以写成如下:
$$ w^\*, b^* = arg \min\_{w,b} L(w,b) $$
我们需要做的就是 穷举所有的 ? 和 ?
,直到找到最佳的那一对,让 Loss Function
$L$ 最小。
第四步:Gradient Descent
上面说的穷举真不是一个好办法(基本没法实现),那我们能不能找一个更好、更有效率的办法解决这个问题呢?有!
- 用线性代数的办法:求解非齐次线性方程组(由于这里的方程并不是同解,所以这个办法还是会有些折腾)
- 用高等数学的办法:L 可微分,求梯度即可
如下曲线,我们随机选择一个起点 $w^0$,然后在这个点上对 $L$ 求 $w$ 的微分 $\frac{dL}{dw}|\_{w=w^0}$:
如果你还搞不太懂微分是啥,那就假想这个曲线是一个山坡,你站在 $w^0$ 上,向左迈一步($w$ 减小)或者向右迈一步 ($w$ 增大),然后看往哪边走 $L$ 会变小就往那个方向走一步,得到一个新的位置 $w^1$,然后这样不断重复,就有机会走到最低点。
$$ w^1 \gets w^0 - \eta \frac{dL}{dw}|\_{w=w^0} $$
那新问题出现了,我们步子该迈多大呢?Gradient Descent
中,这个步子的大小为:
$$ \- {\color{red}\eta} \frac{dL}{dw}|\_{w=w^0} $$
其中,$\frac{dL}{dw}|\_{w=w^0}$ 为 $w^0$ 处的梯度,${\color{red}\eta}$ 是一个常数项,我们把它叫做 Learning Rate(学习速率)
,它是一个事先定好的数值,越大,每踏出一步的距离就越大,这意味着学习得就越快。负号则是因为,我们所求的梯度如果是负值说明我们往这个方向前进,$L$ 就会变小,我们就需要增大 $w$,所以,梯度的符号和我们前进的方向是相反的关系。
到了 $w^1$ 后重新计算梯度,很明显这里的梯度比 $w^0$ 小了很多,所以迈的下一步也会随之变小。经过很多次的调整行走后,我们终于走到了 $w^T$,在这个地方,微分趋近于 0
,算法就认为这里是最好的点了(让 $L$ 最小的点)。
但很明显我们能看到,这只是一个 Local Minimum(局部最小)
,全局最小的点并不在这里,当然 Linear Model
不太会存在这种走到 Local Minimum
的情况,至于为什么,后面会给予说明。
我们总的过程用公式表达就是这样的:
$$ 随机选择一个初始的 w^0 和 b^0 \\\ \Downarrow \\\ 分别对 w^0 和 b^0 做微分并计算下一个点 w^1 和 b^1: \begin{cases} w^1 \gets w^0 - {\color{red}\eta} \frac{dL}{dw}|\_{w=w^0,b=b^0} \\\ b^1 \gets b^0 - {\color{red}\eta} \frac{dL}{db}|\_{w=w^0,b=b^0} \end{cases} \\\ \Downarrow \\\ 分别对 w^1 和 b^1 做微分并计算下一个点 w^2 和 b^2: \begin{cases} w^2 \gets w^1 - {\color{red}\eta} \frac{dL}{dw}|\_{w=w^1,b=b^1} \\\ b^2 \gets b^1 - {\color{red}\eta} \frac{dL}{db}|\_{w=w^1,b=b^1} \end{cases} \\\ \vdots \\\ 最终得到一组让 L 最小的 w^T 和 b^T $$
Gradient Descent
到底是什么呢?其实就是将 $L$ 分别对 $w$ 和 $b$ 做偏微分,最后组成一个向量:
$$ \nabla L = \begin{bmatrix} \frac{\partial L}{\partial w} \\\ \frac{\partial L}{\partial b} \end{bmatrix} _{gradient} $$
当然如果你还是有点点糊涂的话,下面这张图就能更好地向你说明,Gradient Descent
的原理:
Gradient Descent
其实就相当于每次计算所处位置圆弧的法线方向,这个方向是数值变化最明显的方向,所以照着这个方向能最快的走到最低点。
但是,遇到这种图怎么办?
不用担心(至少现在),因为 Linear Model
的图形其实不会像上面的图那样,而是像上面第二张图那样的,一圈一圈很规整的凹面图形,几乎不存在 Local Minimum
的问题。
最后,我们看一下 $\frac {\partial L} {\partial w} $ 和 $\frac {\partial L} {\partial b} $ 都怎么计算的(如果你不会的话,可要恶补一下高等数学了)
$$ L(f) = \sum\_{n=1}^{10} (\widehat{y}^n - (b + w\cdot x\_{cp}^n))^2 \\\ \Downarrow \\\ \begin{cases} \frac {\partial L} {\partial w} = \sum\_{n=1}^{10} 2\cdot (\widehat{y}^n - (b + w\cdot x\_{cp}^n))(\-x\_{cp}^n) \\\ \frac {\partial L} {\partial b} = \sum\_{n=1}^{10} 2\cdot (\widehat{y}^n - (b + w\cdot x\_{cp}^n)){\-1} \end{cases} $$
本文总结
- 我们讲了
Regression(线性回归)
的一些作用与高大上的一些应用场景,不过这些都是很复杂的应用; - 然后我们就提出了一个用
Regression
来解决宝可梦升级 CP 值预测
的系统; - 通过将宝可梦的属性代数化:$x$ 代表某个宝可梦个体、$x_{cp}$ 代表它的 CP 值、$x_h$ 代表它的高度等等,让我们能够通过代数的方法解决这个预测 CP 的问题;
- 在最开始,我们需要建立一个
Model(模型)
,Model
其实就是一堆Function(计算方法)
的集合,我们将一些数据输入进去,他就能输出我们想要的结果:比如我们输入一只宝可梦的数据,他就能输出这只宝可梦进化后的 CP 值; - 在第二步,我们需要
Training Data(训练数据)
。我们需要有大量的训练数据,才能够教会我们的模型正确预测可能的 CP 值变化; - 有了
Model
和Training Data
,我们还需要有Loss Function(误差函数)
来评价我们当前模型的好坏,其实它的实现很简单,就是一个普通的函数,然后将Model
预测的 CP 值,和实际已知进化后的 CP 值做比较,他们差距越大,Loss Funciton
输出的 $L$ 也就越大,越小说明预测得越准确; - 最后我们讲了如何训练这个
Model
,用Gradient Descent(梯度下降)
算法来调节模型,梯度下降算法其实就是通过高等数学中的微分运算,找到一个能让 $L$ 变得更小的方向(并且这个方向是能让 $L$减小得最快的),根据这个方向来决定是增大参数的大小还是减小参数的大小,总之,我们能够通过不断地训练调节,得到一个能比较合理的、误差尽可能小的模型。
今天就先写到这里,小步快跑,下次更新见...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。