1.经验误差与过度拟合
错误率(E):错误样本数(a)占样本总数(m)的比例 E = a / m
精度:1 - E = 1 - a/m (通常为百分比形式)
误差:学习器的实际输出与样本的真实输出之间的差异
学习器在训练集上的误差称为“训练误差”或“经验误差”,在新样本上的误差称为“泛化误差”
过拟合(过配):学习把训练样本学得“太好”时,可能把训练样本自身的一些特点当作潜在样本都具 有的一般性质,导致泛化性能下降 与过拟合相对的即欠拟合(欠配)
2.评估方法
划分训练集S和测试集T
(1)留出法 hold-out
将数据集划分为两个互斥的集合,一个集合作为训练集S,另一个集合作为测试集T,在S上训练出模型,用T评估其测试误差作为对泛化误差的估计。
注意:从采样角度,通常保留类别比例的采样方式(分层采样)
采用若干次随即划分、重复进行实验后取平均值作为留出法的评估结果
通常将样本的2/3~4/5用于训练,剩余样本用于测试
from sklearn.model_selection import train_test_split
# 用train_test_split划分训练集和测试集
train_X , test_X, train_Y ,test_Y = train_test_split(X, Y, test_size=0.2,random_state=0)
# X为原始数据的自变量,Y为原始数据因变量;
# train_X,test_X是将X按照8:2划分所得;
# train_Y,test_Y是将X按照8:2划分所得;
# test_size是划分比例;
# random_state设置是否使用随机数
#例如:
#in
X = np.arange(10).reshape((5, 2))
y = np.arange(5)
# print(X)
# print(list(y))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33,random_state=42)
print(X_train,y_train,X_test,y_test)
#out
#[[4 5] [0 1] [6 7]]
#[2 0 3]
#[[2 3] [8 9]]
#[1 4]
(2)交叉验证法 cross validation
将数据集划分为k个大小相似的互斥子集,每个子集都尽可能保持数据分布的一致性(分层采样得到)每次用k-1个子集的并集作为训练集,余下的1个子集作为测试集,从而可以进行k次训练和测试,最终返回的是这k个测试结果的均值
此方法评估结果的稳定性和保真性很大程度上取决于k的取值,因此通常成为 “k折交叉验证”
为减小因样本划分不同引入的差别,k折交叉验证通常要随即使用不同的划分重复p次,最终评估结果为p次k折交叉验证结果的均值(10次10折交叉验证与100次留出法都进行了100次训练/测试)
若数据集有m个样本,当k = m,得到了交叉验证法的特例------留一法(LOO)
绝大数情况下,留一法被实际评估的模型与期望估计的训练出的模型很相似,评估结果比较准确 缺陷:数据集比较大时训练m个模型的计算开销可能是难以忍受的,而且其估计结果未必永远准确
from sklearn.model_selection import KFold
KFold(n_splits=5, *, shuffle=False, random_state=None)
# n_splits:int, 默认为5(表示拆分成5折)
# shuffle: bool, 默认为False 切分数据集之前是否对数据进行洗牌 True洗牌 False不洗牌
# random_state:int, 默认为None 可按自己喜好设定成整数,设定好后,就不能再更改
# shuffle为True,random_state为None,则每次运行代码,获得的数据切分都不一样,
# random_state指定时,则每次运行代码,都能获得同样的切分数据,保证实验可重复
方法
1.get_n_splits(X=None, y=None, groups=None) 返回交叉验证器中的分裂迭代次数
2.split(X, y=None, groups=None) 生成索引以将数据拆分为训练集和测试集
X:类似形状的数组 (n_samples, n_features) 训练数据,其中
n_samples
是样本n_features
数,是特征数。y:类似形状的数组 (n_samples,),默认无 监督学习问题的目标变量
group:形状类似数组的组(n_samples,),默认无 将数据集拆分为训练/测试集时使用的样本的分组标签
return:train和test的索引,注意返回的是每个集合的索引
# 例
import numpy as np
from sklearn.model_selection import KFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4])
kf = KFold(n_splits=2) #初始化
kf.get_n_splits(X)
print(kf)
for train_index, test_index in kf.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
#结果
# KFold(n_splits=2, random_state=None, shuffle=False)
# TRAIN: [2 3] TEST: [0 1]
# TRAIN: [0 1] TEST: [2 3]
(3)自助法 bootstrapping
以自助采样法(bootstrap sampling)为基础,给定包含m个样本的数据集D,对它进行采样产生数据集D':每次随机从D中挑选一个样本,将其拷贝放入D',然后将该样本放回初始数据集D中,是该样本在下次采样时仍可能被采到。过程重复执行m次后,就得到了包含m个样本的数据集D'。
m次采样中始终不被采到的概率大约为0.368,因此我们可以将D'作为训练集,D-D'作为测试集,测试结果亦称为“包外估计”。
此方法在数据集较小、难以有效划分训练/测试集时有用,但其产生的数据集改变了初始数据集的分布,会引入估计偏差。
from sklearn.utils import resample
resample(*arrays, replace=True, n_samples=None, random_state=None, stratify=None)
*arrays:形状(n_个样本)或(n_个样本,n_个输出)的类似数组的序列
# 可索引数据结构可以是数组、列表、数据帧或具有一致第一维度的scipy稀疏矩阵
#replace:bool, default=True
# 使用替换实现重采样。如果为False,这将实现(切片)随机排列。
#n_samples:int, default=None 要生成的样本数
#random_state:int, RandomState instance or None, default=None 确定随机数的生成,以洗牌数据
#stratify:类似数组的形状(n_个样本)或(n_个样本,n_个输出),默认无
#例:
import numpy as np
X = np.array([[1., 0.], [2., 1.], [0., 0.]])
y = np.array([0, 1, 2])
from scipy.sparse import coo_matrix
X_sparse = coo_matrix(X)
#coo_matrix((data, (row, col)), shape=(4, 4)).toarray() 稀疏矩阵
from sklearn.utils import resample
X, X_sparse, y = resample(X, X_sparse, y, random_state=0)
resample(y, n_samples=2, random_state=0)
(4)调参和最终模型
调参:在进行模型评估与选择时,除了对适用学习的算法进行选择,还需对算法参数进行设定
用于评估测试的数据集称为“验证集”
3.性能度量
(1)错误率与精度
错误率:分类错误的样本数占样本总数的比例
精度:分类正确的样本数占样本总数的比例
(2)查准率(percision)、查全率(recall)、F1
二分类问题将样例根据真实类别与学习器预测类别的组合划分为真正例(TP)、假正例(FP)、真反例(TN)、假反例(FN),有 样例总数=TP+FP+TN+FN
真实情况 | 预测结果 | |
正例 | 反例 | |
正例 | TP(真正例) | FN(假反例) |
反例 | FP(假正例) | TN(真反例) |
查准率P:
查全率R:
查准率和查准率是一对矛盾的度量。查准率高时,查全率低,反之同理。
PR图(PR曲线)
若一个学习器的PR曲线被另一个学习器的曲线完全“包住”,则可断言后者性能完全优于前者;
若两个学习器的曲线发生交叉则很难断言孰优孰劣,若需要判断,一般比较曲线下面积的大小。
平衡点(BEP):"查准率=查全率"时的取值
F1度量 :
是基于查准率与查全率的调和平均定义的:
一般形式():
β = 1退化为标准的F1;β>1 查全率有更大影响;β<1 查准率有更大影响
宏查全率(macro-R)、宏查准率(macro-P):先在各混淆矩阵上分别计算查准率和查全率, 再计算平均值
微查全率(micro-R)、微查准率(micro-P):先将各混淆矩阵对应元素进行平均,得到TP、 FP、TN、FN的平均值,在基于这些平均值计算
(3)ROC 、AUC
ROC(受试者工作特征)曲线:真正例率(TPR): 假正例率(FPR):
AUC可通过对ROC曲线下各部分的面积求和而得,假定ROC曲线是坐标为的点按序连接形成
,则AUC可估算为
(4)代价敏感错误率与代价权限
如下为一个二分类任务代价矩阵:其中表示将第i类样本预测为第j类样本的代价
一般
,损失程度相差越大,
与
值差别越大
若上表第0类作为正例、第1类作为反例,则代价敏感错误率为
下图为代价曲线与期望总体代价
4.比较检验
(1) 假设检验
“假设”是对学习器泛化错误率分布的某种判断或猜想
(2)交叉验证t检验
若要进行有效的假设检验,一个重要前提是测试错误率均为泛化错误率的独立采样,但样本通常有限,交叉验证等方法在使用时训练集会有一定程度的重叠,使测试错误率实际并不独立,会导致过高估计假设成立的概率。为缓解这一问题可采用“5x2交叉验证”法。
(3)McNemar检验
对于二分类问题,使用留出法不仅可以估计学习器A和B的测试错误率,还可以获得两学习器分类结果的差别,两个都正确、都错误、一个正确一个错误的样本数:
(4)Friedman检验、Nemenyi后续检验
Friedman检验:
服从自由度为k-1和(k-1)(N-1)的F分布
若“所有算法的性能相同”这个假设被拒绝,说明算法性能显著不同,需要“后续检验”进一步区分各算法,常用的有Nemenyi后续检验。Nemenyi检验计算出平均序值差别的临界值域:
5.偏差与方差
“偏差-方差分解”是解决学习算法泛化性能的一种重要工具
偏差与方差是有冲突的,称为偏差-方差窘境
泛化误差可分解为偏差、方差与噪声之和