Adaboost

举报
九年义务漏网鲨鱼 发表于 2025/09/15 15:15:07 2025/09/15
【摘要】 Adaboost 一、基本内容[!note]实现思路:在每一轮训练中,记录每一次由f(x)=∑m=1i−1αmGm(x)f(x) = \sum_{m=1}^{i-1}\alpha_mG_m(x)f(x)=∑m=1i−1​αm​Gm​(x)【错误\正确】分类的样本,在加入新的弱学习器中【提高\降低】分类【错误\正确】样本的权值(即改变样本的比例,类似过采样与降采样)加法模型:多个弱分类器Gm...

Adaboost

一、基本内容

[!note]

实现思路:在每一轮训练中,记录每一次由f(x)=m=1i1αmGm(x)f(x) = \sum_{m=1}^{i-1}\alpha_mG_m(x)【错误\正确】分类的样本,在加入新的弱学习器中【提高\降低】分类【错误\正确】样本的权值即改变样本的比例,类似过采样与降采样

  • 加法模型:多个弱分类器Gm(x)G_m(x)与对应权值αm\alpha_m的叠加:

f(x)=m=1MαmGm(x)f(x) = \sum_{m=1}^M\alpha_mG_m(x)

  • 样本权值的初始设计(权值平等):

w1,i=1Nw_{1,i}=\frac{1}{N}

  • 二分类损失函数,指数损失函数

L(y,f(x))=exp[yf(x)]=exp[y(fm1(xi)+αmGm(x))]L(y,f(x)) = exp[-yf(x)]=exp[-y ·(f_{m-1}(x_i)+\alpha_mG_m(x))]

二、样本权值更新

​ 可以发现,指数损失函数在【正确\错误】分类的样本的值【小于\大于】1,正好符合Adaboost加法模型的实现思路,在加入新的弱学习器中【提高\降低】分类【错误\正确】样本的权值,所以第mm个弱分类器,第ii个样本的权值更新可以设计为:

ωm,i=exp[yifm1(xi)]\omega_{m,i} = exp[-y_if_{m-1}(x_i)]

​ 在Adaboost模型中,fm1(xi)=am1Gm1f_{m-1}(x_i) = a_{m-1}G_{m-1},所以,权值更新的公式为:

wm,i=exp(yi(am1)Gm1(xi))w_{m,i} = exp(y_i(-a_{m-1})G_{m-1}(x_i))

​ 为了加强不同弱分类器之间的依赖性,在更新权值时是在上一个弱分类器模型的基础上进行更新的:

wm,i=wm1,iexp(am1yiGm1(xi))w_{m,i} = w_{{m-1},i} · exp(-a_{m-1}y_iG_{m-1}(x_i))

​ 最后加入Zm1Z_{m-1},得到最终的权值更新式子:

wm,i=wm1,izm1exp(am1yiGm1(xi))w_{m,i} = \frac{w_{m-1,i}}{z_{m-1}}exp(-a_{m-1}y_iG_{m-1}(x_i))

​ 其中,规范化因子Zm1Z_{m-1}表示为:

Zm1=i=1Nωm1,iexp(am1yiGm1(xi))Z_{m-1} = \sum_{i=1}^{N}\omega_{m-1,i}exp(-a_{m-1}y_iG_{m-1}(x_i))

[!important]

分类正确时,yi=Gm1(xi)y_i=G_{m-1}(x_i), exp(am1yiGm1(xi))=exp(am1)<1exp(-a_{m-1}y_iG_{m-1}(x_i))=exp(-a_{m-1}) < 1, 其中am1>1a_{m-1}>1,对应正确样本的权值会减少,同理当错误分类时,exp(am1)>1exp(-a_{m-1}) > 1,对应样本的权值增加

三、弱分类器权值更新

​ 目标损失函数:

L(y,f(x))=exp[yf(x)]=exp[y(fm1(xi)+αmGm(x))]L(y,f(x)) = exp[-yf(x)]=exp[-y ·(f_{m-1}(x_i)+\alpha_mG_m(x))]

