机器学习之Boosting和AdaBoost

news2024/11/15 13:32:55

1 Boosting和AdaBoost介绍

1.1 集成学习

集成学习 (Ensemble Learning) 算法的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。

  • 集成学习通过建立几个模型来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成组合预测,因此优于任何一个单分类的做出预测。
  • 集成学习是一种思想,不是某一个算法

 1.1.1 集成学习分类

集成算法大致可以分为:BaggingBoostingStacking等类型。

  • bagging:并行,多个学习器互不相关 可以并行训练
  • boosting:串行,后一个学习器依赖于前一个学习器
  • stacking:多个学习器的输出作为后面一个学习器的输入

1.1.2 Boosting和Bagging

Boosting和Bagging都是流行的集成学习技术,用于通过多个基学习器的组合来提高机器学习模型的性能。虽然两种方法的目标都是减少过拟合并增加泛化能力,但它们具有不同的方法和特点。

(1)Boosting(提升)

提升是一种迭代的集成技术,在这种方法中,基学习器按顺序训练,每个后续模型都专注于纠正前面模型的错误。它给予训练集中被错误分类的实例更高的权重,迫使下一个模型专注于这些难以处理的情况。

  • 基学习器: 通常,提升算法使用弱学习器,这些模型的性能仅比随机猜测略好。例如,使用深度有限的决策树(通常称为“树桩”)或简单的线性模型。
  • 加权投票: 在预测时,根据每个基学习器的性能和在先前迭代中的重要性对其进行加权。在后续迭代中,被错误分类的实例得到更高的权重。

AdaBoost(自适应提升)和梯度提升机(GBM)是常见的提升算法。

(2)Bagging(装袋):

装袋是一种集成技术,它使用并行训练多个基学习器,每个学习器在随机选择的训练数据子集上独立训练,有放回地采样。最终的预测通过对所有基学习器的预测进行平均(回归问题)或投票(分类问题)得到。

  • 基学习器: 装袋通常对每个模型使用相同的基础学习算法,每个模型在不同的数据子集上独立训练。
  • 自助采样: 对于每个基学习器,使用有放回地随机抽样训练数据的子集。这意味着一些实例可能在子集中出现多次,而其他实例可能根本不出现。 

随机森林是一种常见的装袋算法,它使用决策树作为基学习器。

(3)两种技术的不同点

基学习器的多样性:

  • 提升:通常使用一系列弱学习器,每个模型纠正其前任的错误。这种顺序性为集成引入多样性。
  • 装袋:通过对数据的随机采样,每个模型独立训练,获得集成的多样性。

加权投票与简单平均/投票:

  • 提升:最终预测通过结合所有模型的预测,并根据其性能进行加权得到。更准确的模型在最终预测中具有更大的影响力。
  • 装袋:所有模型对最终预测的贡献相等,因为它们只是被平均(回归问题)或投票(分类问题)。

对过拟合的鲁棒性:

  • 提升:如果弱学习器过于复杂以至于记住训练数据,提升更容易过拟合。需要仔细调整参数、限制弱学习器的复杂性并进行早停止来防止过拟合。
  • 装袋:装袋通过平均各个模型的偏差和错误有助于减少过拟合。通常能提供更稳定和可靠的预测结果。

性能:

  • 提升:如果弱学习器选择得当且训练适当,通常比装袋获得更高的准确性。
  • 装袋:虽然不一定与提升一样准确,但通常提供更一致和可靠的结果。

计算复杂度:

  • 提升:由于模型是顺序训练且有加权实例,与装袋相比,计算上更昂贵。
  • 装袋:模型可以并行训练,因此在处理大型数据集时更加高效。

提升和装袋都是有效的集成方法,选择哪种方法取决于具体问题、数据的性质以及准确性与计算资源之间的权衡。提升更专注于纠正错误,可能导致更高的准确性;而装袋更简单且计算效率更高,提供更稳定且不易过拟合的预测结果。

1.2 Boosting算法

boosting算法是一类将弱学习器提升为强学习器的集成学习算法,它通过改变训练样本的权值,学习多个分类器,并将这些分类器进行线性组合,提高泛化性能。

Boosting系列算法的工作机制类似,大致思路为:先从初始训练集中训练出一个基学习器,再根据基学习器的表现对训练样本的分布进行调整,使得先前基学习器做错的训练样本在后续受到更多关注,然后基于调整后的样本分布来训练下一个基学习器;如此重复进行,直至基学习器数目达到事先指定的值或者组合学习器的精度达到100%,最终将这些基学习器进行线性组合,得到最终的学习器。

