回顾上集: 我们尝试提升model的复杂度来优化它,虽然它在训练集中表现得很出色,但是在测试集中却没有太大提升,反而当model越来越复杂的时候,Average error就会暴增,这就是Overfitting的现象。
今天我们要探讨一下究竟这个error是从何而来,我们又可以通过什么方法就优化它。上图已经揭示了答案,error来源于bias和variance,中文对应是“误差”和“方差”。
Estimator估计值
引用上集的宝可梦例子,我们知道
y
^
\hat{y}
y^是真实结果函数,而我们是并不知道的,只有Niantic【开发宝可梦的公式】知道。而我们通过训练集,训练出来了
f
∗
f^{*}
f∗,而
f
∗
f^{*}
f∗就是对
f
^
\hat{f}
f^的一个估测值。通过靶子来形容这个状况,就是
f
^
\hat{f}
f^是靶心,而
f
∗
f^{*}
f∗在靶子的另外一个位置,它们两个之间有一段距离,这段距离就是bias+variace
Bias and Variance of Estimator
这里将用下面的例子解释一下怎么考量bias和variance。
假设这里有一个变量x,我们要估计它的平均值,假设x的平均值是
μ
\mu
μ,方差是
σ
2
\sigma^{2}
σ2。
Variance Estimator
然后我们举例有N个点,{
x
1
,
x
2
,
.
.
.
,
x
N
x^{1},x^{2},...,x^{N}
x1,x2,...,xN},再对这N个点算平均值m,而m是不会完全等于
μ
\mu
μ的,除非有无穷多个点,m值才会无限接近于
μ
\mu
μ。
但是我们可以通过期望值去计算E[m],E[m]=
μ
\mu
μ。就像打靶一样,你瞄准了靶心,但是因为一些干扰,例如风向,你最后射中的位置会在靶心的周围。
而取决于这些散落的点到靶心的距离就是variance。这个值取决于多少的sample,如果取的N比较多,那么就比较集中,反之亦然。
Biased Estimator
上面是估测均值,而恰好均值的期望值就是
μ
\mu
μ。这里我们想估测bias,也是用同样的方法,计算N个points的方差,如下图。通过方差公式,我们求出来
s
2
s^{2}
s2,但是
s
2
s^{2}
s2的期望值不是直接等于
σ
2
\sigma^{2}
σ2,而是
N
−
1
N
σ
2
\frac { N - 1 } { N } \sigma ^ { 2 }
NN−1σ2。我们可以由此推理并从图中看到,多数的点都在
σ
2
\sigma^{2}
σ2的下方,当增加了points的个数,它们的差距就变小了。
不同的variance和bias的表现
经过上面的解释,我们可以这样理解:( f ∗ f^{*} f∗=estimator)
- f ∗ f^{*} f∗的期望值 f ‾ \overline{f} f与靶心之间的距离就是Bias。通俗的说,就是你没有瞄准到靶心。estimator与靶心之间有bias
- 你瞄准的点与
f
‾
\overline{f}
f之间的距离就是Variance。通俗的说,就是在瞄准的点附近射偏了。
多次实验的 f ∗ f^{*} f∗
我们假设有平行宇宙,每个平行宇宙的你都想抓宝可梦,而且抓到的类型肯定都会有差别。
假设我们用同一个model,但是每个宇宙的表现都不一样,下面是宇宙123和宇宙345的表现
现在我们做100次实验,每次都有不一样的宝可梦,不同的model表现如下图。我们可以发现,越高次数幂,图像就越混乱。
引用回射击的例子,当我们用比较简单的model时,结果是比较集中的,而用复杂的model就会散开。
我的个人理解: 模型的复杂程度代表着要考虑的因素更多了,导致你会在射击的时候,射中的点会散布在你瞄准的点周围,考虑得越多,就越散乱,variance就越大。
而Bias是考虑你是否瞄准到了靶心,如果bias大且variance小,就会集中到一个不准确的位置;如果bias小且variance大,就会散乱的分布在靶心附近。
现在我们假设知道
f
^
\hat{f}
f^,然后看看不同的model的表现是怎样的。
- 黑色线:真实的function f ^ \hat{f} f^
- 红色线:5000个 f ∗ f^{*} f∗
- 蓝色线:5000个
f
∗
f^{*}
f∗的平均值
f
‾
\overline{f}
f
三幅图,分别是一次幂,三次幂,五次幂
所以我们可以说,如果是比较简单的model,bias比较大;复杂model,bias比较小。这个如何解释呢?
因为model就是从一堆function set中挑选,当你定义一个model的时候,你就是已经定义了一堆function set,就是下面的深蓝色圆圈框,简单的model是比较小的,没有包含到target。如果你是复杂的model,function的空间比较大,包含到了target,但是可能找不到target的准确位置,因为给的training data不够。
Bias v.s. Variance
我们又回到最初的那个图。现在我们可以说
- 简单的model:bias大,variance小
- 复杂的model:bias小,variance大
横坐标代表复杂模型复杂程度,纵坐标是error。同时考虑variance和bias的时候,就得出蓝色那条线了。
如果你的error来自于variance很大,就是overfitting;如果是来自于bias很大,那就是underfitting
怎么判断是bias大还是variance大呢?
- 如果你的model无法很好的fit training data,你就是bias大(Underfitting)
- 如果你可以fit training data,但是在testing data上有一个大的error,那么就是variance大(Overfitting)
怎么解决它们的问题?
For bias,你要重新设计你的model
- 把更多的feature加入到input中
- 使它变成一个更加复杂的model
For variance
- 增加data,非常有用,但是不实用,因为比较难获得更多data工业界可能会人工增加假data,例如手写字识别,图像旋转多个角度,或者语音识别的男女声转换
- Regularization正则化
让曲线更加平滑,variance变小,不过可能会伤害bias,因为可能调整到了那个区域,没有包含到target。要调整好那个weight( λ \lambda λ )
Model Selection
接下来我们回到选择model的环节,最理想的情况就是希望平衡bias和variance,找到total error最小的model。在选择model的时候,有几个点我们不能去做的:
从上图看,你可能会直接选择model 3,因为err最小。但是它只是在你手里的testing set表现得比较好,但是在真实的testing set中,就是我们未知的数据中,表现有可能并且大多数都会大于你现在测试出来的err。为什么呢?
因为你自己的testing set也有自己的bias。你现在用你手上的testing set测出来可能效果还不错,这是因为你手上的testing set本身也有bias,model表现得好是因为可能刚好稍微贴合你手上的testing set,但是在真实环境(real testing set)中,可能表现就不是这样子了。下面用一个实例去解释一下。
在kaggle比赛中,你上传上去的结果,只是在public leadboard的分数,you beat baseline?但是你并看不到private leadboard,可能在private set并表现得不好。可能是你在public set中排第一名,但是在private set中排到了50多名这样子。我的理解是泛化性能不够。
Cross Validation交叉验证
这个方法可以帮助你在知道结果前,先自己验证一下。
- 把training set分成training set 2和validation set验证集
- training set 2用来做训练集,validation set用来选择model
- 假设model 3表现最好,你可以把这个model直接用testing set测试一下
- 但是如果你怕训练集的数据量太少,你就定下来用model 3,但是用整个training set拿去训练,然后再用testing set测试
温馨提示: 最好不要因为结果,然后去调整你的model,因为这样就是让训练集去适应你的testing set,其实就是在欺骗自己,对于新的数据来,又可能还是表现比之前的差。
N-fold Cross Validation
这是交叉验证的升级版。就是把training set分成N份,每次留一份做validation set,其余做training set,使用N次不同的validation set,算出每个model的N次error值,然后再取每个model的N个error的平均值,选择平均error最低的model,拿去test.