1. 应用建议
当我们运用训练好了的模型来预测未知数据的时候发现有较大的误差,我们下一步可以做什么?获得更多的训练实例——通常是有效的,但代价较大,且不一定会有很好的改善效果,下面的方法也可能有效,可考虑先采用下面的几种方法。
- 尝试减少特征的数量
- 尝试获得更多的特征
- 尝试增加多项式特征
- 尝试减少正则化程度 λ
- 尝试增加正则化程度 λ
2. 模型评估与选择
当学习算法参数优化的时候,考虑的是如何选择参数来使得训练误差最小化。在模型建立的过程中很容易遇到过拟合的问题,那么如何评估模型是否过拟合呢;又或者,该从哪里出发避免欠拟合呢。对于,模型评估的数据处理方式,大致分为以下几个阶段。
![模型评估](https://i-blog.csdnimg.cn/blog_migrate/ad9fce91074888f7d414550e1beec88c.png)
2.1 经典方式
在传统的数学算法中,我们通常用下面的方法进行模型评估:
把数据集全部作为训练集,然后用训练集训练模型,用训练集验证模型,如果有多个模型需要进行选择,那么最后选出训练误差最小的那个模型作为最好的模型。
这种方式显然不可行,因此训练集数据已经在模型拟合时使用过了,再使用相同的数据对模型进行验证,其结果必然是过于乐观的。如果我们对多个模型进行评估和选择,那么我们可以发现,模型越复杂,其训练误差也就越小,当某个模型的训练误差看似很完美时,其实这个模型可能已经严重地过拟合了。
2.2 引入测试集
把数据集随机分为训练集和测试集,然后用训练集训练模型,用测试集验证模型,如果有多个模型需要进行选择,那么最后选出测试误差最小的那个模型作为最好的模型。
把数据分出一部分作为测试集意味着训练集比原来小了。由学习曲线可知,使用较少的数据训练出来的模型,其测试误差会比较大。因此,对于多个模型的评估和选择,合理的做法是:用训练集训练出各个模型后,用测试集选出其中最好的模型,记录最好模型的各项设置。
很多资料都是这样把数据分为训练集(70%-80%)和测试集(20%-30%)。这样做的前提是:把模型各个可能的设置分别列出来,训练出各个不同的模型,然后用测试集选出最好的模型,接下来用全部数据按照最好模型的各项设置重新训练出一个最终的模型。但这样做也有两个问题:
- 模型的超参数通常很多,我们不太有可能把所有可能的设置全部罗列出来,超参数通常需要根据实际情况进行调整。如果模型的测试成绩不理想,那么我们需要返回,重新训练模型。虽然测试集不用于模型的训练,但是我们如果基于测试误差来不断调整模型,这样会把测试集的信息带入到模型中去。
- 得出的最终的模型,其泛化误差是多少?我们还是无法评估。因为我们又把全部数据重新训练出了这个最终的模型,因此也就没有从未见过的数据来测试这个最终的模型了。
2.3 引入验证集
把数据集随机分为训练集,验证集和测试集,然后用训练集训练模型,用验证集验证模型,根据情况不断调整模型,选择出其中最好的模型,再用训练集和验证集数据训练出一个最终的模型,最后用测试集评估最终的模型
首先用训练集训练出模型,然后用验证集验证模型(注意:这是一个中间过程,此时最好的模型还未选定),根据情况不断调整模型,选出其中最好的模型(验证误差用于指导我们选择哪个模型),记录最好的模型的各项设置,然后据此再用(训练集+验证集)数据训练出一个新模型,作为最终的模型,最后用测试集评估最终的模型。
由于验证集数据的信息会被带入到模型中去,因此,验证误差通常比测试误差要小。同时需要记住的是:测试误差是我们得到的最终结果,即便我们对测试得分不满意,也不应该再返回重新调整模型,因为这样会把测试集的信息带入到模型中去。
对于逻辑回归而言,我们将训练误差表示为:
J
train
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J_{\text {train }}(\theta)=\frac{1}{2 m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}
Jtrain (θ)=2m1i=1∑m(hθ(x(i))−y(i))2
验证集的误差表示为:
J
c
v
(
θ
)
=
1
2
m
c
v
∑
i
=
1
m
(
h
θ
(
x
c
v
(
i
)
)
−
y
c
v
(
i
)
)
2
J_{c v}(\theta)=\frac{1}{2 m_{c v}} \sum_{i=1}^{m}\left(h_{\theta}\left(x_{c v}^{(i)}\right)-y_{c v}^{(i)}\right)^{2}
Jcv(θ)=2mcv1i=1∑m(hθ(xcv(i))−ycv(i))2
测试误差为:
J
test
(
θ
)
=
1
2
m
test
∑
i
=
1
m
test
(
h
θ
(
x
test
(
i
)
)
−
y
test
(
i
)
)
2
J_{\text {test }}(\theta)=\frac{1}{2 m_{\text {test }}} \sum_{i=1}^{m_{\text {test }}}\left(h_{\theta}\left(x_{\text {test }}^{(i)}\right)-y_{\text {test }}^{(i)}\right)^{2}
Jtest (θ)=2mtest 1i=1∑mtest (hθ(xtest (i))−ytest (i))2
2.4 交叉验证
简单来说就是重复使用数据。除去测试集,把剩余数据进行划分,组合成多组不同的训练集和验证集,某次在训练集中出现的样本下次可能成为验证集中的样本,这就是所谓的“交叉”。最后用各次验证误差的平均值作为模型最终的验证误差。
为什么要用交叉验证?如果验证集较大,那么训练集就会变得很小,如果数据集本身就不大的话,显然这样训练出来的模型就不好。如果验证集很小,那么此验证误差就不能很好地反映出泛化误差。此外,在不同的划分方式下,训练出的不同模型的验证误差波动也很大(方差大)。到底以哪次验证误差为准?谁都不知道。但是如果将这些不同划分方式下训练出来的模型的验证过程重复多次,得到的平均误差可能就是对泛化误差的一个很好的近似。
交叉验证的几种方法:
(1)留一法
假设数据集一共有m个样本,依次从数据集中选出1个样本作为验证集,其余m-1个样本作为训练集,这样进行m次单独的模型训练和验证,最后将m次验证结果取平均值,作为此模型的验证误差。优缺点分析:
- 结果近似无偏,因为几乎所有的样本都用于模型的拟合
- 计算量很大,如果有1000个数据,那么就要训练1000个模型
因此,当数据量较大时,计算量是巨大的,所以除非数据特别少,一般在实际运用中不会使用留一法。
(2)K折交叉验证
把数据集分成K份,每个子集互不相交且大小相同,依次从K份中选出1份作为验证集,其余K-1份作为训练集,这样进行K次单独的模型训练和验证,最后将K次验证结果取平均值,作为此模型的验证误差。当K=m时,就变为留一法。可见留一法是K折交叉验证的特例。
根据经验,K一般取10。(在各种真实数据集上进行实验发现,10折交叉验证在偏差和方差之间取得了最佳的平衡。)
(3)多次K折交叉验证
每次用不同的划分方式划分数据集,每次划分完后的其他步骤和K折交叉验证一样。例如:10 次 10 折交叉验证,即每次进行10次模型训练和验证,这样一共做10次,也就是总共做100次模型训练和验证,最后将结果平均。这样做的目的是让结果更精确一些。(研究发现,重复K折交叉验证可以提高模型评估的精确度,同时保持较小的偏差。)
3. 偏差和方差
3.1 基本概念
如果一个算法的运行结果不是很理想,只有两种情况:要么偏差过大,要么方差过大。换句话就是说,要么出现欠拟合,要么出现过拟合。那么这两种情况,哪个和偏差有关,哪个和方差有关,或者是不是和两个都有关?搞清楚这一点非常重要,因为能判断出现的情况是这两种情况中的哪一种。
对于一组个数较少的数据,假设我们使用阶数不同的多项式进行拟合。
如图,展现了不同阶数下导致的欠拟合和过拟合情况,基本上也就是高偏差和高方差的问题。
对于验证集的误差和训练集合的误差,在不同阶数下大致如下图所示:
![误差对比图](https://i-blog.csdnimg.cn/blog_migrate/7b7d20480828070d3ee416a80435ad66.png)
对于训练集,当 𝑑 较小时,模型拟合程度更低,误差较大;随着 𝑑 的增长,拟合程度提高,误差减小。对于交叉验证集,当 𝑑 较小时,模型拟合程度低,误差较大;但是随着 𝑑 的增长,误差呈现先减小后增大的趋势,转折点是我们的模型开始过拟合训练数据集的时候。
如果我们的交叉验证集误差较大,我们如何判断是方差还是偏差呢?根据上面的图表,我们知道:
- 训练集误差和交叉验证集误差近似时:偏差/欠拟合
- 交叉验证集误差远大于训练集误差时:方差/过拟合
3.2 正则化
在我们在训练模型的过程中,一般会使用一些正则化方法来防止过拟合。但是我们可能 会正则化的程度太高或太小了,即我们在选择 λ 的值时也需要思考与刚才选择多项式模型次数类似的问题。
当选择的 λ 过大时,对 θ 的惩罚力度也就比较大,一般会导致 θ 较小,整体的曲线偏向线性;而当 λ 过小时,它对损失函数的影响也是几乎就没有了。参数 λ 的选择大致分为以下几个步骤:
(1)使用训练集训练出多个不同程度的正则化模型
(2)用多个模型分别对交叉验证集计算的出交叉验证误差
(3)选择得出交叉验证误差最小的模型
(4)运用步骤3中选出模型对测试集计算得出推广误差
我们也可以同时将训练集和交叉验证集模型的代价函数与 λ 的值绘制在一张图表上。验证集和训练集的误差公式如下所示:
J
train
(
θ
)
=
1
2
m
∑
i
=
1
T
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J
c
v
(
θ
)
=
1
2
m
c
v
∑
i
=
1
m
c
v
(
h
θ
(
x
c
v
(
i
)
)
−
y
c
v
(
i
)
)
2
\begin{array}{l} J_{\operatorname{train}}(\theta)=\frac{1}{2 m} \sum_{i=1}^{T}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2} \\ J_{c v}(\theta)=\frac{1}{2 m_{c v}} \sum_{i=1}^{m_{c v}}\left(h_{\theta}\left(x_{c v}^{(i)}\right)-y_{c v}^{(i)}\right)^{2} \end{array}
Jtrain(θ)=2m1∑i=1T(hθ(x(i))−y(i))2Jcv(θ)=2mcv1∑i=1mcv(hθ(xcv(i))−ycv(i))2
得到的曲线大致如下图,可以看到随着正则化参数的增大,训练集的损失函数的值逐渐变大,而验证集的误差先减小后变大。
![误差对比图--正则化参数](https://i-blog.csdnimg.cn/blog_migrate/da83d631ebfd2385bc9f2665b3275a6e.png)
3.3 学习曲线
使用学习曲线来判断某一个学习算法是否处于偏差、方差问题。学习曲线是将训练集误差和交叉验证集误差作为训练集样本数量的函数绘制的图表。主要依赖的也是这训练集和验证集损失函数的两个公式。
(1)高偏差,欠拟合
这种情况下,模型往往过于简单,其展现的学习曲线大致如下:
![高误差](https://i-blog.csdnimg.cn/blog_migrate/4123417a3932745954557d458798f5a3.png)
从图中我们可以看出:
- 样本越少,训练集误差很小,交叉验证集误差很大
- 当样本逐渐增加的时候,二者的差别逐渐减小
- 在高偏差、欠拟合的情况下,增加样本数量没啥效果
(2)高方差,过拟合
当我们用一个非常高次的多项式模型,并且正则化非常小,数据量也不是特别大的时候,我们会出现高方差过拟合的情况。其学习曲线大致如下:
![高方差](https://i-blog.csdnimg.cn/blog_migrate/8b11ba865f9081940dc445f5668df1f8.png)
观察图片,我们会发现,增加更多的数据到训练集中可以提高算法的效果。
(3)总结
- 获得更多的训练实例——解决高方差
- 尝试减少特征的数量——解决高方差
- 尝试获得更多的特征——解决高偏差
- 尝试增加多项式特征——解决高偏差
- 尝试减少正则化程度 λ ——解决高偏差
- 尝试增加正则化程度 λ ——解决高方差
4. 二分类问题评估
二分类问题中,习惯将两个类别分别称为正类和负类,相应的样本分别称为正例(positive)和负例(negative),但**分类器(分类模型)**输出的类别未必与真实类别一致,因此实际上可能存在四种情况:
真正例(true positive):被判为正例的正例,总数记作TP;
伪正例(false positive):被判为正例的负例,总数记作FP;
真负例(true negative):被判为负例的负例,总数记作TN;
伪负例(false negative):被判为负例的正例,总数记作FN;
由分类器的预测结果和真实类别构成一个 2×2 列联表,称为混淆矩阵(confusion matrix),如下所示:
样本量 N = TP+FP+TN+FN
4.1 PR曲线
精度和错误率分别代表样本中预测正确和错误的比例,公式如下所示:
{
a
c
c
u
r
a
c
y
=
T
P
+
T
N
T
P
+
F
P
+
T
N
+
F
N
e
r
r
o
r
=
F
P
+
F
N
T
P
+
F
P
+
T
N
+
F
N
\left\{\begin{array}{} a ccuracy=\frac{T P+T N}{T P+F P+T N+F N} \\ \\ \ { error }=\frac{F P+F N}{T P+F P+T N+F N} \end{array}\right.
⎩
⎨
⎧accuracy=TP+FP+TN+FNTP+TN error=TP+FP+TN+FNFP+FN
但通常并不使用精度和错误率,我们更加关注精确率(precision)和召回率(recall)。精确率是指预测的正例中真正例的比例;召回率是正例中被准确分类的比例。
P
r
e
c
i
s
i
o
n
=
T
P
T
P
+
F
P
Precision=\frac{T P}{T P+F P}
Precision=TP+FPTP
R e c a l l = T P T P + F N Recall=\frac{T P}{T P+F N} Recall=TP+FNTP
查准率和查全率往往不可兼得。我们一般渴望追求一个两者之间的平衡点,通常使用F1系数表示,也就是说我们可以使用F1曲线衡量一个二分类模型的好坏。
F
1
=
2
P
R
P
+
R
F_{1}=\frac{2 P R}{P+R}
F1=P+R2PR
那么什么是PR曲线呢?在二分类问题中,我们使用 sigmoid 激活函数将经过线性变换的数值映射到0-1之间,而后我们会设置一个阈值,当大于这个阈值时,为正类,反之则为反类。通常情况下阈值设置为0.5,但如若我们变换阈值,混淆矩阵中的四个数字都会随之改变,那么precision和recall也会发生改变。我们将P值和R值映射在二维空间内,得到的便是PR曲线。
![查看源图像](https://www.freesion.com/images/243/95ecdea04ad7205ed7e6276082f36a1b.png)
PR曲线越靠近右上角,也就是说P和R可以同时表现得较大,我们就认为模型的效果良好。
4.2 ROC曲线与AUC
PR曲线考察的是查准率和查全率之间的关系,衡量的是一种模型对于正例的分类效果,另一种更常用的衡量模型对正例的分类效果的可视化工具,就是大名鼎鼎的受试者工作特征(receiver operator characteristic)曲线,即ROC曲线。ROC曲线考察的是真正利率和伪证例率:
- 真正例率(true positive rate),正例被预测为正例的比例:
T P R = T P T P + F N \mathrm{TPR}=\frac{T P}{T P+F N} TPR=TP+FNTP
- 伪正例率(false positive rate),负例被判为正例的比列:
F P R = F P T N + F P \mathrm{FPR}=\frac{F P}{T N+F P} FPR=TN+FPFP
当然,也有对应的真负例率和伪负例率。分别为TNR和FNR
{
T
P
R
+
T
N
R
=
1
F
P
R
+
F
N
R
=
1
\left\{\begin{array}{l} T P R+T N R=1 \\ F P R+F N R=1 \end{array}\right.
{TPR+TNR=1FPR+FNR=1
容易发现,其实TPR就是查全率R。和PR曲线的绘制一样,对于每一个阈值,都有对应的TPR与FPR。我们以FPR为横坐标,TPR为纵坐标绘出若干点,再连接成ROC曲线。
![查看源图像](https://i-blog.csdnimg.cn/blog_migrate/e84ed15d79a4f67750350aa4c1a54266.png)
值得注意,ROC曲线一定是单调的,但PR曲线不一定,每一条PR曲线都有唯一的一条ROC曲线与之对应,所以这两者本质上其实是一致的。
ROC曲线下方区域的面积,也即通常所说的AUC(area under curve),是越接近1越好的,也就是ROC曲线越靠近左上角越好。