简介
Scikit-Learn是Python中使用最广泛的机器学习库之一。它经过优化,效率很高--而且它的高级API简单易行。
Scikit-Learn有大量的便利工具和方法,使预处理、评估和其他艰苦的过程变得像调用一个方法一样简单--并将数据在一个 培训和 测试集也不例外。
一般来说,分割数据的经验法则是80/20--80%的数据用于训练模型,而20%用于测试。这取决于你所使用的数据集,但80/20的比例非常普遍,可以让你顺利通过大多数数据集。
在本指南中,我们将看看如何在Scikit-Learn中使用split_train_test() 方法,以及如何配置参数,以便你能控制分割的过程。
安装Scikit-Learn
假设它还没有安装--Scikit-Learn可以通过pip 轻松安装。
$ pip install scikit-learn
一旦安装完毕,你可以通过导入库本身。
import sklearn
在大多数情况下,人们会避免导入整个库,因为它相当庞大,而会导入他们要特别使用的特定类或模块。
**注意:**这往往意味着人们在使用Scikit-Learn时有一个巨大的导入列表。
训练和测试集的重要性
在机器学习中训练一个(基本)模型时,最常见的程序遵循相同的粗略轮廓。
- 获取和处理数据,并将其输入到模型中。
Scikit-learn有各种数据集可供加载并用于训练模型*(虹膜、糖尿病、数字*......),主要用于基准测试/学习。
- 将数据集分割成训练集和测试集
- 建立一个模型并定义架构
- 编译模型
- 训练模型
- 验证结果
训练集是整个数据集的一个子集,我们一般不会在整个数据上训练一个模型。在非生成性模型中,训练集通常包含主数据集的80%左右的数据。正如它的名字所说,它是用来训练模型的。这个过程也被称为拟合模型。
不过,这条规则也有例外。
例如,在训练生成图像的生成式串行网络(GANs)时--你如何测试结果?在某些情况下,它们是非常主观的,因为它们代表了以前从未见过的新实例。在大多数生成模型中,至少到现在为止,通常需要人类来判断输出,在这种情况下,测试集是完全多余的。
此外,有时你需要多于或少于20%的测试数据,如果你使用交叉验证等技术,你可能希望测试数据少一点,以免从训练数据中 "夺走 "太多。例如,如果你在一个数据集中有1.000.000个实例,只拿出5%作为测试集,相当于50.000个实例,这很可能对任何模型的测试都是足够的。
测试集是整个数据集的一个子集,用于评估模型并检查它从训练集中学习的情况。
在评估之前,模型不能与测试集互动或看到测试集。第一次评估时,数据必须是未知的,否则就不是真正的测试模型。
什么是验证集?
验证集是专业和学术模型中常见的现象。验证集是从训练集中取出来的,在训练中用来验证模型的准确性*。*
在模型完成训练之前,测试集是完全断开的--但是验证集是在训练期间用来验证的。
**注意:**验证集不用于训练,模型不对数据进行训练,只是验证当前的历时。这种方式--它间接地在数据上进行训练,因为它确实影响了它的先验信念。
类似于如果你听到你自己的知识是不正确的--即使你不知道为什么,你也会学到更多。这就是为什么验证集近似于模型的准确性,而测试集即使在使用验证集的时候也是需要的。
它们有助于在训练过程中接近模型的实际性能,所以你不会在通过测试集进行测试后,不知不觉地得到一个虚幻的过拟合模型。你也可以使用验证集来调整模型,并在不暴露于测试集的情况下近似评估其能力。
深度学习框架,如Keras,除了你的常规训练accuracy ,还可以显示一个val_accuracy ,作为过拟合的一个好迹象。如果它们开始发散,说明你的模型在训练过程中过度拟合,当它们发散到一定程度时,你就不需要浪费时间进一步训练它了。此外,如果n epochs之后val_accuracy 没有改善,即使accuracy 正在增加,EarlyStopping 这样的回调也可以用来自动停止模型的训练。
创建一个验证集很容易。
从字面上看,你只需在训练集上运行train_test_split() ,该训练集已经被train_test_split() 方法分割,并从中提取出一个验证集。或者,你也可以手动创建一个验证集。
验证集的大小通常与测试集相似--训练集的10-20%之间是典型的。对于巨大的数据集,你可以做得比这低得多,但对于小的数据集,你可以拿出太多,使模型难以适应训练集的数据。
在接下来的章节中,我们还将使用同样的
train_test_split()方法取出验证集。
Scikit-Learn的数据集模块
Scikit-Learn内置了几个干净而流行的数据集,通常在学习过程中使用,并用于在简单任务上对模型进行基准测试。
如果你曾经阅读过有关Python中的机器学习的资源--你可能已经看到了这些最受欢迎的数据集中的一些。
- 虹膜- 3个类(花)的集合,每个类有50个样本,用于分类。
- 糖尿病- 总共有442个样本的集合,用于回归。
- 数字- 一组10个类(手写的数字),每类有大约180个样本,用于分类。
- 葡萄酒- 一组3类(葡萄酒),共178个样本,用于分类。
这些数据集中的每一个都可以通过datasets 模块加载其各自的函数。
from sklearn import datasets
X_iris, y_iris = datasets.load_iris(return_X_y=True)
X_diabetes, y_diabetes = datasets.load_diabetes(return_X_y=True)
X_digits, y_digits = datasets.load_digits(return_X_y=True)
X_wine, y_wine = datasets.load_wine(return_X_y=True)
另外,你也可以用特定的函数来加载。
from sklearn.datasets import load_iris
from sklearn.datasets import load_diabetes
from sklearn.datasets import load_digits
from sklearn.datasets import load_wine
X_iris, y_iris = load_iris(return_X_y=True)
X_diabetes, y_diabetes = load_diabetes(return_X_y=True)
X_digits, y_digits = load_digits(return_X_y=True)
X_wine, y_wine = load_wine(return_X_y=True)
默认情况下,这些方法返回一个Bunch 对象,包含数据和目标(数据和它们的类别),然而,如果你把return_X_y 参数设置为True ,就会返回一个(data, targets) 的元组,表示你要训练的数据和你希望分类器/回归模型击中的目标类别。
用*train_test_split()*拆分数据集
train_test_split() 方法位于sklearn.model_selection 模块中。
from sklearn.model_selection import train_test_split
在使用这个方法时,我们可以设置几个参数--默认的参数是非常合理的,可以执行75/25的分割。在实践中,Scikit-Learn的所有默认值都是相当合理的,设置为大多数任务提供了良好的服务。然而,值得注意的是这些默认值是什么,在它们不那么好用的情况下。
主要的两个参数是train_size 和test_size ,它们的值在0 和1 之间,它们的总和必须是1 。它们的值表示数据集的百分比比例,所以即使你只定义一个,如train_size ,test_size ,也等于1 - train_size ,反之亦然。
设置train_size和test_size参数
这是最常见的方法,它留给我们4个子集 -X_train,X_test,y_train 和y_test 。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y)
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
如果不设置train_size 或test_size ,默认值就会启动,将test_size 设置为0.25 ,以及一个补充的(0.75)train_size 。
(112, 4)
(38, 4)
(112,)
(38,)
正如你所看到的,训练集和测试集被分成75%/25%,因为在X_train 集里有112个实例,在X_test 集里有38个实例。
一些其他的分割比例是。80%/20%(非常常见),67%/33%,更少的是50%/50%。
设置其中的任何一个,都可以归结为定义train_test_split() 方法中的一个或两个参数。
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, test_size=0.2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
所有这三种分割方式都会导致相同的分割。
(120, 4)
(30, 4)
(120,)
(30,)
用*train_test_split()*创建一个验证集
验证集在训练过程中非常有用,它使你作为一个数据科学家的生活变得非常容易。
只要有可能,就尽量使用验证集。
没有内置的函数可以从训练集中提取验证集,然而,既然这可以归结为像以前一样分割它--为什么不使用相同的train_test_split() 方法?
让我们重新使用它来获得一个验证集,从训练集中抽取10%的数据。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)
X_train, X_valid, y_train, y_valid = train_test_split(X_train, y_train, train_size=0.9)
print(X_train.shape)
print(X_test.shape)
print(X_valid.shape)
这不会产生70%-20%-10%的分割,因为我们要从已经分割好的X_train ,所以我们实际上最终会产生72%-20%-8%的分割。
(108, 4)
(30, 4)
(12, 4)
为了解决这个问题,你可以手动设置一个不同的数字,期待这个,或者你可以预先定义你的比例,并计算一个更新的分割,以参考原始尺寸,而不是已经截断的尺寸。
为了将数据按比例分割成训练、测试和验证集--我们需要将第二个函数调用的test_size 参数设置为。
让我们加载糖尿病数据集,因为它有更多的实例(由于四舍五入,小数据集有时会产生略微不同的分割,即使比例相同)。
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
X, y = load_diabetes(return_X_y=True)
print(X.shape)
(442, 10)
假设我们的目标是80%/10%/10%的分割--我们希望分别有352,45 和45 的实例。让我们定义这些比例,用train_test_split() 函数将数据集分成训练、测试和验证集。
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
train_ratio = 0.80
test_ratio = 0.10
validation_ratio = 0.10
X, y = load_diabetes(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_ratio)
X_train, X_valid, y_train, y_valid = train_test_split(X_train, y_train, test_size=validation_ratio/(train_ratio+test_ratio))
print(X_train.shape)
print(X_test.shape)
print(X_valid.shape)
这样的结果是
(352, 10)
(45, 10)
(45, 10)
真棒!我们的数据集已经成功地分成了三组,现在我们可以把这些数据集输入到一个模型中,并在训练中进行验证,以调整超参数。
分层拆分
有时,数据集中每个类别的样本数量是不同的。比如,一个类别有100个样本,第二个类别有50个,第三个类别有30个,等等。在你训练分类模型时,如果不考虑这个问题,就会产生一个问题(不过,回归模型不受这个影响)。
最好的办法是以某种方式分割这个集合,这样就能保留各个类别的比例。这就是分层分割。
幸运的是,方法train_test_split 有一个参数叫stratify ,它需要一个数组,该数组定义了分层样本的数量,当分裂时,要保持比例。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y)
在很多情况下,你可以简单地使用你的数据集中的y NumPy数组来获得一个好的stratify 拆分数组。这可以确保你的模型可以对抗类的实例之间的不平衡,变得不那么偏向某些。
总结
在本指南中,我们熟悉了Scikit-Learn库的一些内容和它的datasets 模块。你已经了解了什么是训练集、测试集和验证集,它们的应用以及验证模型的好处。
我们看了一下如何采用train_test_split() 方法将你的数据分成训练集和测试集,以及如何分离验证集,动态地保持这些集的比例。