续上
紧接着上面一篇文章 ML01 - Regression 案例学习 (上) 讲到的 Gradient Descent
,我们现在有了 Model
、Training Data
、Loss Function
,我们的 Model
:
$$ y = b + w \cdot x_{cp} $$
经过训练呢,我们得出以下结果:
$$ b=-188.4 \\\ w=2.7 $$
将 $w$ 和 $b$ 代入到原 Model
中,我们就能得到一个一次方程,我们将其画在坐标轴上就是这样(横轴代表进化前的 CP 值,纵轴代表进化后的 CP 值):
计算下来的 $L(w,b)=31.9$。
当然,以上数据仅仅是我们用已知的 10 只宝可梦训练出来的 Model
,如果现在新拿给我们一只宝可梦,代入这个 Model
进行计算,得到的预测数据与实际数据会相差多少呢?
所以我们又捉了 10 只与之前完全不同的宝可梦,代入计算了一下,如下:
可以看到,我们 Model
计算出来的数据与新的 10 只宝可梦实际的数据还是挺契合的。实际计算下来,这 10 只宝可梦的 $L_{w,b}=35.0$。在坐标轴的左下方和右上方,误差会更大一些。
那我们如何才能将左下方和右上方的那些数据也都包含到我们的 Model
中呢?当前我们的 Model
是 Linear Model
也就是线性的,在图中我们能够很明显的看出,用一条红色的直线,再怎么都不可能将所有蓝色点都包含进去。所以,我们现在需要一个更强的 Model
。
第五步:Selecting Another Model
我们更进一步,由于图中的蓝色点并不可能在一条直线上,我们就尝试一下,选用二次方程的曲线来拟合它们:
$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2 $$
然后我们通过之前的办法训练这个 Model
,找出来最好的结果对应的是:
$$ b=-10.3 \\\ w_1=1.0 \\\ w_2=2.7*10^{-3} \\\ L(w_1,w_2,b)=15.4 $$
对应的图形是这样的:
如果我们将其用在 Testing Set
上呢,对应的 $L(w_1,w_2,b)=18.4$,对应的图形是:
如果我们现在将刚才的二次 Model
改成三次方程呢:
$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3 $$
同样训练过后,得出:
$$ b=6.4 \\\ w\_1=0.66 \\\ w_2=4.3\*10^{-3} \\\ w_3=-1.8\*10^{-6} \\\ L(w_1,w_2,w_3,b)=15.3 $$
图形长这样,看上去和二次的 Model
没有太大的区别:
在 Testing Set
上得到的 $L(w_1,w_2,w_3,b)=18.1$,有好一点点:
那如果我们换用四次方程的 Model
的话,训练结果会不会更好一些呢:
$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3+w_4\cdot x_{cp}^4 $$
在 Training Data
下,拟合曲线如下图,很明显的拟合更准确了一些,$L=14.9$:
我们再看看它在 Testing Set
上的表现如何呢:
实际结果竟然是 $L=28.8$,反而比三次方程更糟糕了!!如果我们换做 5 次、6 次或者更高次方程的 Model
情况会不会变好呢?
下面我们再用五次方程的 Model
来训练一下,看看效果如何:
$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3+w_4\cdot x_{cp}^4+w_5\cdot x_{cp}^5 $$
在五次方程的 Model
下,Training Data
的 $L=12.8$,确实变好了,而 Testing Set
的 $L=232.1$,糟糕透顶。
现在,我们将上面五个 Model
(分别为一次方程、二次方程、三次方程、四次方程、五次方程),以及他们的 Loss Funciton
$L$ 的值都画在一张图中,我们可以发现,随着参数的增多、方程次数的增大,我们拟合的效果是越来越好,误差是越来越小的:
这很好解释,因为,二次方程中其实就已经包含了一次方程的情况(使二次方程中$w_2=0$,它就变为了一次方程),所以二次方程除了拟合一次方程已经拟合到的点,还能够拟合更多一次方程没有拟合到的点。所以,它的误差就会比一次方程更小。同理三次方程会比二次方程拟合更好、误差更小...五次方程会比四次方程拟合得更好、误差更小。
但是,在 Testing Data
上则不相同了,我们将不同 Model
在 Training Data
和 Testing Data
上 $L$ 的变化画在同一张图中(蓝色线代表 Training Data
的结果,橙色线代表 Testing Data
的结果):
我们发现,越复杂的 Model
在 Training Data
下表现会越来越好,而在 Testing Data
下则不一定。
这种现象我们就把它叫做 Overfitting(过度拟合)
。举个例子来说,如果我们想训练机器人识别人类,我们就把小明拿给它学习。在只让机器人记住一项
特征的时候,他就记住:有两只眼睛的是人类;只让它记住两项
特征的时候,他会发现:噢,有两只眼睛,一个嘴巴的是人类;当我们让它能记住三项
特征的时候,他就可能会记作:有两只眼睛,一个嘴巴,戴着帽子的是人类,这种情况下,机器人对小明
这个人类的个体
描述得就很明确了,但是对于人类
这个整体来说,就过度拟合
了(并不是所有人都戴帽子,就会导致这个机器人识别不出来很多人类)。
所以我们应当合理地选取 Model
,在减少拟合不够
情况的同时避免过度拟合
。
前面我们的训练都是在 10 只宝可梦的数据上做的,那如果我们选取更多的宝可梦,情况会是怎么样的呢?下面我们就选取了 60 只宝可梦,绘制在图上:
能看出来,这个分布并不是简单的属于一次、二次、三次...式,它其中,应该还有另一个因素在很大程度上影响进化后的结果,很明显,应该就是不同宝可梦对应的物种:
下图中,我们将这些宝可梦,按照不同的物种,将其用不同颜色绘制:
嗯,大概是这么一个画风:
那看来我们可能犯了一个严重的错误,忽略了物种的影响。
重回第一步:Redesign the Model
根据不同的物种,我们需要有不同的 Model
,物种这个属性,就对应的是每个 $x$ 的 $x_s$:
$$ \mbox{输入 }x \\\ \downarrow \\\ y = \begin{cases} b_1+w_1\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Pidgey} \\\ b_2+w_2\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Weedle} \\\ b_3+w_3\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Caterpie} \\\ b_4+w_4\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Eevee} \end{cases} \\\ \downarrow \\\ \mbox{输出 }y $$
那难道我们需要为每个不同的物种设定单独的 Linear Model(线性模型)
吗?这似乎太麻烦了,宝可梦的物种至少有十多类并且还在持续增加。我们能不能用某个特殊的函数将不同的物种都包含进一个 Linear Model
呢?答案是:有的!
我们需要引进一个函数 $\delta()$,它的作用就是,给一个输入,他要么输出 1 要么输出 0 (信号与系统的知识)
$$ \delta(x_s=\mbox{ Pidgey}) \\\ \downarrow \\\ \begin{cases} =1 & \mbox{if }x_s=\mbox{ Pidgey} \\ =0 & \mbox{ 其他情况} \end{cases} $$
那我们的 Model
就可以改写为:
$$ \begin{align} y = & \ b_1\cdot \delta(x_s=\mbox{ Pidgey}) \\\ & +w_1\cdot \delta(x_s=Pidgey)x_{cp} \\\ & +b_2\cdot \delta(x_s=\mbox{ Weedle}) \\\ & +w_2\cdot \delta(x_s=Weedle)x_{cp} \\\ & +b_3\cdot \delta(x_s=\mbox{ Caterpie}) \\\ & +w_3\cdot \delta(x_s=Caterpie)x_{cp} \\\ & +b_4\cdot \delta(x_s=\mbox{ Eevee}) \\\ & +w_4\cdot \delta(x_s=Eevee)x_{cp} \\\ \end{align} $$
比如,我们现在输入一个 Pidgey
,那 $x_s=\mbox{ Pidgey}$,上面的式子就会变成:
$$ \begin{align} y = & \ b_1\cdot 1 \\\ & +w_1\cdot 1 \cdot x_{cp}\\\ & +b_2\cdot 0 \\\ & +w_2\cdot 0 \cdot x_{cp} \\\ & +b_3\cdot 0 \\\ & +w_3\cdot 0 \cdot x_{cp} \\\ & +b_4\cdot 0 \\\ & +w_4\cdot 0 \cdot x_{cp} \\\ \end{align} \\\ \downarrow \\\ y = b_1 +w\_1 \cdot x\_{cp} \\\ $$
所以,现在我们这个 Model
依然是一个 Linear Model
!
做出来的效果怎么样呢?
$L=3.8$,效果和图中看到的一样,非常好的拟合了 Training Data
。但我们真正在意的是它在 Testing Data
上的表现,这几乎决定了这个 Model
的好坏。
结果是 $L=14.3$,比我们以往的所有结果都要好,说明这个思考方式我们是做对了的!
但是仔细看,我们发现,还是有一些点拟合得不够。回想一下,我们刚才只代入了宝可梦的种类 $x_s$ 进行运算,并没有考虑它的其他属性对进化后 CP 值的影响,比如:进化前的体重、高度、生命值等等,这些因素都有可能会影响到一只宝可梦进化后 CP 值的变化情况:
我们该如何将这些因素都考虑进去呢?最简单也是最直接的一个方式就是:把所有属性都传进 Model
中进行运算,那我们就需要设计一个略微复杂的 Model
:
$$ \mbox{输入 }x \\\ \downarrow \\\ y' = \begin{cases} b\_1+w_1\cdot x_{cp}+w_5\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Pidgey} \\\ b\_2+w_2\cdot x_{cp}+w_6\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Weedle} \\\ b\_3+w_3\cdot x_{cp}+w_7\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Caterpie} \\\ b\_4+w_4\cdot x_{cp}+w_8\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Eevee} \end{cases} \\\ \downarrow \\\ y = y'+w_9\cdot x_{hp}+w_{10}\cdot(x_{hp})^2+w_{11}\cdot x_{h}+w_{12}\cdot(x_{h})^2+w_{13}\cdot x_{w}+w_{14}\cdot(x_{w})^2 \\\ \downarrow \\\ \mbox{输出 }y $$
这样,我们既顾及了每只宝可梦物种的特殊性,又增加了 HP 、height 和 weight 三个额外的属性进行分析,总共 18 个参数。
果然,我们得到了一个非常低的 Loss
$L=1.9$,但是,根据以往的经验,这么多参数,我们很有可能会造成 Overfitting
的结果。经过 Testing Data
的运算,$L=102.3$,算是比较糟糕的一个结果了。接下来又怎么处理呢?
重回第二步:Regularization
之前我们的输出 $y$ 定义为:
$$ y=b+ \sum w_i x_i $$
我们需要在 Loss Function
$L$ 的基础上,增加另一个因子,也就是下面公式中,$\color{Red}+$ 号后面的部分:
$$ L= {\sum_n (\widehat{y}^n - (b+\sum w_i x_i))^2} {\color{Red}+\lambda\sum(w_i)^2} $$
这里的 $\lambda$ 是一个参数,需要我们事先给出并手动调节的(它的值越大
,我们的 Loss Function
就越平滑
)。加入 $w_i$ 的意思就是说,在满足 $L$ 尽可能小的前提下,让 $w_i$ 也尽可能地小。因为如果 $w_i$ 越小,输入中 $x$ 值的变化,所带来的 $w_i\cdot x$ 的变化就越小,也就是 $\Delta y$ 越小。这样的话,不同的输入之间,微小的差异就可以控制在一定的范围内,不会对系统产生过大的影响,也就在最大可能上避免了 Overfitting
的发生。当然,它并不需要包含 $b$,因为 $b$ 只是一个常数,并不会随着 $x$ 的变化而变化,所以加上与否,对系统几乎没有影响。
那最终结果怎么样呢?
上图中,我们将 $\lambda$ 的值从 0
调整到 100000
,可以明显看出,其在值为 100 左右的时候,效果是最好的(我们希望 Loss Function
适当地平滑,这可以去除一些噪声对结果的干扰,但过于平滑的话,训练数据对结果的影响又会变得过小,从而减弱了有益特征值对系统的影响)。
最终,我们得到了一个基本可用的宝可梦进化 CP 值预测系统
。当然,由于我们所用的训练数据种类还是偏少,可能在实际的使用中会出现很多系统从来没遇到过的物种,这个时候基本上系统会给出错误率很高的预测值。
本文总结
- 我们最开始通过确定一个
Linear Model
来训练宝可梦的数据,结果发现,有很多的数据都是没办法拟合的(线性模型在图上看来就是一条直线); - 然后我们就想到了用
二次方程
来拟合,结果是:在Training Data
上,Loss Function
的输出的却变小了,并且在Testing Data
上,也得到了同样的结果; - 我们就开始思考,是否通过增加模型的复杂度,就能训练出更好的模型?然后我们就尝试了
三次方程
、四次方程
、五次方程
,结果发现,虽然随着方程复杂度的增大,在Training Data
上的 $L$ 输出越来越小,但是在Testing Data
上,$L$ 变得非常不稳定,并且有快速增大的趋势。我们就意识到,现在的模型Overfitting
了; - 然后我们发现,选取的宝可梦可能有点少了,才导致了个别的特性在训练中变得比较突出加重了
Overfitting
发生的可能性。所以我们又选取了 50 只,一共 60 只宝可梦来进行分析; - 在将 60 只宝可梦绘制在坐标轴上时,我们又发现了一个新的问题,这些点在某些范围内,分布是比较有规律的。所以我们将各个宝可梦根据它们所属的物种进行了分类,然后重新设计了
Model
,用到了 $\delta()$ 函数,这个函数针对不同的输入,只会返回 0 或者 1; - 我们将重新设计的模型通过训练后发现,效果显著,但是还有提升空间,因为有的点并没有被拟合到,所以我们猜想,会不会 CP 的变化不仅和物种 $x_s$ 有关,还和它的生命值 $x_{hp}$、高度$x_h$、重量$x_w$有关呢?所以我们将这些因素都代入了
Model
进行计算,总共用到了 18 个参数。 - 由于之前我们有过经验,
Model
过于复杂就有很大可能发生Overfitting
的现象。果不其然,这次又过度拟合了,为了解决这个问题,我们在Loss Function
中,加入了一个额外的式子 $\lambda\sum(w_i)^2$,由于我们训练的依据就是尽量的让Loss Function
变小,所以我们就需要让刚才这个式子也尽量的小,也就是让 $w_i$ 尽量小,这样的话整个Loss Function
就会变得比较平滑,减少噪声的影响,这也就Regularization(正则化)
的作用; - 最终,我们通过调节 $\lambda$ 的值,得到了比较满意的一个训练结果,在
Training Data
和Testing Data
上的Loss
$L$ 都比较小,不过考虑到我们所使用的宝可梦种类还是太少,如果要将这个系统做到上线实用的话,还需要更丰富的训练数据来训练。
今天更新到这里,期待下一课...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。