7. Adaboost原理以及代码实现 您所在的位置:网站首页 adaboost的原理 7. Adaboost原理以及代码实现

7. Adaboost原理以及代码实现

2023-03-07 23:21| 来源: 网络整理| 查看: 265

完整的实验代码在我的github上👉QYHcrossover/ML-numpy: 机器学习算法numpy实现 (github.com) 欢迎star⭐

当你需要从一个弱分类器中得到强分类器的时候,Adaboost算法是一个很好的选择。Adaboost 是一种集成学习算法,主要用于二分类问题。它通过对多个分类器的集成来提高分类性能。Adaboost 会对数据集进行多次训练,并将每次训练得到的分类器加权组合,最终形成一个强分类器。

Adaboost 原理

Adaboost 的核心思想是将若干个弱分类器组合成一个强分类器。弱分类器是指分类准确率略高于随机猜测的分类器,例如决策树的深度较浅、逻辑回归的迭代次数较少等。 Adaboost 算法的关键在于为每个弱分类器分配一个权重,用于计算最终分类器的输出。

Adaboost 算法的具体流程如下:

初始化训练数据集的权重向量 $w_1 = (w_{1,1},w_{1,2},...,w_{1,N})$,其中 $N$ 表示训练数据集的大小,$w_{1,i}$ 表示第 $i$ 个样本的权重,通常初始值为 $1/N$。 对于 $m=1,2,...,M$,进行以下步骤: 使用当前权重向量 $w_m$ 训练一个弱分类器 $h_m(x)$。 计算弱分类器 $h_m(x)$ 的误差率 $\epsilon_m$,其中 $\epsilon_m$ 定义为分类器 $h_m(x)$ 在当前权重向量下,被误分类的样本的权重之和,即 $\epsilon_m=\sum_{i=1}^{N}w_{m,i}I(y_i \neq h_m(x_i))$,其中 $I$ 为指示函数,当 $y_i \neq h_m(x_i)$ 时为 $1$,否则为 $0$。 计算弱分类器 $h_m(x)$ 的权重 $\alpha_m$,其中 $\alpha_m$ 定义为 $\alpha_m = \frac{1}{2}ln(\frac{1-\epsilon_m}{\epsilon_m})$。 更新权重向量 $w_{m+1}$,其中 $w_{m+1,i} = \frac{w_{m,i}}{Z_m}exp(-\alpha_m y_i h_m(x_i))$,其中 $Z_m$ 是规范化因子,使得 $w_{m+1}$ 成为一个概率分布,即 $Z_m=\sum_{i=1}^{N}w_{m,i}exp(-\alpha_m y_i h_m(x_i))$。 得到最终的分类器 $H(x)=\text{sign}(\sum_{m=1}^{M}\alpha_m h_m(x))$。

Adaboost算法的原理是基于这样一个事实:虽然弱分类器可能不能正确地分类训练数据,但是通过组合它们,我们可以得到一个更强的分类器。在每次迭代中,Adaboost将更多的关注放在上一次分类错误的样本上,以便下一次迭代时它们被正确分类的概率更高。通过这种方式,Adaboost算法不断地优化分类器,使其在分类训练数据时的准确性不断提高。

Adaboost代码实现

下面是使用Python实现Adaboost算法的代码。我们将使用乳腺癌数据集来演示Adaboost算法的应用。在此代码中,我们定义了一个MyAdaboost类,其中包含fit和predict方法,用于训练和预测Adaboost模型。在fit方法中,我们使用_best_split方法找到最佳划分点,并使用_G方法构造弱分类器的决策函数g(X)。在predict方法中,我们计算加权的弱分类器的预测结果,并返回最终预测标签。最后,我们使用score方法计算测试数据集上的分类准确度。