从Boosting的工作机制中我们可以发现,对于提升方法来说有两个关键问题需要解决:

  • 在每轮的训练中如何改变训练数据的权值分布
  • 如何将弱学习器结合成强学习器

1.3 Adaboost算法

Adaboost(adaptive boosting),又称为自适应提升算法,是最著名的Boosting算法。经典的Adaboost算法只能用于二分类问题,因此,我们在这里只讨论adaboost算法在二分类任务中的应用。其基本思想为:一开始,将训练数据的权重初始化为相等的值,训练出第一个弱分类器(这里的弱学习器一般是单层决策树,也就是决策树桩,它通过一个判断条件直接把数据一分为二),并且计算该分类器的错误率。从第二次训练开始,将会根据上一次训练所得的弱分类器的效果重新调整每个样本的权重,具体做法为降低上一次分对的样本的权重,提高上一次分错的样本的权重,然后训练出下一个弱分类器。如此循环,直到弱分类器数量达到一个给定值或者集成模型预测正确率达到100%,然后把这些弱分类器结合起来,结合策略为给分类误差率小的弱分类器分配较大的权重,给分类误差率大的弱分类器分配较小的权重,构成一个更强的最终分类器(强分类器)。

根据Adaboost算法的基本思想我们可以知道:

  • Adaboost采用重赋值法来改变训练样本的权值分布,提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被前一轮弱分类器正确分类样本的权值。这样一来,那些没有被正确分类的数据就会因为权值的加大而受到后一轮弱分类器的更大关注。于是,分类问题被一系列的弱分类器“分而治之”。
  • Adaboost采取线性组合将弱学习器结合成强学习器,给分类误差率小的弱分类器一个较大的权重,使其在最后的表决中起较大的作用,给分类误差率大的弱分类器一个较小的权重,使其在表决中起较小的作用。

1.3.1 AdaBoost分类问题

以二分类为例,假设给定一个二类分类的训练数据集\chi = \left \{ (x_{1}, y_{1}), (x_{2}, y_{2}),...,(x_{n}, y_{n})\right \},其中x_{i}表示样本点,y_{i}表示样本对应的类别,其可取值为{-1,1}。AdaBoost算法利用如下的算法,从训练数据中串行的学习一系列的弱学习器,并将这些弱学习器线性组合为一个强学习器。AdaBoost算法描述如下:

输入:训练数据集\chi = \left \{ (x_{1}, y_{1}), (x_{2}, y_{2}),...,(x_{n}, y_{n})\right \}

输出:最终的强分类器G(x)

(1)初始化训练数据的权重分布值:(D_{m} 表示第m个弱学习器的样本点的权值),也就是说初始化的权重都是 (1/n)

 D_{1}=(w_{11},...,w_{1i},...,w_{1N}),       w_{1i}=1/N,     i=1,2,...,N

(2)对M个弱学习器,m=1,2,...,M:

        a)使用具有权值分布D{_{m}}的训练数据集进行学习,得到基本分类器 G{_{m}}(x) ,其输出值为{-1,1};

        b)计算弱分类器G{_{m}}(x)在训练数据集上的分类误差率e{_{m}},其值越小的基分类器在最终分类器中的作用越大

其中,I(G{_{m}}(x{_{i}})\neq y{_{i}})取值为0或1,取0表示分类正确,取1表示分类错误。其中就等于分类错误的权重*分类错误的个数

        c)计算弱分类器G{_{m}}(x)的权重系数\alpha {_{m}}:(这里的对数是自然对数)

一般情况下 em 的取值应该小于0.5,因为若不进行学习随机分类的话,由于是二分类错误率等于0.5,当进行学习的时候,错误率应该略低于0.5。当 em 减小的时候 am 的值增大,而我们希望得到的是分类误差率越小的弱分类器的权值越大,对最终的预测产生的影响也就越大,所以将弱分类器的权值设为该方程式从直观上来说是合理地,具体的证明 am 为上式请继续往下读

        d)更新训练数据集的样本权值分布:

对于二分类,弱分类器G{_{m}}(x)的输出值取值为{-1,1},y{_{i}}的取值为{-1,1},所以对于正确的分类 y{_{i}}G{_{m}}(x)>0,对于错误的分类y{_{i}}G{_{m}}(x)<0,由于样本权重值在[0,1]之间,当分类正确时w{_{m+1,i}}取值较小,而分类错误时w{_{m+1,i}}取值较大,而我们希望得到的是权重值高的训练样本点在后面的弱学习器中会得到更多的重视。

其中,Z{_{m}}是规范化因子,主要作用是将W{_{mi}}的值规范到0-1之间,使得\sum_{i=1}^{N}{W{_{mi}}} = 1

(3)上面我们介绍了弱学习器的权重系数α如何计算,样本的权重系数W如何更新,学习的误差率e如何计算,接下来是最后一个问题,各个弱学习器采用何种结合策略了,AdaBoost对于分类问题的结合策略是加权平均法。如下,利用加权平均法构建基本分类器的线性组合:

得到最终的分类器:

1.3.2 AdaBoost回归问题

AdaBoost回归问题有许多变种,这里我们以AdaBoost R2算法为准

(1)我们先看看回归问题的误差率问题,对于第m个弱学习器,计算他在训练集上的最大误差(也就是每次训练后,计算预测值和真实值的差的最大值):

                       E{_{m}}=max|y{_{i}}-G{_{m}}(x{_{i}})|    i=1,2,...,N

然后计算每个样本的相对误差:(计算相对误差的目的是将误差规范化到[0,1]之间)

  e{_{mi}}=\frac{|y{_{i}}-G{_{m}}(x{_{i}})|}{E{_{m}}}  ,  显然 0\leq e{_{mi}}\leq 1

这里是误差损失为线性时的情况,如果我们用平方误差,则e{_{mi}}=\frac{|y{_{i}}-G{_{m}}(x{_{i}})|}{E{_{m}}^2}^2,如果我们用指数误差,则e{_{mi}}=1-exp(\frac{-y{_{i}}+G{_{m}}(x{_{i}})}{E{_{m}}})

最终得到第k个弱学习器的误差率为:  e{_{m}}=\sum_{i=1}^{N}{w{_{mi}}e{_{mi}}},表示每个样本点的加权误差的总和即为该弱学习器的误差。

(2)我们再来看看弱学习器的权重系数α,如下公式:

                   \alpha {_{m}}=\frac{e{_{m}}}{1-e{_{m}}}

(3)对于如何更新回归问题的样本权重,第k+1个弱学习器的样本权重系数为:

                w{_{m+i,i}}=\frac{w{_{mi}}}{Z{_{m}}}\alpha {_{m}}^{1-e{_{mi}}}

其中Z{_{k}}是规范化因子:Z{_{m}}=\sum_{i=1}^{N}{w{_{mi}}\alpha {_{m}}^{1-e{_{mi}}}}

(4)最后是结合策略,和分类问题不同,回归问题的结合策略采用的是对加权弱学习器取中位数的方法,最终的强回归器为: G(x)=\sum_{m=1}^{M}{g(x)ln\frac{1}{\alpha {_{m}}}},其中g(x)是所有\alpha {_{m}}G{_{m}}(x)的中位数(m=1,2,...,M)。

这就是AdaBoost回归问题的算法介绍,还有一个问题没有解决,就是在分类问题中我们的弱学习器的权重系数\alpha {_{m}}是如何通过计算严格的推导出来的。

1.3.3 AdaBoost前向分步算法

在上两节中,我们介绍了AdaBoost的分类与回归问题,但是在分类问题中还有一个没有解决的就是弱学习器的权重系数\alpha {_{m}}=\frac{1}{2}ln{\frac{1-e{_{m}}}{e{_{m}}}}是如何通过公式推导出来的。这里主要用到的就是前向分步算法,接下来我们就介绍该算法。

从另一个角度讲,AdaBoost算法是模型为加法模型,损失函数为指数函数,学习算法为前向分步算法时的分类问题。其中,加法模型表示我们的最终得到的强分类器是若干个弱分类器加权平均得到的,如下:

f(x)=\sum_{m=1}^{M}{\alpha {_{m}}G{_{m}}(x)}

损失函数是指数函数,如下:

L(y,f(x))=exp(-yf(x))

学习算法为前向分步算法,下面就来介绍AdaBoost是如何利用前向分布算法进行学习的:

(1)假设进过m-1轮迭代前向分布算法已经得到f{_{m-1}}(x)

