机器学习算法通常应用例如 kFold等的穿插验证技术来进步模型的准确度。在穿插验证过程中,预测是通过拆分进去的不用于模型训练的测试集进行的。这些预测被称为折外预测(out-of-fold predictions)。折外预测在机器学习中施展着重要作用,能够进步模型的泛化性能。

在本文中,将介绍机器学习中的折外预测,次要包含以下几个方面:

  • 折外预测是对不用于训练模型的数据进行的一种样本外预测。
  • 在对看不见的数据进行预测时,折外预测最罕用于预计模型的性能。
  • 折外预测可用于构建集成模型,称为重叠泛化或重叠集成。

什么是折外预测?

应用重采样技术例如 k-fold来评估机器学习算法在数据集上的性能是一种很常见的办法。k-fold 过程包含将训练数据集分成 k 组,而后在应用 k 组样本中的每一个作为测试集,而其余样本用作训练集。

这意味着训练和评估了 k 个不同的模型。这个过程能够总结如下:

1、随机打乱数据集。

2、将数据集分成 k 组。

3、对于每个独特的组:将该组作为一个保留数据用做测试,将残余的组作为训练数据集,在训练集上拟合模型并在测试集上进行评估,反复k次使得每一组保留数据都进行了测试。

4、最初预测时应用训练出的K个模型进行整合预测。

数据样本中的每个数据都被调配到一个独自的组中,并在整个过程中放弃在该组中。这意味着每个样本都有机会在 作为测试集保留至多1次,并作为训练集最多 k-1 次。折外预测是在重采样过程中对每组得保留数据(测试集)所做的那些预测。如果正确执行,训练数据集中的每个数据都会有一个预测。

折外预测的概念与样本外预测(Out-of-Sample )的概念间接相干,因为这两种状况下的预测都是在模型训练期间未应用的样本上进行的,并且都能够预计模型在对新数据进行预测时的性能。折外预测也是一种样本外预测,只管它应用了k-fold穿插验证来评估模型。

上面咱们看看折外预测的两个次要性能

应用折外预测进行模型的评估

折外预测最常见的用处是评估模型的性能。应用诸如谬误或准确率之类的评分指标对未用于模型训练的数据进行预测和评估。相当用于应用了新数据(训练时不可见的数据)进行预测和对模型性能的预计,应用不可见的数据能够评估模型的泛化性能,也就是模型是否过拟合了。

对模型在每次训练期间所做的预测进行评分,而后计算这些分数的平均值是最罕用的模型评估办法。例如,如果一个分类模型,能够在每组预测上计算分类准确度,而后将性能预计为对每组折外预测预计的均匀分数。

上面能够通过一个小的示例展现应用折外预测的模型评估。首先,应用 scikit-learn 的make_blobs() 函数创立一个蕴含 1,000 个样本、两个类和 100 个输出特色的二元分类问题。

上面的代码筹备了一个数据样本并打印了数据集的输出和输入元素的形态。

from sklearn.datasets import make_blobs# create the inputs and outputsX, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)# summarize the shape of the arraysprint(X.shape, y.shape)

运行该示例会打印输出数据的形态,显示 1,000 行数据和 100 列或输出特色以及相应的分类标签。

下一步应用 KFold 来对数据进行分组训练 KNeighborsClassifier 模型。

咱们将对 KFold 应用 k=10参数,这是正当的默认值,在每组数据上拟合一个模型,并在每组的保留数据上进行测试评估。

评分保留在每个模型评估的列表中,并打印这些分数的平均值和标准差。

# evaluate model by averaging performance across each foldfrom numpy import meanfrom numpy import stdfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import KFoldfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import accuracy_score# create the inputs and outputsX, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)# k-fold cross validationscores = list()kfold = KFold(n_splits=10, shuffle=True)# enumerate splitsfor train_ix, test_ix in kfold.split(X):# get datatrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]# fit modelmodel = KNeighborsClassifier()model.fit(train_X, train_y)# evaluate modelyhat = model.predict(test_X)acc = accuracy_score(test_y, yhat)# store scorescores.append(acc)print('> ', acc)# summarize model performancemean_s, std_s = mean(scores), std(scores)print('Mean: %.3f, Standard Deviation: %.3f' % (mean_s, std_s))

留神:后果可能会因算法或评估过程的随机性或数值精度的差别而有所不同。在运行完结时,打印的分数的平均值和标准差如下:

>  0.95>  0.92>  0.95>  0.95>  0.91>  0.97>  0.96>  0.96>  0.98>  0.91Mean: 0.946, Standard Deviation: 0.023

除对每个模型的预测评估进行均匀以外,还能够将每个模型的预测聚合成一个列表,这个列表中蕴含了每组训练时作为测试集的保留数据的汇总。在所有的模型训练实现后将该列表作为一个整体以取得单个的准确率分数。

应用这种办法是思考到每个数据在每个测试集中只呈现一次。也就是说,训练数据集中的每个样本在穿插验证过程中都有一个预测。所以能够收集所有预测并将它们与指标后果进行比拟,并在整个训练完结后计算分数。这样的益处是更能突出模型的泛化性能。

