第2章 模型选择和评估
1. 经验错误与过拟合
1.1. 错误率:分类错误的样本数占总数的比例。eg:m个样本中有a个样本分错,错误率E=a/m
1.2. 精度:精度=1-错误率。
1.3. 误差:学习器(模型)的预测输出与样本的真实值之间的差异。
1.4. 训练误差/经验误差:学习器在训练集上的误差
1.5. 泛化误差:在新样本上的误差。我们希望得到泛化误差小的学习器
1.6. 过拟合:学习器把训练数据自身的一些特点当作整个样本空间的特点,从而使得在训练数据上有很小的经验误差,导致泛化能力下降
常见原因:由于学习能力过于强大,以至于把训练样本所包含的不太一般的特性都学到了
1.7. 欠拟合:对训练样本的一般性质尚未学好。通常是由于学习能力低下造成的。
1.8. 模型选择:理想的解决方案是选择泛化误差最小的那个模型。
问题:无法直接获得泛化误差,而经验误差又存在着过拟合问题,不适合作为标准,那么应该如何进行模型评估与选择呢?
1.9. 书中将模型选择问题拆解为(1)评估方法;(2)性能度量;(3)比较检验;三个子问题。
- 评估方法:用什么数据做评估?如何获得这些数据?
- 性能度量:评估时如何衡量模型的好坏?有哪些评价标准?
- 比较检验:如何比较模型的性能?注意不是简单地比大小!在机器学习中性能比较是相当复杂的。
2. 评估方法
测试集:测试学习器对新样本的判断能力。测试集应该尽可能与训练集互斥
测试误差:以测试集上的“测试误差”作为泛化误差的近似
代码实现
2.1 划分数据集
2.1.1 留出法
定义:直接将数据集D划分为两个互斥的集合,一个作为训练集S,一个作为测试集T
注意:训练/测试集的划分要尽可能保持数据分布的一致性。保留类别比例的采样方式又叫分层采样
单次使用留出法得到的估计结果往往不够稳定可靠,一般要采用若干次随机划分、重复进行实验评估后,取平均值作为留出法的评估结果。
常见做法:大约2/3~4/5的样本用于训练,剩余样本用于测试。
2.1.2 交叉验证法
k折交叉验证:将数据集D划分为k个大小相似的互斥子集。每个子集Di都尽可能保持数据分布的一致性(分层采样)。每次使用k-1个子集的并集作为训练集,余下的一个子集作为测试集。这样就进行了k次训练和测试。最后
返回k个测试结果的
均值
。k:常取10、5、20等。
- KFold类实现了数据集的k折交叉切分:
sklearn.model_selection.KFold(n_splits=3, shuffle=False, random_state=None)
- StratifiedKFold类实现了数据集的分层采样折交叉切分:
sklearn.model_selection.StratifiedKFold(n_splits=3, shuffle=False, random_state=None)
- 便利函数cross_val_score 对estimator执行k折交叉验证
sklearn.model_selection.cross_val_score(estimator, X, y=None, scoring=None, cv=None,n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs')
返回值:返回一个浮点数的数组。每个浮点数都是针对某次k折交叉的数据集上,estimator预测性能得分。
留一法LOO
是交叉验证法,在划分子集k=m数据集样本数时的特例
优点:不需要担心随即样本划分带来的误差,因为这样的划分是唯一的。结果往往认为比较准确。
缺点:数据集较大时,训练m个模型的计算开销是难以忍受的
它每次迭代时,依次取0,1,…(n-1)作为测试集样本的下标。
from sklearn.model_selection import LeaveOneOut for train_index,test_index in LeaveOneOut(len(y)):
#train_index保存训练集样本下标,test_index保存测试集样本下标
2.1.3 自助法
以自助采样为基础,对包含m个样本的数据集D进行有放回的m次采样以获得同等规模的训练集D’(有重复)。在这m次采样中都不被抽到的概率大约为0.368,也即数据集D中有约1/3的样本是训练集中没有的,用于测试。这样的测试结果,亦称“外包估计”
优点:1.在数据集较小、难以有效划分训练/测试集时很有用。2.能从初始数据集产生多个不同的训练集,对集成学习等方法有很大好处。
缺点:改变了初始数据集的分布,会引入估计偏差。
在初始数据量足够时,留出法和交叉验证法更常用一些。
2.2 调参与最终模型
在进行模型评估与选择时,除了要对适用学习算法进行选择,还需对算法参数进行设定,也就是常说的“调参”
机器学习参数分类
算法的参数:超参数。由人工设定多个参数候选值后产生模型。
模型的参数:数目可能很多,通过学习来产生多个候选模型。eg:DL
校验集:模型评估与选择中用于评测的数据集。把训练数据划分为训练集和测试集。
3. 性能度量
定义:衡量模型泛化能力的评价标准。
均方误差:回归任务。预测结果与真实标记进行比较。
E
(
f
:
D
)
=
1
m
∑
i
=
1
m
(
f
(
x
i
)
−
y
i
)
2
E(f:D)=\frac{1}{m}\sum^m_{i=1}(f(x_i)-y_i)^2
E
(
f
:
D
)
=
m
1
i
=
1
∑
m
(
f
(
x
i
)
−
y
i
)
2
更一般的,对于数据分布
D
\mathcal{D}
D
和概率密度函数
p
(
x
)
p(x)
p
(
x
)
,均方误差可描述为:
E
(
f
:
D
)
=
∫
x
∼
D
(
f
(
x
)
−
y
)
2
p
(
x
)
d
(
x
)
E(f:\mathcal{D})=\int_{x\sim\mathcal{D}}(f(x)-y)^2p(x)\rm{d}(x)
E
(
f
:
D
)
=
∫
x
∼
D
(
f
(
x
)
−
y
)
2
p
(
x
)
d
(
x
)
3.1. 错误率与精度
分类任务
错误率:
E
(
f
:
D
)
=
1
m
∑
i
=
1
m
I
(
f
(
x
i
)
=
y̸
)
E(f:D)=\frac{1}{m}\sum^m_{i=1}\mathbb{I}(f(x_i) =\not y)
E
(
f
:
D
)
=
m
1
i
=
1
∑
m
I
(
f
(
x
i
)
=
y
)
对于数据分布
D
\mathcal{D}
D
和概率密度函数
p
(
x
)
p(x)
p
(
x
)
E
(
f
:
D
)
=
∫
x
∼
D
I
(
f
(
x
)
=
y̸
)
p
(
x
)
d
(
x
)
E(f:\mathcal{D})=\int_{x\sim\mathcal{D}}\mathbb{I}(f(x) =\not y)p(x)\rm{d}(x)
E
(
f
:
D
)
=
∫
x
∼
D
I
(
f
(
x
)
=
y
)
p
(
x
)
d
(
x
)
精度:
a
c
c
(
f
:
D
)
=
1
m
∑
i
=
1
m
I
(
f
(
x
i
)
=
y
)
=
1
−
E
(
f
:
D
)
acc(f:D)=\frac{1}{m}\sum^m_{i=1}\mathbb{I}(f(x_i) = y)=1-E(f:D)
a
c
c
(
f
:
D
)
=
m
1
i
=
1
∑
m
I
(
f
(
x
i
)
=
y
)
=
1
−
E
(
f
:
D
)
对于数据分布
D
\mathcal{D}
D
和概率密度函数
p
(
x
)
p(x)
p
(
x
)
a
c
c
(
f
:
D
)
=
∫
x
∼
D
I
(
f
(
x
)
=
y
)
p
(
x
)
d
(
x
)
=
1
−
E
(
f
:
D
)
acc(f:\mathcal{D})=\int_{x\sim\mathcal{D}}\mathbb{I}(f(x) = y)p(x)\rm{d}(x)=1-E(f:\mathcal{D})
a
c
c
(
f
:
D
)
=
∫
x
∼
D
I
(
f
(
x
)
=
y
)
p
(
x
)
d
(
x
)
=
1
−
E
(
f
:
D
)
sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
3.2. 查全率、查准率、F1
3.2.1 分类结果混淆矩阵
sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None)
classification_report:分类评估报告,返回每一类的预测性能指标:
sklearn.metrics.classification_report(y_true, y_pred, labels=None, target_names=None,sample_weight=None, digits=2)
3.2.2 查准率precision
预测结果中真正例在正例中所占的比例
P
=
T
P
T
P
+
F
P
P = \frac{TP}{TP+FP}
P
=
T
P
+
F
P
T
P
sklearn.metrics.precision_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None)
3.2.3 查全率recall
所有正例被预测为正例所占的比例
R
=
T
P
T
P
+
F
N
R = \frac{TP}{TP+FN}
R
=
T
P
+
F
N
T
P
sklearn.metrics.recall_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None)
查准率和查全率相互矛盾。
3.2.4 P-R曲线
很多情况下,可以根据预测结果对样例进行排序,排在前面是学习器认为“最可能”是正例样本,排在后面“最不可能”是正例样本。可以计算在查全率为多少的情况下查准率的值,实际上考虑了输出元素的顺序。
曲线越靠外,性能越好;交叉时,比较曲线下的面积。
平衡点(BEP):查准率p=查全率R
BEP过于简化,常用F1度量
sklearn.metrics.precision_recall_curve(y_true, probas_pred, pos_label=None,sample_weight=None)
3.2.5 F1
F1:P和R的调和平均
1
F
1
=
1
2
⋅
(
1
P
+
1
R
)
\frac{1}{F1}=\frac{1}{2}\cdot(\frac{1}{P}+\frac{1}{R})
F
1
1
=
2
1
⋅
(
P
1
+
R
1
)
F
1
=
2
×
P
×
P
P
+
R
=
2
×
T
P
样
例
总
数
+
T
P
−
T
N
F1=\frac{2\times P \times P}{P+R}=\frac{2\times TP}{样例总数+TP-TN}
F
1
=
P
+
R
2
×
P
×
P
=
样
例
总
数
+
T
P
−
T
N
2
×
T
P
sklearn.metrics.f1_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None)
Fβ:加权调和平均
能够表达对查全率和查准率的不同偏好
1
F
β
=
1
1
+
β
2
⋅
(
1
P
+
β
2
R
)
\frac{1}{F_\beta}=\frac{1}{1+\beta^2}\cdot(\frac{1}{P}+\frac{\beta^2}{R})
F
β
1
=
1
+
β
2
1
⋅
(
P
1
+
R
β
2
)
F
β
=
(
1
+
β
2
)
×
P
×
P
(
β
2
×
P
)
+
R
F_\beta=\frac{(1+\beta^2)\times P \times P}{(\beta^2 \times P)+R}
F
β
=
(
β
2
×
P
)
+
R
(
1
+
β
2
)
×
P
×
P
β>0 度量了查全率对查准率的相对重要性 β=1时退化为标准F1;
β<1时查准率更重要;β>1时查全率更重要。
sklearn.metrics.fbeta_score(y_true, y_pred, beta, labels=None, pos_label=1, average='binary', sample_weight=None)
3.2.6. macro、micro
上面是针对一个二分类问题,当我们有多个二分类混淆矩阵(多次训练/测试); 或者多个数据集上进行训练/测试,希望估计算法的全局性能; 或者多分类任务,该怎么计算?
-
方法一:macro宏观。
1.先在混淆矩阵上分别计算出各自的查准率和查全率,记为(P1,R1),(P2,R2),…(Pn,Rn)
2.计算平均值(是先对每一个类统计指标值,然后在对所有类求算术平均值)
宏查准率:
ma
c
r
o
−
P
=
1
n
∑
i
=
1
n
P
i
macro-P = \frac{1}{n}\sum^n_{i=1}P_i
m
a
c
r
o
−
P
=
n
1
i
=
1
∑
n
P
i
宏查全率 :
ma
c
r
o
−
R
=
1
n
∑
i
=
1
n
R
i
macro-R = \frac{1}{n}\sum_{i=1}^nR_i
m
a
c
r
o
−
R
=
n
1
i
=
1
∑
n
R
i
宏F1 :
ma
c
r
o
−
F
1
=
2
×
m
a
c
r
o
−
P
×
m
a
c
r
o
−
R
m
a
c
r
o
−
P
+
m
a
c
r
o
−
R
macro-F1=\frac{2\times macro-P \times macro-R}{macro-P+macro-R}
m
a
c
r
o
−
F
1
=
m
a
c
r
o
−
P
+
m
a
c
r
o
−
R
2
×
m
a
c
r
o
−
P
×
m
a
c
r
o
−
R
-
方法二:micro微观。
1.先将个混淆矩阵的对应元素进行平均,得到TP、FP、TN、FN的平均值
TP
‾
、
F
P
‾
、
T
N
‾
、
F
N
‾
\overline {TP}、\overline {FP}、\overline {TN}、\overline {FN}
T
P
、
F
P
、
T
N
、
F
N
2.基于这些平均值计算
微查准率 :
ma
c
r
o
−
P
=
T
P
‾
T
P
‾
+
F
P
‾
macro-P=\frac{\overline {TP}}{\overline {TP}+\overline {FP}}
m
a
c
r
o
−
P
=
T
P
+
F
P
T
P
微查全率:
mi
c
r
o
−
R
=
T
P
‾
T
P
‾
+
F
N
‾
micro-R=\frac{\overline{TP}}{\overline{TP}+\overline{FN}}
m
i
c
r
o
−
R
=
T
P
+
F
N
T
P
微F1:
mi
c
r
o
−
F
1
=
2
×
m
i
c
r
o
−
P
×
m
i
c
r
o
−
R
m
i
c
r
o
−
P
+
m
i
c
r
o
−
R
micro-F1=\frac{2\times micro-P \times micro-R}{micro-P+micro-R}
m
i
c
r
o
−
F
1
=
m
i
c
r
o
−
P
+
m
i
c
r
o
−
R
2
×
m
i
c
r
o
−
P
×
m
i
c
r
o
−
R
-
average:宏平均和微平均的对比
1.如果每个class的样本数量差不多,那么宏平均和微平均没有太大差异
2.如果每个class的样本数量差异很大,而且你想:
更注重样本量多的class:使用宏平均
更注重样本量少的class:使用微平均
3.如果微平均大大低于宏平均,检查样本量多的class
4.如果宏平均大大低于微平均,检查样本量少的class - 综合代码:
sklearn.metrics.precision_recall_fscore_support(y_true,y_pred,beta=1.0,labels=None,pos_label=1,average=None,warn_for=(‘precision’,’recall’,’f-score’),sample_weight=None)
微观:average=‘micro’;宏观:average=‘macro’
3.3 ROC与AUC
很多学习器是为测试样本产生一个实值或者预测概率,然后将这个预测值与一个分类阈值(threshold)进行比较,若大于阈值则分为正类,否则为反类
3.3.1 ROC
- 排序本身的质量很能体现出一个模型的泛化性能,ROC曲线就是一个用来衡量排序质量的工具。
-
和P-R曲线相似,只是纵横轴不一样。根据学习器预测结果对样例进行排序,按此顺序逐个把样本作为正例进行预测,每次计算得到两个重要的值TPR、FPR分别作为纵、横轴,得到ROC曲线。
TPR真正例率 :
TP
R
=
T
P
T
P
+
F
N
TPR=\frac{TP}{TP+FN}
T
P
R
=
T
P
+
F
N
T
P
FPR假正例率 :
FP
R
=
F
P
T
N
+
F
P
FPR=\frac{FP}{TN+FP}
F
P
R
=
T
N
+
F
P
F
P
若一个学习器的ROC曲线在另一学习器曲线的外面,则外面的那个性能更好。 若二者交叉,则比较曲线下面的面积,即AUC
sklearn.metrics.roc_curve(y_true, y_score, pos_label=None, sample_weight=None, drop_intermediate=True)
3.3.2 AUC
A
U
C
=
1
2
∑
i
=
1
m
−
1
(
x
i
+
1
−
x
i
)
(
y
i
+
y
i
+
1
)
AUC=\frac{1}{2}\sum_{i=1}^{m-1}(x_{i+1}-x_i)(y_i+y_{i+1})
A
U
C
=
2
1
i
=
1
∑
m
−
1
(
x
i
+
1
−
x
i
)
(
y
i
+
y
i
+
1
)
高*(上底+下底)/2
sklearn.metrics.roc_auc_score(y_true, y_score, average='macro', sample_weight=None)
等价于以下两句:
fpr,tpr,thresholds=metrics.roc_curve(y_true,y_scores,pos_label=1)
metrics.auc(fpr,tpr)
3.4. 代价敏感错误率、代价曲线
不同类型的错误所造成的后果不同。为权衡不同类型错误造成的不同损失,可为错误赋予“非均等代价”。
3.4.1. 代价矩阵
一般来说,
c
o
s
t
i
i
=
0
cost_{ii}=0
c
o
s
t
i
i
=
0
;但把第0类错预测为第1类和把第1类错预测为第0类这两种错误的代价是不同的。重要的不是绝对值的大小而是它们的比值。eg:
c
o
s
t
01
/
c
o
s
t
10
>
1
cost_{01}/cost_{10}>1
c
o
s
t
0
1
/
c
o
s
t
1
0
>
1
, 说明把第0类错预测为第1类的代价更高。
3.4.2. 代价敏感错误率
E
(
f
;
D
;
c
o
s
t
)
=
1
m
[
∑
x
i
∈
D
+
I
(
f
(
)
x
i
=
̸
y
i
)
×
c
o
s
t
01
+
∑
x
i
∈
D
−
I
(
f
(
)
x
i
=
̸
y
i
)
×
c
o
s
t
10
]
E(f;D;cost)=\frac{1}{m}[\sum_{x_i \in D^+}\mathbb I(f()x_i=\not y_i) \times cost_{01}+\sum_{x_i \in D^-}\mathbb I(f()x_i =\not y_i) \times cost_{10}]
E
(
f
;
D
;
c
o
s
t
)
=
m
1
[
x
i
∈
D
+
∑
I
(
f
(
)
x
i
=
y
i
)
×
c
o
s
t
0
1
+
x
i
∈
D
−
∑
I
(
f
(
)
x
i
=
y
i
)
×
c
o
s
t
1
0
]
D
+
、
D
−
D^+、D^-
D
+
、
D
−
分别是样例集D的正例子集和反例子集
3.4.3. 代价曲线
- 非均等条件下,ROC曲线不能直接反映出学习器的期望总体代价,要用“代价曲线”。 代价曲线横轴是取值为[0,1]的正例概率代价P
-
横轴P(+)cost :
P(
+
)
c
o
s
t
=
p
×
c
o
s
t
01
p
×
c
o
s
t
01
+
(
1
−
p
)
×
c
o
s
t
10
P(+)cost=\frac{p\times cost_{01}}{p \times cost_{01}+(1-p)\times cost_{10}}
P
(
+
)
c
o
s
t
=
p
×
c
o
s
t
0
1
+
(
1
−
p
)
×
c
o
s
t
1
0
p
×
c
o
s
t
0
1
-
纵轴costnorm:
co
s
t
n
o
r
m
=
F
N
R
×
p
×
c
o
s
t
01
+
(
1
−
p
)
×
c
o
s
t
10
p
×
c
o
s
t
01
+
(
1
−
p
)
×
c
o
s
t
10
cost_{norm}=\frac{FNR\times p\times cost_{01}+(1-p)\times cost_{10}}{p\times cost_{01}+(1-p)\times cost_{10}}
c
o
s
t
n
o
r
m
=
p
×
c
o
s
t
0
1
+
(
1
−
p
)
×
c
o
s
t
1
0
F
N
R
×
p
×
c
o
s
t
0
1
+
(
1
−
p
)
×
c
o
s
t
1
0
-
是取值为[0,1]的归一化代价。 规范化:将不同变化范围的值映射到相同的固定范围中,[0,1]也称归一化
假反例率 FNP=1-TPR
-
是取值为[0,1]的归一化代价。 规范化:将不同变化范围的值映射到相同的固定范围中,[0,1]也称归一化
4. 比较检验
5. 偏差与方差
记录自己的学习过程,方便日后查阅,如有不对的地方还请指教!如果你喜欢欢迎点赞、评论\(^o^)/~