编者按:Towards Data Science博主Sagar Howal简明扼要地介绍了集成学习的常用技术。
使用多种不同的模型通常比使用单一模型更可靠。在单个数据集上使用多个协同工作的模型称为集成(Ensemble)。这一方法称为集成学习(Ensemble Learning)。
你可以使用多种不同的算法训练你的模型,然后加以集成以预测最终输出。比如,你可以使用随机森林分类器、SVM分类器、线性回归,等等。模型互相竞争,然后你可以使用sklearn.ensemble
的VotingClassifier
类来挑选最佳表现。
硬投票(hard voting)按照简单多数原则选择最终预测。而软投票(soft voting)仅在所有的分类器都可以为输出计算概率时才可以使用。软投票通过对单独算法计算出的概率取均值得到最佳结果。
代码:
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
log_clf = LogisticRegression()
rnd_clf = RandomForestClassifier()
svm_clf = SVC()
voting_clf = VotingClassifier(
Estimators = [('lr', log_clf), ('rf', rnd_clf), ('svc',svm_clf)],
voting = 'hard')
voting_clf.fit(X_train, y_train)
以上代码使用了SVM、线性回归、随机森林三种分类器,并进行硬投票。
一般而言,VotingClassifier
的精确度比单独分类器要高。确保使用了差异足够大的分类器,这样类似的错误不会累积。
除了在单一数据集上运行多个模型以外,你还可以在一个数据集的多个随机子集上运行单个模型。有放回的随机取样称为Bagging(bootstrap aggregaing,引导聚类)。如果这对你而言太不形象的话,你可以想像忽略数据集中的部分随机条目,然后基于剩下的条目建模。Pasting与此类似,只不过它不允许为同一预测反复取样训练实例。
代码:
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
bag_clf = BaggingClassifier(
DecisionTreeClassifier(random_state=42), n_estimators=500,
max_samples=100, bootstrap=True, n_jobs=-1, random_state=42)
bag_clf.fit(X_train, y_train)
y_pred = bag_clf.predict(X_test)
bootstrap=True
参数指定使用Bagging。改为bootstrap=False
则使用Pasting。
如果分类器可以计算预测概率,那么BaggingClassifier会自动进行软投票。可以计算预测概率的分类器带有predict_proba()
方法。
一般而言,Bagging的结果比Pasting要好很多。
在训练集上使用Bagging时,模型只包括63%的实例,这意味着分类器看不到37%的实例。这些实例可以用于验证,类似交叉验证。
只需在之前的代码样例的BaggingClassifier
类中加上oob_score = True
参数即可使用这一功能。
代码:
bag_clf = BaggingClassifier(
DecisionTreeClassifier(random_state=42), n_estimators=500,
max_samples=100, bootstrap=True, n_jobs=-1, random_state=42,
oob_score = True)
目前我们取样的仅仅是实例。对具有大量特征的数据集而言,有其他的技术。
随机补丁同时取样训练实例和特征。在BaggingClassifier()
中设定特定的参数即可使用:
bootstrap_features = True, max_samples = 0.6
# max_samples需小于1.0,否则会被舍弃
随机子空间保留所有样本,并取样特征:
Bootstrap = True, bootstrap_features = True, max_features = 0.6
# max_samples需小于1.0,否则会被舍弃
集成决策树可得随机森林。随机森林内部进行Bagging操作。随机森林创建若干决策树,有时创建数千决策树,并为指定数据集计算可能最佳的模型。在分叉节点时,随机森林并不考虑所有特征,而是在所有特征的子集中选择最佳特征。这是用更高的偏置交换更低的差异,从而得到更好的模型。
代码:
rom sklearn.ensemble import RandomForestClassifier
rnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1, random_state=42)
rnd_clf.fit(X_train, y_train)
y_pred_rf = rnd_clf.predict(X_test)
参数:
n_estimators
是森林中的决策树数量限制。
max_leaf_nodes
用于设置端节点的最大值,这样算法不会因为深深钻入单一特征而过拟合。
n_jobs
指定使用的计算机核心数目。-1
意味着使用所有的核心。
可以通过网格搜索变动参数的值以改善该模型。
尽管AdaBoost技术的数学机制挺吓人的,它的理念还是很简单的。首先你选取一个基本分类器,在给定数据集上做出预测。记录错误分类的实例。然后增加错误分类的权重。第二个分类器基于更新的权重在训练集上进行训练。
简单来说,运行一个分类器并做出预测。运行另一个分类器拟合之前错误分类的实例并做出预测。重复此过程直到拟合所有/大部分训练实例。
AdaBoost不使用决策树,而使用决策树桩(Decision Stump),决策树桩可以看成max_depth = 1
的决策树,即,由一个决策节点和两个叶节点组成的树。AdaBoost的n_estimators
参数设定决策树桩的数目。
代码
from sklearn.ensemble import AdaBoostClassifier
ada_clf = AdaBoostClassifier(
DecisionTreeClassifier(max_depth=1), n_estimators=200,
algorithm="SAMME.R", learning_rate=0.5, random_state=42)
ada_clf.fit(X_train, y_train)
Scikit-learn使用了Adaboost的多类版本,称为SAMME(多类指数损失函数逐步添加模型,Stagewise Additive Modelling using a Multiclass Exponential Loss Function)。如果预测器可以计算概率(具备predict_proba()
方法),Scikit Learn使用SAMME.R(R代表实数),该算法基于概率,更不容易过拟合。
如果发生了过拟合,尝试正则化你的基本估计量。
类似AdaBoost,梯度提升同样基于加入集成的后续预测模型。和AdaBoost不同,梯度提升并不更新训练实例的权重,梯度提升让新模型去拟合残差。
简单来说,用一个模型拟合给定的训练集。计算残差,这些残差将成为新的训练实例,并在其之上训练一个新模型。所有模型相加以做出预测。
代码
from sklearn.ensemble import GradientBoostingRegressor
gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0, random_state=42)
gbrt.fit(X, y)
学习率(learning_rate
)参数收缩每棵树的分布。learning_rate
和n_estimator
需要折衷。降低learning_rate
的值会增加集成中的树的数量。这称为收缩(Shrinkage)。注意,n_estimator
过大可能导致过拟合。需要仔细监测这一折衷。
XGBoost是最近出现的、最受推崇的强大梯度提升方法。XGBoost不在叶节点处做出强硬的“是”和“否”决策,而是给每个做出的决定分配一个正值或负值。所有树都是一个弱学习者,提供比随机猜测稍好的决策。但将它们收集起来加以平均后,XGBoost表现非常好。
代码
from xgboost import XGBoostClassifier
xgb_clf = XGBClassifier()
xgb_clf.fit(X, y)
XGBoost既可以配合树,也可以配合线性模型。推荐阅读XGBoost文档以获取更多参数调节选项。
XGBoost最近变得很流行,在大多数Kaggle竞赛优胜模型中得到使用。你的数据科学工具箱该有这么一个强大的工具。