从0开始实现一个Adaboost分类器(完整代码)

简介: 日前,通俗易懂的推导了三种集成学习的原理及主要公式,今天本文基于Python从0开始手动实现一个Adaboost分类器,文中提供完整代码。

640.jpg


01 Adaboost


基本原理回顾Adaboost作为一种提升集成算法,核心思想是不断训练弱学习器,来针对性的提升前一轮中预测错误样本的权重,最终通过加权所有弱学习器的训练结果得到最终分类标签。Adaboost是一种加权提升的集成算法,关键在于两个权重系数:

  • 弱学习器权重,影响每个弱学习器的结果对最终集成学习结果的影响程度,与该学习器的错误率有关
  • 样本权重,这也是Adaboost算法的精髓所在,即每轮训练弱学习器时不断优化调整样本间的权重,保证前一轮中学习错误的样本在下一轮训练中受到重点照顾


弱学习器的权重为:

微信截图_20220527165354.png

为学习器错误率


样本权重更新迭代公式为:


微信截图_20220527165406.png


具体含义及推导过程详见:三种集成学习算法原理及核心公式推导


值得指出,在sklearn库内置的Adaboost算法中,当解决分类问题时弱学习器选择最大深度为1的决策树(俗称决策树桩),解决回归问题时则选择最大深度为3的决策树(CART)。


02 决策树桩


本文以分类问题为例实现Adaboost算法,所以首先探索实现一个最大深度只有一层的决策树桩。


简单起见,假设样本为连续数值型特征,要实现一个最大深度只有一层决策树桩,那么实际上无论有多少个特征,也仅会用到其中一个特征作为分类。则问题等价于确定以下三个参数:

  • 确定选择哪一列特征作为分类依据
  • 选择的特征列中,以什么数值作为二分类的阈值
  • 特征与阈值的判别符号问题,即大于阈值还是小于阈值判断为正类


由于是分类问题,那么选择最优参数的依据不妨可以选择为Accuracy。当然,由于该决策树桩需要支持样本权重参数,所以这里的Accuracy严谨的说是指所有分类正确的样本权重之和占所有样本权重之和的比例,当执行样本权重归一化时所有样本权重之和为1。


基于此,一个简单的决策树桩实现思路就比较清晰了,实现3重循环依次遍历寻找最有参数组合即可。另外,沿袭sklearn标准库中的做法,这里仅实现fit()、predict()和score()三个核心接口。


详细代码如下,配合注解应该比较简单易懂:


class DecisionTreeClassifierWithWeight:
    def __init__(self):
        self.best_err = 1  # 最小的加权错误率
        self.best_fea_id = 0  # 最优特征id
        self.best_thres = 0  # 选定特征的最优阈值
        self.best_op = 1  # 阈值符号,其中 1: >, 0: <
    def fit(self, X, y, sample_weight=None):
        if sample_weight is None:
            sample_weight = np.ones(len(X)) / len(X)
        n = X.shape[1]
        for i in range(n):
            feature = X[:, i]  # 选定特征列
            fea_unique = np.sort(np.unique(feature))  # 将所有特征值从小到大排序
            for j in range(len(fea_unique)-1):
                thres = (fea_unique[j] + fea_unique[j+1]) / 2  # 逐一设定可能阈值
                for op in (0, 1):
                    y_ = 2*(feature >= thres)-1 if op==1 else 2*(feature < thres)-1  # 判断何种符号为最优
                    err = np.sum((y_ != y)*sample_weight)
                    if err < self.best_err:  # 当前参数组合可以获得更低错误率,更新最优参数
                        self.best_err = err
                        self.best_op = op
                        self.best_fea_id = i
                        self.best_thres = thres
        return self
    def predict(self, X):
        feature = X[:, self.best_fea_id]
        return 2*(feature >= self.best_thres)-1 if self.best_op==1 else 2*(feature < self.best_thres)-1
    def score(self, X, y, sample_weight=None):
        y_pre = self.predict(X)
        if sample_weight is not None:
            return np.sum((y_pre == y)*sample_weight)
        return np.mean(y_pre == y)