残缺的代码如下

# evaluate model by calculating the score across all predictionsfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import KFoldfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import accuracy_score# create the inputs and outputsX, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)# k-fold cross validationdata_y, data_yhat = list(), list()kfold = KFold(n_splits=10, shuffle=True)# enumerate splitsfor train_ix, test_ix in kfold.split(X):# get datatrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]# fit modelmodel = KNeighborsClassifier()model.fit(train_X, train_y)# make predictionsyhat = model.predict(test_X)# storedata_y.extend(test_y)data_yhat.extend(yhat)# evaluate the modelacc = accuracy_score(data_y, data_yhat)print('Accuracy: %.3f' % (acc))

每个保留数据集的所有预期值和预测值在运行完结时打印出单个准确度得分。

Accuracy: 0.930

除了对模型评估以外,折外预测的最大作用就是能够进行模型的集成,进步泛化能力。

折外预测进行模型集成

集成学习是一种机器学习的办法,它在同一训练数据上训练多个模型,并将多个模型的预测进行集成以进步整体的性能。这也是在进行机器学习比赛时最常见办法。

首先,对每个模型都进行进行穿插验证并收集所有的折外预测。须要留神的是每个模型执行数据拆分必须是雷同的。这样就能够取得所有的折外预测。这样就取得了Base-Model:在训练数据集上应用 k 折穿插验证评估的模型,并保留所有非折叠预测。

下一步依据其余模型的预测训练一个高阶模型(也被称为Meta-Model)。这个模型的工作是学习如何最好地联合和纠正其余模型使得这些(其余)模型的折外预测可能取得更好的性能。

听起来很绕口,上面还是应用一个简略的二分类问题进行解释,首先训练一个决策树和一个 k 最近邻模型作为Base-Model。每个Base-Model通过 折外预测为训练数据集中的每个样本预测 0 或 1。这些预测与输出数据一起输出到高阶模型(Meta-Model)中。

  • Meta-Model输出:Base-Model的输出特色+Base-Model的预测。
  • Meta-Model输入:样本的指标(与Base-Models雷同)。

为什么要应用折外预测来训练Meta-Model?

在整个训练数据集上训练Base-Model,而后对训练数据集中的每个样本进行预测,并将预测用作Meta-Model的输出,这样其实所有的样本都用Meta-Model训练,预测必定比失常状况更好(非常容易产生过拟合),并且Meta-Model可能不会对纠正Base-Model预测产生任何的帮忙,甚至会使后果变差。

然而应用Base-Model的折外预测来训练Meta-Model,Meta-Model能够是应用Base-Model看不见的数据进行操作,能够取得Base-Model对新数据预测行为的有余并通过训练来纠正Base-Model的问题,这就像应用集成学习时的状况一样:应用的都是训练时不可见的新数据。

通过穿插验证每个Base-Model也都是在整个数据集上进行训练,这些最终的Base-Model和Meta-Model可用于对新数据进行预测。这个过程能够总结如下:

  • 对于每个Base-Model,应用穿插验证训练并保留折外预测。
  • 应用Base-Model中的折外预测进行Meta-Model的训练。

这一过程称为Stacked Generalization(重叠泛化)简称重叠。通常应用线性加权和作为Meta-Model,这个过程有时✌被称为blending。

代码实现

这里能够应用上一节中雷同数据具体介绍这个过程。首先将数据拆分为训练和验证数据集。训练数据集将用于拟合Base-Model和Meta-Model,验证数据集将在训练完结时用于评估Meta-Model和Base-Model。

X, X_val, y, y_val = train_test_split(X, y, test_size=0.33)

下一步应用 穿插验证来拟合每折的 DecisionTreeClassifier 和 KNeighborsClassifier 模型并保留折外预测。这些模型将输入概率而不是类别标签,因为须要为Meta-Model提供更有用的输出特色。。

# collect out of sample predictionsdata_x, data_y, knn_yhat, cart_yhat = list(), list(), list(), list()kfold = KFold(n_splits=10, shuffle=True)for train_ix, test_ix in kfold.split(X):# get datatrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]data_x.extend(test_X)data_y.extend(test_y)# fit and make predictions with cartmodel1 = DecisionTreeClassifier()model1.fit(train_X, train_y)yhat1 = model1.predict_proba(test_X)[:, 0]cart_yhat.extend(yhat1)# fit and make predictions with cartmodel2 = KNeighborsClassifier()model2.fit(train_X, train_y)yhat2 = model2.predict_proba(test_X)[:, 0]knn_yhat.extend(yhat2)

以上的代码为Meta-Model构建了数据集,该数据集由输出数据的 100 个输出特色和来自 kNN 和决策树模型的两个预测概率组成。

上面的 create_meta_dataset() 函数 将折外的数据和预测作为输出,并为Meta-Model构建输出数据集。

def create_meta_dataset(data_x, yhat1, yhat2):# convert to columnsyhat1 = array(yhat1).reshape((len(yhat1), 1))yhat2 = array(yhat2).reshape((len(yhat2), 1))# stack as separate columnsmeta_X = hstack((data_x, yhat1, yhat2))return meta_X