f{_{m-1}}=f{_{m-2}}(x)+\alpha {_{m-1}}G{_{m-1}}(x)

                    =\alpha {_{1}}G{_{1}}(x)+...+\alpha {_{m-1}}G{_{m-1}}(x)

在第m轮的迭代得到\alpha {_{m}}G{_{m}}(x)f{_{m}}(x).

          f{_{m}}(x)=f{_{m-1}}(x)+\alpha {_{m}}G{_{m}}(x)

目标是使前向分布算法得到的\alpha {_{m}}G{_{m}}(x)使f{_{m}}(x)在训练数据集T上的指数损失最小,即

         (\alpha {_{m}},G{_{m}}(x))=arg \underset{\alpha ,G}{min}\sum_{i=1}^{N}exp(-y{_{i}}(f{_{m-1}}(x{_{i}})+\alpha G(x{_{i}})))

                               =arg\underset{\alpha ,G}{min}\sum_{i=1}^{N}\bar{w}{_{mi}}exp(-y{_{i}}\alpha G(x{_{i}}))          {\color{Red} (1)}

上式即为我们利用前向分步学习算法得到的损失函数。其中,\bar{w}{_{mi}}=exp(-y{_{i}}f{_{m-1}}(x{_{i}}))。因为\bar{w}{_{mi}}既不依赖\alpha也不依赖于G,所以在第m轮迭代中与最小化无关。但\bar{w}{_{mi}}依赖于f{_{m-1}}(x),随着每一轮的迭代而发生变化。

上式达到最小时所取的\alpha ^{_{*}}{_{m}}G ^{_{*}}{_{m}}(x)就是AdaBoost算法所得到的\alpha {_{m}}G{_{m}}(x)

(2)首先求分类器G ^{_{*}}{_{m}}(x)

我们知道,对于二分类的分类器G(x)的输出值为-1和1,y{_{i}}\neq G{_{m}}(x{_{i}})表示预测错误,y{_{i}}= G{_{m}}(x{_{i}})表示正确,每个样本点都有一个权重值,所以对于一个弱分类器的输出则为:G{_{m}}(x)=\sum_{i=1}^{N}\bar{w}{_{mi}}I(y{_{i}}\neq G{_{m}}(X{_{i}})),我们的目标是使损失最小化,所以我们的具有损失最小化的第m个弱分类器即为:

G^{_{*}}{_{m}}(x)=arg \underset{G}{min}\sum_{i=1}^{N}\bar{w}{_{mi}}I(y{_{i}}\neq G(x{_{i}}))   其中,\bar{w}{_{mi}}=exp(-y{_{i}}f{_{m-1}}(x{_{i}}))

为什么用I(y{_{i}}\neq G(x{_{i}}))表示一个弱分类器的输出呢?因为我们的AdaBoost并没有限制弱学习器的种类,所以它的实际表达式要根据使用的弱学习器类型来定。

此分类器即为Adaboost算法的基本分类器G{_{m}}(x),因为它是使第m轮加权训练数据分类误差率最小的基本分类器。

(3)然后就是来求\alpha ^{_{*}}{_{m}}

G ^{_{*}}{_{m}}(x)代入损失函数(1)式中,得:

\alpha {_{m}}=\sum_{i=1}^{N}\bar{w}{_{mi}}exp(-y{_{i}}\alpha{_{m}} G^{_{*}}{_{m}}(x{_{i}}))

我们的目标是最小化上式,求出对应的\alpha ^{_{*}}{_{m}}

              \sum_{i=1}^{N}\bar{w}{_{mi}}exp(-y{_{i}}\alpha{_{m}} G^{_{*}}{_{m}}(x{_{i}}))

         =\sum_{y{_{i}}=G{_{m}}(x{_{i}})}\bar{w{_{mi}}}e^{_{-\alpha }}+\sum_{y{_{i}}\neq G{_{m}}(x{_{i}})}\bar{w{_{mi}}}e^{_{\alpha }}

        =e^{_{-\alpha }}\sum_{y{_{i}}=G{_{m}}(x{_{i}})}\bar{w}{_{mi}}+e^{_{\alpha }}\sum_{y{_{i}}\neq G{_{m}}(x{_{i}})}\bar{w}{_{mi}}

        =e^{_{-\alpha }}(\sum_{i=1}^{N}\bar{w}{_{mi}}-\sum_{y{_{i}}\neq G{_{m}}(x{_{i}})}\bar{w}{_{mi}})+e^{_{\alpha }}\sum_{y{_{i}}\neq G{_{m}}(x{_{i}})}\bar{w}{_{mi}}

        =(e^{_{\alpha }}-e^{_{-\alpha }})\sum_{y{_{i}}\neq G{_{m}}(x{_{i}})}\bar{w}{_{mi}}+e^{_{-\alpha }}\sum_{i=1}^{N}\bar{w}{_{mi}}

        =(e^{_{\alpha }}-e^{_{-\alpha }})\sum_{i=1}^{N}\bar{w}{_{mi}}I(y{_{i}}\neq G{_{m}}(x{_{i}}))+e^{_{-\alpha }}\sum_{i=1}^{N}\bar{w}{_{mi}}        {\color{Red} (2)}