这里以sklearn库中自带的乳腺癌二分类数据集为例,以上述实现的决策树桩进行训练和评分,得到最终得分0.867,这对于一个仅有单层决策树的分类器来说效果还是比较好的。


from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
y = 2*y-1  # 将0/1取值映射为-1/1取值
X_train, X_test, y_train, y_test = train_test_split(X, y)
DecisionTreeClassifierWithWeight().fit(X_train, y_train).score(X_test, y_test)
# 0.8671328671328671


注:按照Adaboost中的算法约定,二分类模型中标签分别用-1和1代表负类和正类。


03 Adaboost集成分类器


在实现决策树桩作为弱分类器的基础上,实现Adaboost算法就仅需按照算法流程逐层训练即可。简单起见,这里仅设置超参数n_estimators用于选择弱分类器的个数。为区分于sklearn中的Adaboost标准内置库,本文将自定义实现的Adaboost分类算法命名为AdaBoostClassifier_,并设置相同的默认弱学习器数量超参数n_estimators=50,其余不做限制。


实质上,在逐渐调整样本权重的基础上,仅需逐层训练一个最优的决策树桩作为每轮的弱学习器,并保存在一个弱学习器列表中,同步记录每个弱学习器的权重系数。最后,在实现predict接口时,用每个弱学习器逐一完成训练,而后按其权重系数加权即可得到最终结果。完整代码如下:


class AdaBoostClassifier_:
    def __init__(self, n_estimators=50):
        self.n_estimators = n_estimators
        self.estimators = []
        self.alphas = []
    def fit(self, X, y):
        sample_weight = np.ones(len(X)) / len(X)  # 初始化样本权重为 1/N
        for _ in range(self.n_estimators):
            dtc = DecisionTreeClassifierWithWeight().fit(X, y, sample_weight)  # 训练弱学习器
            alpha = 1/2 * np.log((1-dtc.best_err)/dtc.best_err)  # 权重系数
            y_pred = dtc.predict(X)
            sample_weight *= np.exp(-alpha*y_pred*y)  # 更新迭代样本权重
            sample_weight /= np.sum(sample_weight)  # 样本权重归一化
            self.estimators.append(dtc)
            self.alphas.append(alpha)
        return self
    def predict(self, X):
        y_pred = np.empty((len(X), self.n_estimators))  # 预测结果二维数组,其中每一列代表一个弱学习器的预测结果
        for i in range(self.n_estimators):
            y_pred[:, i] = self.estimators[i].predict(X)
        y_pred = y_pred * np.array(self.alphas)  # 将预测结果与训练权重乘积作为集成预测结果
        return 2*(np.sum(y_pred, axis=1)>0)-1  # 以0为阈值,判断并映射为-1和1
    def score(self, X, y):
        y_pred = self.predict(X)
        return np.mean(y_pred==y)


最后,继续以乳腺癌二分类数据集为例,对比测试自定义实现的AdaBoostClassifier_算法与sklearn标准库中的AdaBoostClassifer算法性能,得到如下结果:


from sklearn.ensemble import AdaBoostClassifier
AdaBoostClassifier_().fit(X_train, y_train).score(X_test, y_test)
# 0.986013986013986
AdaBoostClassifier().fit(X_train, y_train).score(X_test, y_test)
# 0.965034965034965


除了训练效率略低,自定义实现Adaboost算法效果简直好的不得了。


本文按部就班的实现了一个Adaboost分类算法的baseline,实现了较好的分类效果,但仍有很多需要优化的点,例如对回归算法的支持、更多集成学习参数的设置以及特殊训练情况下的处理等。To be continued……


640.png