而后调用这个函数来为Meta-Model筹备数据。

meta_X = create_meta_dataset(data_x, knn_yhat, cart_yhat)

将每个Base-Model拟合到整个训练数据集上,并应用验证集进行预测。

# fit final submodelsmodel1 = DecisionTreeClassifier()model1.fit(X, y)model2 = KNeighborsClassifier()model2.fit(X, y)

而后在筹备好的数据集上Meta-Model,这里咱们应用 LogisticRegression 模型。

# construct meta classifiermeta_model = LogisticRegression(solver='liblinear')meta_model.fit(meta_X, data_y)

最初,应用Meta-Model对保留数据集进行预测。首先通过Base-Model,输入用于构建Meta-Model的数据集,而后应用Meta-Model进行预测。把所有这些操作封装到stack_prediction() 的函数中。

# make predictions with stacked modeldef stack_prediction(model1, model2, meta_model, X):# make predictionsyhat1 = model1.predict_proba(X)[:, 0]yhat2 = model2.predict_proba(X)[:, 0]# create input datasetmeta_X = create_meta_dataset(X, yhat1, yhat2)# predictreturn meta_model.predict(meta_X)

应用最后宰割的保留数据集进行Base-Model的验证

# evaluate sub models on hold out datasetacc1 = accuracy_score(y_val, model1.predict(X_val))acc2 = accuracy_score(y_val, model2.predict(X_val))print('Model1 Accuracy: %.3f, Model2 Accuracy: %.3f' % (acc1, acc2))# evaluate meta model on hold out datasetyhat = stack_prediction(model1, model2, meta_model, X_val)acc = accuracy_score(y_val, yhat)print('Meta Model Accuracy: %.3f' % (acc))

将下面所有的代码合并,残缺的代码如下:

# example of a stacked model for binary classificationfrom numpy import hstackfrom numpy import arrayfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import KFoldfrom sklearn.model_selection import train_test_splitfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_score# create a meta datasetdef create_meta_dataset(data_x, yhat1, yhat2):# convert to columnsyhat1 = array(yhat1).reshape((len(yhat1), 1))yhat2 = array(yhat2).reshape((len(yhat2), 1))# stack as separate columnsmeta_X = hstack((data_x, yhat1, yhat2))return meta_X# make predictions with stacked modeldef stack_prediction(model1, model2, meta_model, X):# make predictionsyhat1 = model1.predict_proba(X)[:, 0]yhat2 = model2.predict_proba(X)[:, 0]# create input datasetmeta_X = create_meta_dataset(X, yhat1, yhat2)# predictreturn meta_model.predict(meta_X)# create the inputs and outputsX, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)# splitX, X_val, y, y_val = train_test_split(X, y, test_size=0.33)# collect out of sample predictionsdata_x, data_y, knn_yhat, cart_yhat = list(), list(), list(), list()kfold = KFold(n_splits=10, shuffle=True)for train_ix, test_ix in kfold.split(X):# get datatrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]data_x.extend(test_X)data_y.extend(test_y)# fit and make predictions with cartmodel1 = DecisionTreeClassifier()model1.fit(train_X, train_y)yhat1 = model1.predict_proba(test_X)[:, 0]cart_yhat.extend(yhat1)# fit and make predictions with cartmodel2 = KNeighborsClassifier()model2.fit(train_X, train_y)yhat2 = model2.predict_proba(test_X)[:, 0]knn_yhat.extend(yhat2)# construct meta datasetmeta_X = create_meta_dataset(data_x, knn_yhat, cart_yhat)# fit final submodelsmodel1 = DecisionTreeClassifier()model1.fit(X, y)model2 = KNeighborsClassifier()model2.fit(X, y)# construct meta classifiermeta_model = LogisticRegression(solver='liblinear')meta_model.fit(meta_X, data_y)# evaluate sub models on hold out datasetacc1 = accuracy_score(y_val, model1.predict(X_val))acc2 = accuracy_score(y_val, model2.predict(X_val))print('Model1 Accuracy: %.3f, Model2 Accuracy: %.3f' % (acc1, acc2))# evaluate meta model on hold out datasetyhat = stack_prediction(model1, model2, meta_model, X_val)acc = accuracy_score(y_val, yhat)print('Meta Model Accuracy: %.3f' % (acc))

下面的残缺代码首先打印了决策树和 kNN 模型的准确性,而后打印最终Meta-Model在保留数据集上的性能,能够看到元模型的体现优于两个Base-Model。

Model1 Accuracy: 0.670, Model2 Accuracy: 0.930Meta-Model Accuracy: 0.955

能够看到尽管模型1的准确率只有67%,然而通过折外预测的集成办法也对最终的后果产生的良好的影响。

总结

  • 折外预测是对不用于训练模型的数据进行的一种样本外预测。
  • 在对看不见的数据进行预测时,折外预测最罕用于预计模型的性能。
  • 折外预测还可用于构建集成模型,称为重叠泛化或重叠集成。

https://www.overfit.cn/post/1ebf8320e9934d02ad74bafd198d67b5

作者:Jason Brownlee PhD