有时,一个模型是不够的。在这篇集成模型指南中,我将向您介绍如何(以及何时)对机器学习模型使用集成技术。
每当我们试图做出重要决定时,我们都会尝试收集尽可能多的信息,并向专家寻求建议。我们可以收集的信息越多,我们(和我们周围的人)就越信任决策过程。
机器学习预测遵循类似的行为。模型处理给定的输入并产生结果。结果是根据模型在训练过程中看到的模式进行预测。
在许多情况下,一个模型是不够的,本文阐明了这一点。我们何时以及为何需要多个模型?我们如何训练这些模型?这些模型应该提供什么样的多样性?所以,让我们直接进入。
如果你想看一个如何构建集成模型的例子,你可以跳到最后!
Note
什么是集成模型?
集成模型是一种机器学习方法,用于在预测过程中结合多个其他模型。这些模型称为基础估计器。集成模型提供了一种解决方案,可以克服构建单个估计器的技术挑战。
构建单一估计器的技术挑战包括:
- 高方差:模型对为学习特征提供的输入非常敏感。
- 准确性低:一个模型(或一种算法)无法拟合整个训练数据,可能无法为您提供项目所需的细微差别。
- 具有噪声和偏差的特征:模型在进行预测时严重依赖于太少的特征。
集成算法
单一算法可能无法对给定的数据集做出完美的预测。机器学习算法有其局限性,生成高精度的模型具有挑战性。如果我们构建并组合多个模型,我们就有机会提高整体准确性。然后,我们通过将每个模型的输出与两个目标聚合来实现模型组合:
- 减少模型误差
- 保持模型的泛化
您可以使用不同的技术(有时称为元算法)来实现此类聚合。
图 1:使用多种算法使模型预测多样化
集成学习
当我们构建集成模型时,我们不仅要关注算法的方差。例如,我们可以构建多个 C45 模型,其中每个模型都在学习专门用于预测任何给定事物的特定模式。我们可以用来获得元模型的模型称为弱学习器。在这种集成学习架构中,输入被传递给每个弱学习器,同时还收集他们的预测。我们可以使用组合预测来构建最终的集成模型。
值得一提的是,弱学习者可以采用不同的方式将特征与变体决策边界进行映射。
图 2:使用同一算法的多个弱学习器的聚合预测
Note
集成建模技术的类型
- Bagging
- Boosting
- Stacking
- Blending
集成技术
Bagging
bagging 的想法是基于使训练数据可用于迭代学习过程。每个模型都使用训练数据集的略有不同的子集来学习前一个模型产生的误差。bagging 可减少 方差 并最大程度地减少 过拟合。这种技术的一个例子是 随机森林 算法。
Bootstrap Aggregation (Bagging)
此技术基于自举采样技术 (bootstrapping sampling technique)。bootstrapping 会创建多组原始训练数据并进行替换。替换允许在一组中复制样本实例。每个子集都具有相同的相等大小,可用于并行训练模型。
图 3:通过结合来自多个模型的预测来做出最终预测的 Bagging 技术
随机森林 (Random Forest)
此技术使用训练样本的子集以及特征的子集来构建多个分割树。构建了多个决策树以适应每个训练集。样本/特征的分布通常以随机模式实现。
Extra-Trees Ensemble
这是另一种集成技术,其中来自许多 决策树 的预测组合在一起。与随机森林类似,它结合了大量的决策树。但是,额外的树在随机选择分割时使用整个样本。
Boosting
Adaptive Boosting (AdaBoost)
这是一个算法集合,我们在 几个弱学习器 的顶部构建模型。正如我们前面提到的,这些学习器被称为弱学习器,因为它们通常很简单,预测能力有限。AdaBoost 的适应能力使该技术成为最早成功的二元分类器之一。
顺序决策树 (Sequential Decision Trees)
这些是这种适应性的核心,每棵树都根据先验的精度知识调整其权重。因此,我们以顺序(而不是并行)过程执行这种技术的训练。在这种技术中,对于给定的迭代次数或当错误率没有显着变化时,可以重复训练和测量估计误差的过程。
图 4:AdaBoost 的顺序学习产生更强的学习模型
梯度提升 (Gradient Boosting)
梯度提升算法是具有高预测性能的出色技术。 Xgboost、LightGBM 和 CatBoost 是可用于回归和分类问题的常用提升算法。在他们证明有能力 赢得一些 Kaggle 比赛 后,他们的受欢迎程度显着增加。
Stacking
堆叠类似于提升模型; 它们产生更稳健的预测因子。堆叠是一个学习如何从所有弱学习者的预测中创建这样一个更强大的模型的过程。
图 5:用于在集成架构中进行最终预测的堆叠技术
请注意,该算法正在从每个模型(作为特征)中学习预测。
Ensemble Learners Tutorial | Video: Udacity
Blending
blending 类似于 stacking 方法,不同之处在于最终模型正在学习验证和测试数据集以及预测。因此,所使用的特征被扩展为包括验证集。
分类问题
分类只是一个分类过程。如果我们有多个标签,我们需要决定:我们是否应该构建一个单一的多标签分类器?或者我们是否应该构建多个二元分类器?如果我们决定构建多个二元分类器,我们需要解释每个模型预测。例如,如果我们想要识别四个对象,每个模型都会告诉您输入数据是否是该类别的成员。因此,每个模型都提供了隶属的概率。同样,我们可以构建一个结合这些分类器的最终集成模型。
回归问题
在上一个函数中,我们使用所得概率确定了最佳拟合隶属度。在回归问题中,我们不是在处理“是”或“否”的问题。相反,我们需要找到最佳预测的数值,然后我们可以对收集的预测值进行平均。
聚合预测
当我们集成多个算法以调整预测过程以组合多个模型时,我们需要一种聚合方法。我们可以使用三种主要技术:
- 最大投票:此技术的最终预测是基于对分类问题的多数投票做出的。
- 平均:此技术通常用于对预测进行平均的回归问题。我们也可以使用概率,例如,通过对最终分类进行平均。
- 加权平均:有时,在生成最终预测时,我们需要为某些模型/算法赋予权重。
如何构建集成模型:示例
我们将使用以下示例来说明如何构建集成模型。我们将使用泰坦尼克号数据集,并尝试使用不同的技术预测泰坦尼克号的生存情况。图六和图七显示了数据集的样本和目标列对乘客年龄的分布。如果你想跟着做,你可以在我的 GitHub 上找到示例代码。
泰坦尼克号数据集是需要大量特征工程的分类问题之一。我们将尝试只关注模型构建以及如何将集成模型应用于此用例。
我们将使用不同的算法和技术; 因此,我们将创建一个模型对象来提高代码的可重用性。
# Model Class to be used for different ML algorithms
class ClassifierModel(object):
def __init__(self, clf, params=None):
self.clf = clf(**params)
def train(self, x_train, y_train):
self.clf.fit(x_train, y_train)
def fit(self,x,y):
return self.clf.fit(x,y)
def feature_importances(self,x,y):
return self.clf.fit(x,y).feature_importances_
def predict(self, x):
return self.clf.predict(x)
def trainModel(model, x_train, y_train, x_test, n_folds, seed):
cv = KFold(n_splits= n_folds, random_state=seed)
scores = cross_val_score(model.clf, x_train, y_train, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
Random Forest Classifier
# Random Forest parameters
rf_params = {
'n_estimators': 400,
'max_depth': 5,
'min_samples_leaf': 3,
'max_features' : 'sqrt',
}
rfc_model = ClassifierModel(clf=RandomForestClassifier, params=rf_params)
rfc_scores = trainModel(rfc_model,x_train, y_train, x_test, 5, 0)
Extra Trees Classifier
# Extra Trees Parameters
et_params = {
'n_jobs': -1,
'n_estimators':400,
'max_depth': 5,
'min_samples_leaf': 2,
}
etc_model = ClassifierModel(clf=ExtraTreesClassifier, params=et_params)
etc_scores = trainModel(etc_model,x_train, y_train, x_test, 5, 0)
AdaBoost Classifier
# AdaBoost parameters
ada_params = {
'n_estimators': 400,
'learning_rate' : 0.65
}
ada_model = ClassifierModel(clf=AdaBoostClassifier, params=ada_params)
ada_scores = trainModel(ada_model,x_train, y_train, x_test, 5, 0)
XGBoost Classifier
Gradient Boosting parameters
# Gradient Boosting parameters
gb_params = {
'n_estimators': 400,
'max_depth': 6,
}
gbc_model = ClassifierModel(clf=GradientBoostingClassifier, params=gb_params)
gbc_scores = trainModel(gbc_model,x_train, y_train, x_test, 5, 0)
让我们将所有模型交叉验证精度结合在五个折上。
现在,让我们构建一个堆叠模型,其中一个新的更强的模型从所有这些弱学习器中学习预测。我们用于训练先前模型的标签向量将保持不变。特征是从每个分类器收集的预测。
x_train = np.column_stack((etc_train_pred, rfc_train_pred, ada_train_pred, gbc_train_pred, svc_train_pred))
现在,让我们看看构建 XGBoost 模型仅学习生成的预测是否会表现得更好。但首先,我们将快速了解分类器预测之间的相关性。
图 9:分类器投票标签之间的 Pearson 相关性
现在,我们将构建一个模型来组合来自多个贡献分类器的预测。
def trainStackModel(x_train, y_train, x_test, n_folds, seed):
cv = KFold(n_splits=n_folds, random_state=seed)
gbm = xgb.XGBClassifier(
n_estimators=2000,
max_depth=4,
min_child_weight=2,
gamma=0.9,
subsample=0.8,
colsample_bytree=0.8,
objective='binary:logistic',
scale_pos_weight=1).fit(x_train, y_train)
scores = cross_val_score(gbm, x_train, y_train, scoring='accuracy', cv=cv)
return scores
之前创建的基础分类器表示 Level-0 模型,新的 XGBoost 模型表示 Level-1 模型。该组合说明了在样本数据的预测上训练的元模型。您可以在下面看到新堆叠模型的准确性与基础分类器之间的快速比较:
仔细考虑
- 噪声、偏差和方差:来自多个模型的决策组合有助于提高整体性能。因此,使用集成模型的关键原因之一是克服噪声、偏差和方差。如果集成模型没有提供集体经验来提高这种情况下的准确性,那么有必要仔细重新考虑是否有必要使用。
- 简单性和可 解释 性:机器学习模型,尤其是那些投入生产环境的模型,应该易于解释。当您使用集成模型时,您能够解释最终模型决策的机会会大大降低。
- 泛化:有许多说法认为集成模型具有更强的泛化能力,但其他报告的用例显示出更多的泛化错误。因此,如果没有仔细的训练过程,集成模型可能会快速产生高过拟合模型。
- 推理时间:尽管我们可能不愿意接受更长的模型训练时间,但推理时间仍然很关键。将集成模型部署到生产环境中时,传递多个模型所需的时间会增加,并且可能会减慢预测任务的吞吐量。
集成模型是机器学习的一种极好的方法,因为它们为分类和回归问题提供了各种技术。现在您了解了集成模型的类型,我们如何构建简单的集成模型,以及它们如何提高模型的准确性。