目录
相关文章
|
6月前
|
机器学习/深度学习 存储
集成学习方法——随机森林
之前我们介绍过决策树,随机森林(Random Forest)是将多个决策树(Decision Tree)组合在一起形成一个强大的分类器或回归器,是一种集成学习(Ensemble Learning)方法。 随机森林的主要思想是通过随机选择样本和特征来构建多个决策树,并通过集成这些决策树的预测结果来达到更准确的分类或回归结果。具体步骤如下: 随机选择部分训练样本集; 随机选择部分特征子集; 构建决策树,对每个节点进行特征选择和分裂; 再进行重复,构建多个决策树; 对每个决策树,根据投票或平均值等方法,获得最后的分类或回归结果。
WK
|
2月前
|
机器学习/深度学习 算法 数据挖掘
什么是逻辑回归分类器
逻辑回归分类器是一种广泛应用于二分类问题的统计方法,它基于线性组合并通过Sigmoid函数将输出映射为概率值进行分类。核心原理包括:线性组合假设函数、Sigmoid函数转换及基于概率阈值的预测。该模型计算高效、解释性强且鲁棒性好,适用于信用评估、医疗诊断、舆情分析和电商推荐等多种场景。利用现有机器学习库如scikit-learn可简化其实现过程。
WK
30 1
|
5月前
|
机器学习/深度学习 算法 前端开发
决策树与随机森林算法在分类问题中的应用
本文探讨了决策树和随机森林两种监督学习算法,它们在分类任务中表现出强大的解释性和预测能力。决策树通过特征测试进行分类,构建涉及特征选择、树生成和剪枝。随机森林是集成学习方法,通过构建多棵决策树并汇总预测结果,防止过拟合。文中提供了Python代码示例,展示如何使用sklearn构建和应用这些模型,并讨论了参数调优和模型评估方法,如交叉验证和混淆矩阵。最后,强调了在实际问题中灵活选择和调整模型参数的重要性。
146 4
|
5月前
|
机器学习/深度学习 算法 Python
线性回归训练和预测代码详解
线性回归作为一种基础的回归分析方法,其核心思想和实现相对简单。本文通过详细的代码示例,介绍了线性回归模型的训练过程和预测函数的实现。希望能够帮助读者更好地理解和掌握这一基础算法。在实际应用中,线性回归可以作为一种初步的分析工具,为更复杂的模型提供参考和基础。
73 2
|
6月前
|
数据可视化 Python
Python进行多输出(多因变量)回归:集成学习梯度提升决策树GRADIENT BOOSTING,GBR回归训练和预测可视化
Python进行多输出(多因变量)回归:集成学习梯度提升决策树GRADIENT BOOSTING,GBR回归训练和预测可视化
Python进行多输出(多因变量)回归:集成学习梯度提升决策树GRADIENT BOOSTING,GBR回归训练和预测可视化
|
6月前
|
机器学习/深度学习 算法 Python
使用Python实现集成学习算法:Bagging与Boosting
使用Python实现集成学习算法:Bagging与Boosting
76 0
|
机器学习/深度学习 算法 前端开发
集成学习之随机森林、Adaboost、Gradient Boosting、XGBoost原理及使用
集成学习之随机森林、Adaboost、Gradient Boosting、XGBoost原理及使用
497 0
集成学习之随机森林、Adaboost、Gradient Boosting、XGBoost原理及使用
|
机器学习/深度学习 算法 前端开发
集成学习方法之随机森林
集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器模型,各自独立地学习和作出预测。这些预测最后结合成组合预测,因此优于任何一个单分类的做出预测。
135 0
集成学习方法之随机森林
|
机器学习/深度学习 算法
集成学习-Stacking算法
tacking是通过一个元分类器或者元回归器来整合多个分类模型或回归模型的集成学习技术。基础模型利用整个训练集做训练,元模型将基础模型的特征作为特征进行训练。
579 0
集成学习-Stacking算法
|
机器学习/深度学习 黑灰产治理 Python
5行代码提升GBDT,提升巨大!
如果你打过kaggle应该一定都知道,大家心照不宣的表格数据竞赛的第一tricks:
下一篇
无影云桌面