由于,e{_{m}}=\frac{\sum_{i=1}^{N}\bar{w}{_{mi}}I(y{_{i}}\neq G{_{m}}(x{_{i}}))}{\sum_{i=1}^{N}\bar{w}{_{mi}}}

注意:这里我们的样本点权重系数\bar{w}{_{mi}}并没有进行规范化,所以\sum_{i=1}^{m}\bar{w}{_{mi}}\neq 1

(2)式为:   (e^{_{\alpha }}-e^{_{-\alpha }})e{_{m}}\sum_{i=1}^{N}\bar{w}{_{mi}}+e^{_{-\alpha }}\sum_{i=1}^{N}\bar{w}{_{mi}}

则我们的目标是求:

         \alpha {_{m}}=arg\underset{\alpha }{min}(e^{_{\alpha }}-e^{_{-\alpha }})e{_{m}}\sum_{i=1}^{N}\bar{w}{_{mi}}+e^{_{-\alpha }}\sum_{i=1}^{N}\bar{w}{_{mi}}

上式求\alpha偏导,并令偏导等于0,得:

       (e^{_{\alpha }}+e^{_{-\alpha }})e{_{m}}\sum_{i=1}^{N}\bar{w}{_{mi}}-e^{_{-\alpha }}\sum_{i=1}^{N}\bar{w}{_{mi}}=0,进而得到:

       (e^{_{\alpha }}+e^{_{-\alpha }})e{_{m}}-e^{_{-\alpha }}=0,求得:\alpha ^{_{*}}{_{m}}=\frac{1}{2}ln\frac{1-e{_{m}}}{e{_{m}}},其中e{_{m}}为误差率:

       e{_{m}}=\frac{\sum_{i=1}^{N}\bar{w}{_{mi}}I(y{_{i}}\neq G{_{m}}(x{_{i}}))}{\sum_{i=1}^{N}\bar{w}{_{mi}}}=\sum_{i=1}^{N}w{_{mi}}I(y{_{i}}\neq G(x{_{i}}))

(4)最后看样本权重的更新。

利用前面所讲的f{_{m}}(x)=f{_{m-1}}(x)+\alpha {_{m}}G{_{m}}(x),以及权值 \bar{w}{_{mi}}=exp(-y{_{i}}f{_{m-1}}(x))

可以得到如下式子:

       \bar{w}{_{m+1,i}}=\bar{w}{_{mi}}exp(-y{_{i}}\alpha {_{m}}G{_{m}}(x{_{i}}))

这样就得到了我们前面所讲的样本权重更新公式。

1.3.4 AdoBoost算法的正则化

为了防止过拟合,AdaBoost算法中也会加入正则化项,这个正则化项我们称之为步长也就是学习率。定义为v,对于前面的弱学习器的迭代有:

f{_{m}}(x)=f{_{m-1}}(x)+\alpha {_{m}}G{_{m}}(x)

加入正则化项,就变成如下:

f{_{m}}(x)=f{_{m-1}}(x)+v\alpha {_{m}}G{_{m}}(x)

v的取值范围为(0,1]。对于同样的训练集学习效果,较小的v意味着我们需要更多的弱学习器的迭代次数。通常我们用学习率和迭代最大次数一起来决定算法的拟合效果。

2 AdaBoost的优缺点

AdaBoost(自适应增强)是一种集成学习方法,它将弱学习器(通常是决策树)组合起来创建一个强分类器。它通过在每次迭代中给予被错误分类的数据点更大的权重来专注于难以分类的实例。AdaBoost具有一些优点和缺点:

2.1 AdaBoost的优点

  • 提高准确性:与单个学习算法相比,AdaBoost通常能够实现更好的分类准确性。通过结合多个弱学习器,它可以有效处理复杂的分类问题。

  • 多样性:它可以与各种学习算法一起使用作为弱学习器,因此在选择适合当前问题的基础模型时具有灵活性。

  • 减少过拟合:AdaBoost减少了过拟合的风险,因为它更专注于错误分类的样本,使得算法在未见过的数据上具有更好的泛化能力。

  • 不需要调整许多超参数:与某些其他复杂模型不同,AdaBoost通常只有较少的超参数需要调整,使得使用和实现更加简单。

  • 有效处理不平衡数据集:即使在一个类别明显比其他类别更普遍的不平衡数据集上,AdaBoost的表现也很好。

2.2 AdaBoost的缺点

  • 对噪声数据敏感:AdaBoost对噪声数据和异常值很敏感。噪声数据可能导致过拟合,从而降低模型的性能。

  • 计算复杂度高:由于算法需要迭代训练多个弱学习器,因此可能计算上比较昂贵。

  • 需要足够的训练数据:如果训练数据不足或者弱学习器无法优于随机猜测,AdaBoost的性能可能会下降。

  • 可能导致过拟合:尽管AdaBoost在一定程度上减少了过拟合,但如果弱学习器过于复杂或者迭代次数(boosting轮数)过高,仍有可能过拟合。

  • 对复杂模型的偏好:AdaBoost倾向于偏好复杂的弱学习器,这可能导致较长的训练时间,并且如果控制不当可能导致过拟合。

AdaBoost是一种强大的集成学习技术,通过组合多个弱学习器可以显著提高分类准确性。然而,它需要仔细处理噪声数据,调整boosting轮数,并选择合适的弱学习器才能达到最佳效果。

3 AdaBoost的应用场景

AdaBoost在许多领域和应用场景中都表现出色,特别是在处理分类问题时。以下是一些AdaBoost的常见应用场景:

  • 图像识别和计算机视觉: AdaBoost可以用于图像分类、物体检测和人脸识别等计算机视觉任务,通过结合多个弱分类器来提高图像识别的准确性。

  • 自然语言处理(NLP): 在文本分类、情感分析和垃圾邮件过滤等NLP任务中,AdaBoost可以用于提高文本分类的性能。

  • 医学诊断: 在医学图像处理和诊断中,AdaBoost可用于辅助医生诊断,如肿瘤检测和疾病分类。

  • 金融领域: AdaBoost可以应用于信用风险评估、欺诈检测和股票市场预测等金融领域的问题。

  • 推荐系统: 在电子商务和在线推荐系统中,AdaBoost可以用于个性化推荐和用户行为预测。

  • 语音识别: 在语音识别应用中,AdaBoost可以用于声纹识别和语音分类等任务。

  • 生物信息学: 在分析生物数据、DNA序列分类和蛋白质结构预测等生物信息学问题中,AdaBoost可以发挥重要作用。

  • 遥感图像分析: AdaBoost可用于遥感图像分类和地物识别,如土地利用分类和环境监测。

  • 行为识别: 在行为分析和行为识别应用中,AdaBoost可以用于识别动作、行为和活动等。

虽然AdaBoost在许多场景中表现优秀,但并不是适用于所有问题。在实际应用中,需要根据具体问题的特点和数据集的特征选择合适的机器学习算法及参数调整方法。

4 AdaBoost代码实现

4.1 数据集介绍

乳腺癌数据集,是sklearn中经典的二分类数据集:

包含569个样本,每个样本30个特征,阳性样本357,阴性样本212

4.2 代码实现

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import numpy as np
from tqdm import tqdm


class CancerAdaboost:
    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] <= fv) * -1  # which <= value assign -1 else 0
            else:
                predict = (X[:, fi] > fv) * -1  # which > 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
                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)

            # 计算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)

    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 < 0] = -1
        return y_predict

    def score(self, X_test, y_test):
        y_predict = self.predict(X_test)
        return np.sum(y_predict == y_test) / len(y_predict)


