使用重采样评估Python中机器学习算法的性能
你需要知道你的算法在看不见的数据上表现如何。
评估算法性能的最好方法是对已经知道答案的新数据进行预测。第二个最好的方法是使用来自统计学的聪明技术,称为重采样方法,使您可以准确估计算法在新数据上的表现。
在这篇文章中,您将了解如何使用Python和scikit-learn中的重采样方法来评估机器学习算法的准确性。
让我们开始吧。
- 2017年1月 更新:已更新,以反映0.18版中scikit-learn API的更改。
- 更新Oct / 2017 :用Python 3更新打印语句。
使用 Douglas Waldron的 Resampling Photo (保留某些权利)评估Python中机器学习算法的性能。
关于方法
在本文中,使用Python中的小代码方法来展示重采样方法。
每个方法都是独立设计的,因此您可以将其复制并粘贴到您的项目中并立即使用。
在 糖尿病的数据集的皮马印第安人发生 在每个配方中使用。这是一个二元分类问题,其中所有的输入变量都是数字的。在每个配方中,直接从 UCI Machine Learning存储库 下载。您可以根据需要将其替换为您自己的数据集。
评估你的机器学习算法
为什么不能在数据集上训练机器学习算法,并使用来自同一数据集的预测来评估机器学习算法?
简单的答案是过度拟合。
设想一个算法,记住它显示的每一个观察。如果您在用于训练算法的相同数据集上评估机器学习算法,那么类似这样的算法将在训练数据集上具有完美分数。但是它对新数据的预测是可怕的。
我们必须对不用于训练算法的数据评估我们的机器学习算法。
评估是一个估计,我们可以用来谈论我们认为算法实际上可能在实践中做得如何。这不是表演的保证。
一旦我们估计了算法的性能,我们就可以在整个训练数据集上重新训练最终的算法,并准备好用于操作。
接下来,我们将看看四种不同的技术,我们可以使用它们来分割我们的训练数据集,并为我们的机器学习算法创建有用的性能估计:
- 训练和测试集。
- K-fold交叉验证。
- 留下一个交叉验证。
- 重复的随机测试列车拆分。
我们将从最简单的方法开始,称为训练和测试集。
1.分割成训练和测试集
我们可以使用最简单的方法来评估机器学习算法的性能,即使用不同的训练和测试数据集。
我们可以把我们的原始数据集,分成两部分。对第一部分的算法进行训练,对第二部分进行预测,并对预期结果进行评估。
拆分的大小取决于数据集的大小和细节,尽管通常使用67%的数据用于训练,其余的33%用于测试。
这种算法评估技术是非常快的。对于大量数据集(数百万条记录)来说,如果有强有力的证据表明数据分裂是潜在问题的代表,那么这是理想的选择。由于速度的原因,当你正在调查的算法训练缓慢时,使用这种方法是有用的。
这种技术的缺点是它可能具有很高的方差。这意味着训练和测试数据集中的差异会导致准确性估计的有意义的差异。
在下面的例子中,我们将数据Pima印第安人数据集分成67%/ 33%的比例进行训练和测试,并评估Logistic回归模型的准确性。
# Evaluate using a train and a test set
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
test_size = 0.33
seed = 7
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, Y, test_size=test_size, random_state=seed)
model = LogisticRegression()
model.fit(X_train, Y_train)
result = model.score(X_test, Y_test)
print("Accuracy: %.3f%%" % (result*100.0))
我们可以看到模型的估计精确度大约是75%。请注意,除了指定分割的大小外,我们还指定了随机种子。由于数据的分割是随机的,我们要确保结果是可重复的。通过指定随机种子,我们确保每次运行代码时都会得到相同的随机数。
如果我们想要将这个结果与另一个机器学习算法的估计精度或具有不同配置的相同算法进行比较,这一点很重要。为了确保苹果的比较,我们必须确保他们在相同的数据上进行了培训和测试。
Accuracy: 75.591%
2. K-fold交叉验证
交叉验证是一种方法,您可以使用这种方法来估计具有较少方差的机器学习算法的性能,而不是单个列车测试集拆分。
它通过将数据集分成k个部分(例如k = 5或k = 10)来工作。数据的每个分割被称为折叠。该算法在k-1折叠上进行训练,其中一个保持在后面的折叠上进行测试。这是重复的,这样数据集的每一个折叠都有机会成为阻止测试集。
运行交叉验证后,您将得到k个不同的表现分数,您可以使用平均值和标准差进行总结。
结果是给出测试数据的新数据的算法性能的更可靠的估计。这是更准确的,因为算法是在不同的数据上进行多次训练和评估。
k的选择必须允许每个测试分区的大小足够大以成为该问题的合理样本,同时允许对算法的训练测试评估的足够重复,以提供关于不可见数据的算法性能的公平估计。对于数千或数万个记录中的适度大小的数据集,3,5和10的k值是常见的。
在下面的例子中,我们使用10倍交叉验证。
# Evaluate using Cross Validation
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
num_instances = len(X)
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LogisticRegression()
results = model_selection.cross_val_score(model, X, Y, cv=kfold)
print("Accuracy: %.3f%% (%.3f%%)" % (results.mean()*100.0, results.std()*100.0))
Accuracy: 76.951% (4.841%)
3.保留一个交叉验证
您可以配置交叉验证,以便折叠的大小为1(k设置为数据集中观察值的数量)。交叉验证的这种变化称为“留一交”验证。
其结果是大量的性能指标可以总结出来,以便对未经验证的数据更准确地估计模型的准确性。缺点是它可能比k-fold交叉验证在计算上更昂贵。
在下面的例子中,我们使用了leave-one-out交叉验证。
# Evaluate using Leave One Out Cross Validation
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
num_folds = 10
num_instances = len(X)
loocv = model_selection.LeaveOneOut()
model = LogisticRegression()
results = model_selection.cross_val_score(model, X, Y, cv=loocv)
print("Accuracy: %.3f%% (%.3f%%)" % (results.mean()*100.0, results.std()*100.0))
您可以在标准偏差中看到,得分比上述k倍交叉验证结果有更多的方差。
Accuracy: 76.823% (42.196%)
4.重复的随机测试 - 列车拆分
k折叠交叉验证的另一个变化是像上面描述的训练/测试分割那样创建数据的随机分割,但重复多次分割和评估算法的过程,如交叉验证。
这具有使用训练/测试分割的速度以及k倍交叉验证的估计性能方差的减少。您也可以根据需要多次重复该过程。不利的一面是,重复可能包括列车中的大部分相同的数据,或者从运行到运行的测试分离,将冗余引入到评估中。
下面的例子将数据拆分成67%/ 33%的列车/测试拆分,并重复该过程10次。
# Evaluate using Shuffle Split Cross Validation
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
num_samples = 10
test_size = 0.33