# 构建Adaboost类 class MyAdaboost: def __init__(self,n_estimators): self.n_estimators = n_estimators self.clfs = [lambda x:0 for i in range(self.n_estimators)] self.alphas = [0 for i in range(self.n_estimators)] self.weights = None # 构造弱分类器的决策函数g(X) def _G(self,fi,fv,direct): assert direct in ["positive","nagetive"] def _g(X): if direct == "positive": predict = (X[:,fi] value assign 0 else -1 predict[predict == 0] = 1 return predict return _g #选择最佳的划分点,即求出fi和fv def _best_split(self,X,y,w): best_err = 1e10 best_fi = None best_fv = None best_direct = None for fi in range(X.shape[1]): series = X[:,fi] for fv in np.sort(series): predict = np.zeros_like(series,dtype=np.int32) # direct = postive predict[series fv] = 1 err = np.sum((predict != y)* 1 * w) # print("err = {} ,fi={},fv={},direct={}".format(err,fi,fv,"postive")) if err < best_err: best_err = err best_fi = fi best_fv = fv best_direct = "positive" # direct = nagetive predict = predict * -1 err = np.sum((predict != y) * 1 * w) if err < best_err: best_err = err best_fi = fi best_fv = fv best_direct = "nagetive" # print("err = {} ,fi={},fv={},direct={}".format(err,fi,fv,"nagetive")) return best_err,best_fi,best_fv,best_direct def fit(self,X_train,y_train): self.weights = np.ones_like(y_train) / len(y_train) for i in tqdm(range(self.n_estimators)): err,fi,fv,direct = self._best_split(X_train,y_train,self.weights) # print(i,err,fi,fv,direct) #计算G(x)的系数alpha alpha = 0.5 * np.log((1-err)/err) if err !=0 else 1 # print("alpha:",alpha) self.alphas[i] = alpha #求出G g = self._G(fi,fv,direct) self.clfs[i] = g if err == 0: break #更新weights self.weights = self.weights * np.exp(-1 * alpha * y_train * g(X_train)) self.weights = self.weights / np.sum(self.weights) # print("weights :",self.weights)

首先初始化模型参数,也就是__init__函数的主要含义

n_estimators表示要构建的基分类器数量; clfs是一个列表,用于存储每个基分类器的决策函数,初始值为0; alphas是一个列表,用于存储每个基分类器的权重,初始值为0; weights是一个数组,用于存储每个样本的权重,初始值为1/len(y_train)。

其次通过fit函数训练n个基分类器,主要流程是:

通过_best_split函数选择最佳的划分点,即求出fi和fv; 计算G(x)的系数alpha,更新alphas列表; 求出G,更新clfs列表; 更新weights数组; 如果err为0,则停止训练。

在fit函数中best_split函数是该算法的核心之一。best_split函数用于选择最佳的划分点,即求出fi和fv,其中fi表示选择哪个特征,fv表示该特征的划分值。

具体实现过程如下:

对于每个特征fi,在该特征上从小到大排序,枚举每个排好序的取值fv。 对于每个fv,先考虑将小于等于fv的样本划分到负类(-1),大于fv的样本划分到正类(+1)的情况(记为"positive")。 计算划分错误率,即被误分类的样本的权重之和。如果当前的错误率小于已有最小错误率,则更新最小错误率、最佳划分特征fi、最佳划分值fv、划分方向("positive")。 接下来,再考虑将小于等于fv的样本划分到正类(+1),大于fv的样本划分到负类(-1)的情况(记为"nagetive")。 计算划分错误率,如果当前的错误率小于已有最小错误率,则更新最小错误率、最佳划分特征fi、最佳划分值fv、划分方向("nagetive")。 返回最佳划分点。

在构建完fit训练模型的主要逻辑后,我们再来简单看一下怎么测试和评估模型,主要用到了predict函数和score函数,

predict函数:predict函数的作用是对输入的测试数据进行分类预测。具体实现是对每个弱分类器预测结果进行加权和,最终根据加权和的符号来判断属于哪一类。 score函数:score函数的作用是对模型的性能进行评估。具体实现是在预测阶段,将预测结果与真实标签进行比较,计算准确率。 def predict(self,X_test): y_p = np.array([self.alphas[i] * self.clfs[i](X_test) for i in range(self.n_estimators)]) y_p = np.sum(y_p,axis=0) y_predict = np.zeros_like(y_p,dtype=np.int32) y_predict[y_p>=0] = 1 y_predict[y_p


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有