《机器学习》阅读笔记 第二章

Contents

  • 1. 模型评估[^1]
    • 1.1 过拟合
    • 1.2 评估方法
      • 留出法(hold-out)
      • 交叉验证(cross validation)
      • 自助法(bootstrap)
    • 1.3 调参
  • 2. 性能度量
    • 2.1 回归任务
    • 2.2 分类任务
      • 分类精度与交叉熵损失
      • 查准率和查全率
      • ROC曲线、AUC和代价曲线

1. 模型评估1

1.1 过拟合

一个模型在训练集上精度较高,而在测试集上表现(泛化性能)不佳,称为过拟合。为什么会出现过拟合?这是因为模型将样本的特征训练的“太好了”,以至于将一些样本中特有的现象当作了“一般规律”。过拟合是机器学习算法需要解决的核心问题,不同的算法实际上是采用不同的手段缓解过拟合。在存在过拟合问题的情况下,发展出了一系列用于评价模型泛化能力的方法。

1.2 评估方法

留出法(hold-out)

  • 做法:直接将数据集划分成两个互斥的集合,一个称为训练集,用于模型的训练;另一个称作测试集,用于泛化性能的验证
  • 注意
    • 划分时要尽量使得两个集合中的类别比一致,类别不平衡容易导致泛化性能估计的偏差
    • 实际操作中,一般采用多次划分、估计测试误差后取平均的做法
    • 测试集的样本量不能太大(会导致训练模型与真实模型不一致),也不能太小(会导致评估结果不准确),采用经验比例 2 / 3 ∼ 4 / 5 2/3 \sim 4/5 2/34/5
from sklearn.model_selection import train_test_split
x1,x2,y1,y2 = train_test_split(X,Y,0.25)

交叉验证(cross validation)

将数据集划分成 k k k 个大小相似的互斥子集,每次用 k − 1 k-1 k1 个作为训练集,剩下的一个作为测试集,这样就有 k k k 次测试,取平均就得到最终的泛化误差。这一做法的好处在于,所有的样本都纳入训练了,若采用留出法,即使重复许多次,也可能有样本没有纳入训练。

from sklearn.model_selection import cross_val_score
scores = cross_val_score(estimator, X, Y, cv=10)

自助法(bootstrap)

对数据集 D D D m m m ( m m m 就是样本数) 次有放回抽样得到 D ′ D' D,某个样本 x i x_i xi 不在 D ′ D' D 中的概率是

( 1 − 1 m ) m (1-\frac{1}{m})^{m} (1m1)m

取极限得到

( 1 − 1 m ) m → e − 1 ≈ 0.368      a s      n → ∞ (1-\frac{1}{m})^{m} \rightarrow e^{-1} \approx 0.368 \;\;as\;\; n \rightarrow \infty (1m1)me10.368asn

这就是说,初始数据集 D D D 中约有 36.8% 的样本未出现在采样数据集 D ′ D' D中。于是我们可将 D ′ D' D 用作训练集, D / D ′ D/D' D/D 用作测试集。这样,实际评估的模型与期望评估的模型都使用 m m m 个训练样本,而我们仍有数据总量约 1/3 的、没在训练集中出现的样本用于测试。

可以这样理解自助法2:理想的抽样估计是从总体(真实分布)中抽取多个样本,计算参数估计量

F ⟶ i i d X ⟶ s θ ^ F \overset{iid}{\longrightarrow} X \overset{s}{\longrightarrow} \hat{\theta}\\ FiidXsθ^

然而实际中只能得到一个样本,因此对样本(经验分布)进行再抽样,得到bootstrap估计

F ^ ⟶ i i d X ∗ ⟶ s θ ^ ∗ \hat{F} \overset{iid}{\longrightarrow} X^* \overset{s}{\longrightarrow} \hat{\theta}^* F^iidXsθ^

自助法在数据集较小时比较有用,但是会改变初始数据集的分布,可能引入估计偏差。

1.3 调参

  • 常采用“网格搜索”(grid search)的方法,即设定每一个超参数可能的取值,让python遍历每一种组合,选出最好的那一种
  • 评估完成、选出最佳的模型(或超参数后),需要将所有数据再训练一次,作为最终模型提交
from sklearn.model_selection import GridSearchCV
parameters = {'beta': [0.001, 0.01, 0.1, 1], 
				'gamma':[0.001, 0.01, 0.1, 1]}
# 输出每一次搜索结果,并行计算,自动为估计器配置最优参数
gs = GridSearchCV(estimator, parameters, 
					refit = True, cv = 5, verbose = 2, n_jobs = -1)
gs.fit(X,y) 
print(gs.best_params_)
print(gs.best_score_)

2. 性能度量

2.1 回归任务

主要使用均方误差(MSE)