if __name__ == "__main__":
    breast_cancer = load_breast_cancer()
    X = breast_cancer.data
    y = breast_cancer.target
    y[y == 0] = -1

    # 划分数据
    X_train, X_test, y_train, y_test = train_test_split(X, y)
    print(X_train.shape, X_test.shape)

    clf = CancerAdaboost(200)
    clf.fit(X_train, y_train)
    print(clf.score(X_test, y_test))

4.3 结果展示

(1)n_estimators=50,分类结果达到了93%的准确率 

  0%|          | 0/50 [00:00<?, ?it/s](426, 30) (143, 30)
100%|██████████| 50/50 [00:24<00:00,  2.04it/s]
0.9300699300699301

 (2)n_estimators=100,分类结果达到了94%的准确率 

  0%|          | 0/100 [00:00<?, ?it/s](426, 30) (143, 30)
100%|██████████| 100/100 [00:54<00:00,  1.83it/s]
0.9440559440559441

(3)n_estimators=200时,分类结果达到了97%的准确率 

(426, 30) (143, 30)
100%|██████████| 200/200 [02:09<00:00,  1.54it/s]
0.972027972027972

n_estimators数量越大,需要的计算时间也越长,准确率也越高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/798505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PDA开发:MAUI调用Jar包,so文件

PDA系统&#xff1a;android 6.0 PDA功能&#xff1a;扫码打印一体机&#xff0c;扫物料标签&#xff0c;调用金蝶云星空ERP实现收发料&#xff0c;PDA打印功能主要是同一个料号物品只贴一个标签&#xff0c;打印功能是为了复制物料标签&#xff0c;下次再发料使用 打印SDK只…

中国农业大学计算机考研分析

关注我们的微信公众号 姚哥计算机考研 更多详情欢迎咨询 中国农业大学&#xff08;B-&#xff09;考研难度&#xff08;☆☆☆&#xff09; 中国农业大学计算机考研招生学院是信息与电气工程学院。目前均已出拟录取名单。 中国农业大学信息与电气工程学院&#xff0c;起源于…

ST官方基于米尔STM32MP135开发板培训课程(一)

本文将以Myirtech的MYD-YF13X以及STM32MP135F-DK为例&#xff0c;讲解如何使用STM32CubeMX结合Developer package实现最小系统启动。 1.开发准备 1.1 Developer package准备 a.Developer package下载&#xff1a; ‍https://www.st.com/en/embedded-software/stm32mp1dev.ht…

手把手移植 simpleFOC (三):编码器篇

文章目录 前言 一、延时函数 二、修改encoder外中断接口 1.中断调用接口 2.嫁接回调函数 3、新增digitalRead函数 三、添加编译项 四、编译&#xff0c;调试 总结 前言 今天移植的主要内容是simpleFoc的encoder&#xff0c;目标是转到电机&#xff0c;读出对应的角度及角度率。…

Labview串口通信VISA实现串口收发

文章目录 前言一、什么是 VISA二、VISA 驱动下载及安装1、下载2、安装 三、VISA 实现串口收发1、打开虚拟串口2、前面板运行效果3、程序框图 前言 前面使用过调用 MSComm 控件的方式&#xff08;Labview串口通信MSComm实现串口收发&#xff09;&#xff0c;即利用 Windows 提供…

尚医通07:MongoDB+医院需求介绍

内容介绍 1、客户端工具 2、MongoDB常用操作 3、springboot集成MongoDB&#xff08;mongoTemplate&#xff09; 4、springboot集成MongoDB&#xff08;MongoRepository&#xff09; 5、医院需求介绍 6、部署医院模拟系统 7、开发平台接口-上传医院接口 客户端工具 1、…

【用IDEA基于Scala2.12.18开发Spark 3.4.1 项目】

目录 使用IDEA创建Spark项目设置sbt依赖创建Spark 项目结构新建Scala代码 使用IDEA创建Spark项目 打开IDEA后选址新建项目 选址sbt选项 配置JDK debug 解决方案 相关的依赖下载出问题多的话&#xff0c;可以关闭idea&#xff0c;重启再等等即可。 设置sbt依赖 将sbt…

Linux6.2 ansible 自动化运维工具(机器管理工具)

文章目录 计算机系统5G云计算第一章 LINUX ansible 自动化运维工具&#xff08;机器管理工具&#xff09;一、概述二、ansible 环境安装部署三、ansible 命令行模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9.ping …

【Python入门系列】第十九篇:Python基于协同过滤推荐系统的实现