​ 在模型优化更新权重的过程中,并不是与传统模型一样采用梯度下降法,因为弱分类器的数量多,更新的参数多,难以实现,在Adaboost模型中采用的前向分布算法,只更新当前弱分类器GmG_m的参数,优化目标:

(am,Gm(x)=argmaxa,Gi=1Nexp[yi(fm1(xi)+αGm(xi))])(a_m,G_m(x) = argmax_{a,G} \sum_{i=1}^Nexp[-y_i(f_{m-1}(x_i) + \alpha G_m(x_i))])

​ 对aa求导的结果,表示损失最小的α\alpha

αm=12log1emem\alpha_m = \frac{1}{2}log\frac{1-e_m}{e_m}

​ 其中eme_m表示误差率:

em=i=1NP(Gm(xiyi))=i=1NωmiI(Gm(xiyi))=Gm(xi)yiωmie_m' = \sum_{i=1}^N P(G_m(x_i \neq y_i))= \sum_{i=1}^N\omega_{mi}I(G_m(x_i \neq y_i))= \sum_{G_m(x_i) \neq y_i}\omega_{mi}

​ 最后还需要实现归一化:

em=Gm(xi)yiωmii=1Nωime_m = \frac{\sum_{G_m(x_i) \neq y_i}\omega_{mi}}{\sum_{i=1}^N}\omega_i^{m}

四、代码实现

  • 定义弱分类器,采用决策树
model = DecisionTreeClassifier(max_depth=1)
model.fit(X, y, sample_weight=w)
y_pred = model.predict(X)
  • 权重更新

权重初始化w1,i=1Nw_{1,i}=\frac{1}{N}

# 权重初始化
w = np.ones(n_samples) / n_samples # 初始化权重

误差率计算em=Gm(xi)yiωmii=1Nωime_m = \frac{\sum_{G_m(x_i) \neq y_i}\omega_{mi}}{\sum_{i=1}^N}\omega_i^{m}

弱分类器α\alpha更新αm=12log1emem\alpha_m = \frac{1}{2}log\frac{1-e_m}{e_m}

# 误差率计算以及更新权重
err = np.sum(w * (y_pred != y)) / np.sum(w)
alpha = 0.5 * np.log((1 - err) / max(err, 1e-10))

样本权重更新wm,i=wm1,izm1exp(am1yiGm1(xi))w_{m,i} = \frac{w_{m-1,i}}{z_{m-1}}exp(-a_{m-1}y_iG_{m-1}(x_i))

# 更新样本权重
norm = np.sum(w)
w = w * np.exp(-alpha * y * y_pred)
w /= norm 
  • 加法模型预测:f(x)=m=1MαmGm(x)f(x) = \sum_{m=1}^M\alpha_mG_m(x)
for alpha, model in zip(self.alphas, self.models):
    pred += alpha * model.predict(X)
return np.sign(pred)
  • 完整代码:
class AdaBoost:
    def __init__(self, n_estimators=50):
        self.n_estimators = n_estimators
        self.alphas = []  # 每个弱分类器的权重
        self.models = []  # 弱分类器列表

    def fit(self, X, y):
        n_samples, n_features = X.shape
        # 初始化样本权重
        w = np.ones(n_samples) / n_samples # 初始化权重

        for _ in range(self.n_estimators):
            # 使用样本权重训练一个弱分类器
            model = DecisionTreeClassifier(max_depth=1)
            model.fit(X, y, sample_weight=w)
            y_pred = model.predict(X)

            # 计算分类误差率
            err = np.sum(w * (y_pred != y)) / np.sum(w)
            if err >= 0.5:
                break

            # 计算弱分类器的权重
            alpha = 0.5 * np.log((1 - err) / max(err, 1e-10))
            self.alphas.append(alpha)
            self.models.append(model)
            norm = np.sum(w)
            # 更新样本权重
            w = w * np.exp(-alpha * y * y_pred)
            w /= norm

    def predict(self, X):
        pred = np.zeros(X.shape[0])
        for alpha, model in zip(self.alphas, self.models):
            pred += alpha * model.predict(X)
        return np.sign(pred)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。