M S E = 1 m ∑ i m ( f ( x i ) − y i ) 2 MSE = \frac{1}{m}\sum_{i}^{m} (f(x_i)-y_i)^2 MSE=m1im(f(xi)yi)2

用OLS来理解,实际上就是使得MSE最小化。

2.2 分类任务

分类精度与交叉熵损失

分类精度

a c c = 1 m ∑ i m I ( f ( x i ) = y i ) acc = \frac{1}{m}\sum_{i}^{m} \mathbb{I}(f(x_{i})=y_{i}) acc=m1imI(f(xi)=yi)

但这个函数不太好求导做优化,所以算法里一般会用交叉熵损失作为目标函数

c e = − 1 m ∑ i m ∑ j T δ j i log ⁡ 2 f ( x i ) ce = -\frac{1}{m}\sum_{i}^{m}\sum_{j}^{T}\delta_{ji}\log_2{f(x_i)} ce=m1imjTδjilog2f(xi)

当样本 x i x_i xi 属于第 j j j 类时, δ j i = 1 \delta_{ji}=1 δji=1,否则为 0 0 0

查准率和查全率

精度无法完整反映模型的性能!考虑如下案例:已知100名贷款人中有一位会违约,现有一个模型的预测模式为预测所有人都不会违约。这样,虽然模型的精度能达到99%,但是没有什么用。为此,需要引入混淆矩阵及查准率、查全率的概念。

考虑如下混淆矩阵

预测为正例 预测为反例
真实为正例 TP FN
真实为反例 FP TN

定义查准率(precision)、查全率(recall)分别为:

P = T P T P + F P R = T P T P + F N P = \frac{TP}{TP+FP}\\[3mm] R = \frac{TP}{TP+FN} P=TP+FPTPR=TP+FNTP

查准率表示预测为正例的有多少确实是正例,查全率表示真实的正例中,有多少被预测出来了。注意,这两个值一定是针对某一个类别定义的,不能说某个模型的查准率是多少,只能说这个模型在某一类别上的查准率为多少。在开头举得例子中,违约的 R = 0 R=0 R=0,查全率表现不佳。

一般来说, P P P R R R 是一对互斥的指标,一个高了另一个就低。考虑一种极端的情况:将所有类别预测为正例,那么真实正例的 R = 1 R=1 R=1,而 P P P 可能比较低。

可以绘制P-R图直观地展示模型的预测能力。根据学习器的预测结果(一个0-1之间的概率值)对样例进行排序,排在前面的是学习器认为“最可能”是正例的样本,排在最后的则是学习器认为“最不可能”是正例的样本。按此顺序逐个把样本作为正例进行预测 ,则每次可以计算出当前的查全率、 查准率。以每一次的查准率为纵轴、查全率为横轴作图,就得到P-R图。基于P-R图可以定义一些综合考虑查准率、查全率的指标,如BEP, F 1 F_1 F1 F β F_{\beta} Fβ 等。

如果进行多次检验,就会得到多个混淆矩阵,此时可以基于每一次的结果定义宏/微查准率、查全率等。

ROC曲线、AUC和代价曲线

与P-R曲线类似,根据学习器预测结果对样例进行排序,将分类阈值依次设定为1、每个样本的预测概率,每次计算两个值作为横纵坐标,就画出了受试工作者特征(ROC)曲线,这两个值为“真正例率”(TPR)和“假正例率”(FPR)

T P R = T P T P + F N = R F P R = F P T N + F P TPR = \frac{TP}{TP+FN} = R\\[3mm] FPR = \frac{FP}{TN+FP} TPR=TP+FNTP=RFPR=TN+FPFP

AUC是ROC曲线下面积,它反映了样本预测的排序质量,AUC越大,认为模型分类性能越好。

注意,ROC曲线的绘制是基于混淆矩阵的,而混淆矩阵默认两类的分类错误代价的权重是相等的。而在非均等代价下,ROC 曲线不能直接反映出学习器的期望总体代价,需要用“代价曲线”(cost curve) 。

画ROC曲线的例子

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve
from sklearn.metrics import auc
# 计算 FPR,TPR 与 AUC 面积
fpr, tpr, thresholds = roc_curve(true_label, predict_label)
roc_auc = auc(fpr, tpr)
# 绘制 ROC 曲线
plt.figure(figsize=(16,9))
lw = 2
plt.plot(fpr, tpr, color='darkorange',
lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic (ROC)')
plt.legend(loc="lower right")
plt.show()

《机器学习》阅读笔记 第二章_第1张图片


  1. 周志华,《机器学习》,第二章,2.1-2.3 ↩︎

  2. 吕晓玲等,《数据科学统计基础》,第五章 ↩︎

你可能感兴趣的:(Datawhale寒假学习,吃瓜系列)