文章目录 前言一、协同过滤算法简介二、计算相似度三、Python实现简单的协同过滤推荐系统总结 前言 推荐系统是现代互联网平台中的重要组成部分&#xff0c;它可以根据用户的兴趣和行为&#xff0c;向其推荐个性化的内容。协同过滤是推荐系统中常用的一种方法&#xff0c;它基…

POI信息点的diPointX、diPointY转化成经纬度

需求&#xff1a;接口返回某个地点的数据&#xff08;diPointX、diPointY&#xff09;&#xff0c;前端需把该地点转化成经纬度形式在地图上进行Marker标记。 实现&#xff1a;&#xff08;查找百度地图开发文档&#xff09; 代码验证&#xff1a; console.log(new BMap.Merca…

性能测试问题之慢sql分析

我们在做性能测试的时候&#xff0c;慢sql也可以说是很常见问题&#xff0c;我的性能测试生涯几乎经常遇到慢sql&#xff0c;那么我们怎么来判断有没有慢sql呢&#xff0c;有慢sql后怎么来分析优化呢?如图&#xff1a; 通过上图看可以看到当存在慢sql的时候&#xff0c;这里会…

火爆全网,接口自动化测试-DDT数据驱动实战总结,一篇贯通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 DDT&#xff08;D…

信息安全:网络安全体系 与 网络安全模型.

信息安全&#xff1a;网络安全体系 与 网络安全模型. 网络安全保障是一项复杂的系统工程&#xff0c;是安全策略、多种技术、管理方法和人员安全素质的综合。一般而言&#xff0c;网络安全体系是网络安全保障系统的最高层概念抽象&#xff0c;是由各种网络安全单元按照一定的规…

python更换iterm2背景图片

背景 在看知乎的时候&#xff0c;突然看到了这样的一个视频教程&#xff0c;用python代码更换iterm2的背景。于是我细细的研究一下。视频地址 视频中提到的参考文章地址&#xff1a; iterm2官网官方仓库 实现过程 我直接把作者的代码粘贴如下&#xff0c;首先需要安装iter…

pycharm 使用远程服务器 jupyter (本地jupyter同理)

1. 远程服务器miniconda 环境中创建jupyter环境 # 1. 激活环境 conda activate envname#2. 在环境中安装jupyter pip install jupyter # 或者 conda install jupyter#3. 生成jupyter_notebook_config.py文件 jupyter notebook --generate-config#4. 设置密码 jupyter noteboo…

docker—springboot服务通信

文章目录 docker—springboot服务通信一、方式1、host 二、坑点末、参考资料 docker—springboot服务通信 一、方式 1、host 步骤&#xff1a; host文件增加域名解析&#xff1a; 127.0.0.1 rabbitmqapplication.yml&#xff1a; application.yml中&#xff0c;连接方式使用…

【HarmonyOS】API6使用storage实现轻量级数据存储

写在前面 本篇内容基于API6 JS语言进行开发&#xff0c;通过结合轻量级数据存储开发指导的文档&#xff0c;帮助大家完成一个实际的代码案例&#xff0c;通过这个小案例&#xff0c;可以实现简单数据的存储。 参考文档&#xff1a;文档中心 1、页面布局 首先我们编写一个简单…

C++容器——list的模拟实现

目录 一.list的基本结构 二. 接下来就是对list类构造函数的设计了&#xff1a; 三.链表数据的增加&#xff1a; 四.接下来就是迭代器的创建了&#xff1a; 四.简单函数的实现&#xff1a; 五.构造与析构 六.拷贝构造和赋值重载 传统写法: 现代写法&#xff1a; 七.迭…

Docker—— consul的容器服务更新与发现

Docker—— consul的容器服务更新与发现 一、Consul概述1.什么是服务注册与发现2.什么是consul 二、consul 部署1.consul服务器①. 建立 Consul 服务②. 查看集群信息③. 通过 http api 获取集群信息 2.registrator服务器①. 安装 Gliderlabs/Registrator②. 测试服务发现功能是…

别再被割韭菜了,小白几块钱就能打造专属AI知识库

随着AIGC各种项目的越发成熟&#xff0c;打造自己的知识库&#xff0c;对于企业和个人来说就变的门槛越来越低&#xff0c;自己的知识库&#xff0c;有许多的好处&#xff0c;上传自己的知识文档&#xff0c;能让对话变的更加垂直专业。 但是博主看到网站很多商家动辄几千的收…