【机器学习】吃瓜笔记
- 误差与过拟合
- 训练集与测试集的划分方法
- 留出法——互斥
- 交叉验证法
- 自助法
- 性能度量
- 最常见的性能度量
- 查准率/查全率/F1
- ROC与AUC
误差与过拟合
学习器对样本的实际预测结果与样本的真实值之间的差异成为:误差(error)。
在训练集上的误差称为训练误差(training error)或经验误差(empirical error)。
在测试集上的误差称为测试误差(test error)。
学习器在所有新样本上的误差称为泛化误差(generalization error)。
过拟合(overfitting)
训练集与测试集的划分方法
几种常用的划分方法:
留出法——互斥
将数据集D划分为两个互斥的集合,一个作为训练集S,一个作为测试集T,满足D=S∪T且S∩T=∅,常见的划分为:大约2/3-4/5的样本用作训练,剩下的用作测试。需要注意的是:训练/测试集的划分要尽可能保持数据分布的一致性,以避免由于分布的差异引入额外的偏差,常见的做法是采取分层抽样。同时,由于划分的随机性,单次的留出法结果往往不够稳定,一般要采用若干次随机划分,重复实验取平均值的做法。
交叉验证法
将数据集D划分为k个大小相同的互斥子集,满足D=D1∪D2∪…∪Dk,Di∩Dj=∅(i≠j),同样地尽可能保持数据分布的一致性,即采用分层抽样的方法获得这些子集。
自助法
自助法的基本思想是:给定包含m个样本的数据集D,每次随机从D 中挑选一个样本,将其拷贝放入D’,然后再将该样本放回初始数据集D 中,使得该样本在下次采样时仍有可能被采到。重复执行m 次,就可以得到了包含m个样本的数据集D’。
# 分层抽样:按照类标签设定的比例进行分层抽样,按照每个分组单独随机抽样,从每层抽取一定/大小/比例的数据
# data = pd.read_csv('.\report_card.csv')
# #sample_probability_per_class = [{'Class': 'M', 'Probability': 0.1}, {'Class': 'F', 'Probability': 0.1}, {'Class': 'I', 'Probability': 0.1}]
# sample_size_per_class = [{'Class': '是', 'Size': 1}, {'Class': '否', 'Size': 2}]
# label = data['是否提干']
# _dict = {}
# for item in sample_size_per_class:
# for k, v in item.items():
# _dict.setdefault(k, []).append(v)
# s_key, s_value = _dict['Class'], _dict['Size']
# n_dict = dict(zip(s_key, s_value))
# n = len(sample_size_per_class)
# def AbsoluteSampling(group, n_dict):
# name = group.name
# sam_n = n_dict[name]
# return group.sample(n=sam_n) # 返回按大小分组后的数据
# result = data.groupby(label, group_keys=False).apply(AbsoluteSampling, n_dict)
# result
# 按比例分层抽
# data = pd.read_csv('.\report_card.csv')
# #sample_probability_per_class = [{'Class': 'M', 'Probability': 0.1}, {'Class': 'F', 'Probability': 0.1}, {'Class': 'I', 'Probability': 0.1}]
# sample_probability_per_class = [{'Class': '是', 'Probability': 0.1}, {'Class': '否', 'Probability': 0.1}]
# label = data['是否提干']
# n = len(sample_probability_per_class)
# _dict = {}
# for item in sample_probability_per_class:
# for k, v in item.items():
# _dict.setdefault(k, []).append(v)
# p_key, p_value = _dict['Class'], _dict['Probability']
# # p_value = {item['Probability'] for item in sample_probability_per_class for key in item.items()}
# # p_key = {item['Class'] for item in sample_probability_per_class for key in item.items()}
# frac_dict = dict(zip(p_key, p_value))
# frac_dict
# def ProbabilitySampling(group, frac):
# name = group.name
# frac = frac[name]
# return group.sample(frac=frac) # 返回按比例分组后的数据
# result = data.groupby(label, group_keys=False).apply(ProbabilitySampling, frac_dict)
# result
# 数据拆分:train_test_split或pandas.sample
def sample(self):
data = pd.DataFrame()
split_ratio = self.split_ratio
seed = random.randint(-2011, 2011)
# train, test = train_test_split(data, test_size=split_ratio, random_state=seed)
train = data.sample(frac=split_ratio, random_state=seed, axis=0)
test = data[~data.index.isin(train.index)]
return train, test
# HiveSQL拆
def sample(self):
train = pd.DataFrame()
test = pd.DataFrame
total_num = await train.count()
train_num = round(total_num * self.split_ratio)
seed = random.randint(-2011, 2011)
sql = "SELECT *, ROW_NUMBER() OVER(ORDER BY 0) AS hr_temp_col FROM %s ORDER BY RAND(%d)" % (train.hr_view, seed)
train_sql = "SELECT * FROM (%s) hr_temp_table_train LIMIT %d" % (sql, train_num)
# limit Y offset X :跳过 X 个数据,选取 Y 个数据
test_sql = "SELECT * FROM (%s) hr_temp_table_test LIMIT %d OFFSET %d" % (sql, total_num - train_num, train_num)
# train_sql = "SELECT *, ROW_NUMBER() OVER(ORDER BY 0) AS hr_temp_col FROM %s ORDER BY RAND(%d) LIMIT %d" % (
# train.hr_view, seed, train_num)
# test_sql = "SELECT *, ROW_NUMBER() OVER(ORDER BY 0) AS hr_temp_col FROM %s ORDER BY RAND(%d) DESC LIMIT %d" % (
# test.hr_view, seed, total_num - train_num)
# train_sql = "SELECT * FROM (%s) hr_temp_table_train ORDER BY hr_temp_col" % train_sql
# test_sql = "SELECT * FROM (%s) hr_temp_table_test ORDER BY hr_temp_col" % test_sql
train.sql = train.index
test.sql = test.index
return train, test
性能度量
性能度量(performance measure)是衡量模型泛化能力的评价标准,在对比不同模型的能力时,使用不同的性能度量往往会导致不同的评判结果。
最常见的性能度量
在回归任务即预测连续值的问题,最常用的性能度量是“均方误差”MSE(mean squared error)。
在分类任务即预测离散值的问题,最常用的是错误率和精度,错误率是分类错误的样本数占样本总数的比例,精度则是分类正确的样本数占样本总数的比例,易知:错误率+精度=1。
查准率/查全率/F1
在推荐系统中,我们只关心推送给用户的内容用户是否感兴趣(即查准率),或者说所有用户感兴趣的内容我们推送出来了多少(即查全率)。因此,使用查准/查全率更适合描述这类问题。
“P-R曲线”正是描述查准/查全率变化的曲线,P-R曲线定义如下:根据学习器的预测结果(一般为一个实值或概率)对测试样本进行排序,将最可能是“正例”的样本排在前面,最不可能是“正例”的排在后面,按此顺序逐个把样本作为“正例”进行预测,每次计算出当前的P值和R值
有时候我们会有多个二分类混淆矩阵,例如:多次训练或者在多个数据集上训练,那么估算全局性能的方法有两种,分为宏观和微观。简单理解,宏观就是先算出每个混淆矩阵的P值和R值,然后取得平均P值macro-P和平均R值macro-R,在算出Fβ或F1,而微观则是计算出混淆矩阵的平均TP、FP、TN、FN,接着进行计算P、R,进而求出Fβ或F1。
ROC与AUC
如上所述:学习器对测试样本的评估结果一般为一个实值或概率,设定一个阈值,大于阈值为正例,小于阈值为负例,因此这个实值的好坏直接决定了学习器的泛化性能,若将这些实值排序,则排序的好坏决定了学习器的性能高低。ROC曲线正是从这个角度出发来研究学习器的泛化性能,ROC曲线与P-R曲线十分类似,都是按照排序的顺序逐一按照正例预测,不同的是ROC曲线以“真正例率”(True Positive Rate,简称TPR)为横轴,纵轴为“假正例率”(False Positive Rate,简称FPR),ROC偏重研究基于测试样本评估值的排序好坏。
同样地,进行模型的性能比较时,若一个学习器A的ROC曲线被另一个学习器B的ROC曲线完全包住,则称B的性能优于A。若A和B的曲线发生了交叉,则谁的曲线下的面积大,谁的性能更优。ROC曲线下的面积定义为AUC(Area Uder ROC Curve),不同于P-R的是,这里的AUC是可估算的,即AOC曲线下每一个小矩形的面积之和。易知:AUC越大,证明排序的质量越好,AUC为1时,证明所有正例排在了负例的前面,AUC为0时,所有的负例排在了正例的前面。