1.1 样本划分的必要性
在现实的机器学习任务中,我们往往是利用搜集到的尽可能多的样本集来输入算法进行训练,以尽可能高的精度为目标,但这里便出现一个问题,一是很多情况下我们不能说搜集到的样本集就能代表真实的全体,其分布也不一定就与真实的全体相同,但是有一点很明确,样本集数量越大则其接近真实全体的可能性也就越大;二是很多算法容易发生过拟合(overfitting),即其过度学习到训练集中一些比较特别的情况,使得其误认为训练集之外的其他集合也适用于这些规则,这使得我们训练好的算法在输入训练数据进行验证时结果非常好,但在训练集之外的新测试样本上精度则剧烈下降,这样训练出的模型可以说没有使用价值;因此怎样对数据集进行合理的抽样-训练-验证就至关重要。
在数据分析过程中,如果给定的样本数据充足,为了保证模型在实际系统中能够起到预期作用,一般需要将总样本分划分成独立的3部分如下。
1) 训练集(Training Set):
用于模型拟合的数据样本,即建立模型使用的样本集。
2) 验证集(Validation Set):
是模型训练过程中单独留出的样本,用于调整模型的超参数和用于对模型的能力进行初步评估
3) 测试集(Test Set):
用来测试模型在预测未知样本时的准确率,即评估最终模型的泛化能力。
泛化能力(Generalization Ability),是指机器学习模型对新鲜样本的适应能力,即对于任意未知类型的新样本,模型预测的准确率,它的目标是寻找一个假设h(x),使得对于所有的样本,都有h(x)=c(x)(c(x)为实际类别)。
一般做预测分析时,会将样本划分为两个部分:
- 一部分是训练集数据,用于构建模型
- 一部分是测试集数据,用于检验模型
但是有时模型的构建过程中也需要检验模型,辅助模型构建,这是就需要在样本中再划分出一部分作为验证集。验证集是可选项。
训练集的规模远大于验证集和测试集:
- 在小样本机器学习中,训练集、测试集、验证集的比例一般为7:1:2
- 在大样本机器学习中,训练集所占的比例一般为99%以上,验证集和测试集占1%
拓展:样本和参数在统计学和机器学习中的意义
对于统计学来说,样本的作用是通过样本的特征(统计量)来估计总体的特征(参数,如方差、均值)。
而在机器学习中,样本的作用是利用训练集来建立模型和参数估计,利用测试集进行模型测试。
统计学和机器学习中都有“参数估计”的概念,但是它们的含义是不同的。
- 统计学中的参数是指总体的方差、均值等。
- 机器学习中的参数是指模型的参数,如神经网络中各个节点的权重值。
机器学习的步骤:
- 首先,在训练集上用不同的学习方法训练多个模型
- 然后,将训练到的多个模型在验证集上验证,选择验证误差最小的模型作为最终的模型
- 最后,用测试集对选出的最终模型进行测试。
具体方法如下:
先不看测试集中的类别属性,将测试集中的样本特征集输入机器学习模型中,看给模型输出的类别属性与测试集中的实际类别属性差异有多大。差异越小,就说明模型的有效性越高。
测试集只是测试模型的准确率,而不会再对模型进行调整,这是测试集和验证集的明显区别。
1.2 划分样本的方法
1.2.1 sklearn.model_selection.train_test_split
随机划分训练集和测试集
X_train,X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=None, train_size=None, random_state=None, shuffle=True, stratify=None)
- X:待分割的样本集中的自变量部分,通常为二维数组或矩阵的形式;
- y:待分割的样本集中的因变量部分,通常为一维数组;
- test_size:用于指定验证集所占的比例,有以下几种输入类型:
+ 1.float型,0.0~1.0之间,此时传入的参数即作为验证集的比例;
+ 2.int型,此时传入的参数的绝对值即作为验证集样本的数量;
+ 3.None,这时需要另一个参数train_size有输入才生效,此时验证集去为train_size指定的比例或数量的补集;
+ 4.缺省时为0.25,但要注意只有在train_size和test_size都不输入值时缺省值才会生效;
- train_size:基本同test_size,但缺省值为None,其实test_size和train_size输入一个即可;
- random_state:int型,控制随机数种子,默认为None,即纯随机(伪随机);
- stratify:控制分类问题中的分层抽样,默认为None,即不进行分层抽样,当传入为数组时,则依据该数组进行分层抽样(一般传入因变量所在列);
- shuffle:bool型,用来控制是否在分割数据前打乱原数据集的顺序,默认为True,分层抽样时即stratify为None时该参数必须传入False;
返回值:
依次返回训练集自变量、测试集自变量、训练集因变量、测试集因变量,因此使用该函数赋值需在等号右边采取X_train, X_test, y_train, y_test
的形式
import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)
X
list(y)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42)
X_train
y_train
X_test
y_test
1.2.2 简单交叉验证
而在数据不充足的情况下,为了选择好的模型,可以采取交叉验证法。交叉验证的一个显著特点是:摒弃了独立验证集,仅将数据划分为训练集和测试集。交叉验证又可细分为:简单交叉验证、K折交叉验证、留一交叉验证。
- 首先随机地将已给数据分成两部分:训练集、测试集
- 然后在训练集上用不同的学习方法训练多个模型,在测试集上评价各个模型的测试误差
- 选择测试误差最小的模型作为最终的模型,这个模型可以用来预测新数据
- 优点:
简单方便。直接将数据集按比例拆分成训练集和测试集,比如50:50。 - 缺点:
没有充分利用数据,结果具有偶然性。如果按50:50分,会损失掉50%的数据信息,因为有50%的数据没有利用来训练模型。
在sklearn的model_selection模块中提供了train_test_split函数,可对数据集进行拆分,实现简单交叉验证。
train_test_split函数的基本使用格式如下。
sklearn.model_selection.train_test_split(*arrays, test_size=None, train_size=None, random_state=None, shuffle=True, stratify=None)
- 如果传入的是一组数据集,那么生成的就是这一组数据集随机划分后的训练集和测试集,总共两组。
- 如果传入的是两组数据集,则生成的训练集和测试集分别两组,总共4组。
from sklearn.datasets import load_diabetes
diabetes = load_diabetes() # 将数据集赋值给diabetes变量
print('diabetes数据集的长度为:', len(diabetes))
print('diabetes数据集的类型为:', type(diabetes))
diabetes_data = diabetes['data']
print('diabetes数据集的数据为:','\n', diabetes_data)
diabetes_target = diabetes['target'] # 取出数据集的标签
print('diabetes数据集的标签为:\n', diabetes_target)
diabetes_names = diabetes['feature_names'] # 取出数据集的特征名
print('diabetes数据集的特征名为:\n', diabetes_names)
diabetes_desc = diabetes['DESCR'] # 取出数据集的描述信息
print('diabetes数据集的描述信息为:\n', diabetes_desc)