超全面讲透一个算法模型,AdaBoost ! !

学术   2024-09-25 08:51   中国台湾  

大家好,我是小白~

今儿的基础算法,我们来聊AdaBoost~

首先,咱们来通俗易懂的聊聊 AdaBoost 是什么,能干什么?~

AdaBoost 是一种 提升方法,全称叫 Adaptive Boosting,翻译成中文就是自适应增强。它是一种用来组合多个弱分类器的算法,最后让它们变得更强大。这里的 “弱分类器” 是指那些表现不太好的模型,单独使用时准确率不高,但通过 AdaBoost 的技巧把它们结合在一起,能得到一个强大的分类器。

那么,AdaBoost 是怎么工作的呢?

  1. 开始的时候,我们有一个数据集,AdaBoost 会先训练一个简单的分类器(也就是“弱分类器”)。这个弱分类器在某些样本上做对了,但在其他样本上犯错了。

  2. 接下来,AdaBoost 会关注这些被第一个分类器错分的样本,给它们更高的权重,意思是让后面的分类器更加注意这些错误的地方。

  3. 然后,继续训练下一个分类器,这个新的分类器会尽量改进前一个分类器做错的地方。再次犯错的样本,权重又会进一步增大,直到最后为止。

  4. 最终,AdaBoost 会把所有这些弱分类器的结果组合起来,得到一个更强的分类器。这个组合过程也很聪明:表现好的分类器权重大,表现不好的分类器权重小。

用例子来解释

假设大家是老师,班里有三个同学负责给出考试及格不及格的判断。他们分别是小红、小明和小李。每个人的准确率都不是很高,他们单独判断的准确率只有 60%。现在,你想通过 AdaBoost 的方式,让他们一起做出更准确的判断。

  1. 第一步:初始化权重

    你首先假设班里的所有同学的意见都一样重要。所以一开始每个同学的投票权重是一样的(比如每个人 1 票)。这时你让第一个同学小红判断一组学生是否及格。

    小红可能在 60% 的学生上判断对了,但她也在 40% 的学生上判断错了。AdaBoost 发现小红对某些学生判断错了,那就要在下一轮里给这些学生更高的权重。

  2. 第二步:更新权重

    接着,轮到第二个同学小明来判断了。因为 AdaBoost 注意到小红之前犯错的那些学生,它会让小明更加注意这些学生——这意味着在给小明的训练数据中,那些小红判断错误的学生占更大的比重。小明会尽量改进小红的错误。

  3. 第三步:再次更新

    小明也不会百分之百准确,他也会犯错。所以第三轮的时候,你把小李拉过来,让他在小红和小明都搞错的地方下更多功夫。

  4. 最终结果:组合

    最后,你不再单独听小红、小明或小李任何一个人的意见,而是结合他们三个人的判断。因为 AdaBoost 给每个人分配了不同的权重,表现好的同学(比如在关键学生上判断对了的)会有更多话语权,表现不好的同学权重就小。

通过这样的一轮轮调整,AdaBoost 最终会生成一个综合的“老师”,它能比任何单独的小红、小明或小李表现得都好。

总的来说,AdaBoost 的核心思想就是把多个表现一般的弱分类器(比如小红、小明、小李)组合起来,并且让每个后续分类器特别关注前面分类器做错的地方。最后,经过多轮的组合,得到一个强大的分类器,可以比单个分类器做得更好。

下面,咱们聊聊对应的原理、公式和一个完整的案例。

1. AdaBoost 算法公式推导

基本思想

假设我们有一个数据集 ,其中  是样本的特征, 是样本的标签。AdaBoost 的目标是通过加权组合一系列弱分类器来创建一个强分类器。

1. 弱分类器的训练: AdaBoost 会生成一系列弱分类器,每个弱分类器根据当前的样本权重进行训练。样本的权重表示这个样本的重要性。

2. 加权分类器的组合: AdaBoost 最终生成的分类器是多个弱分类器的加权和。我们给每个弱分类器一个权重,表现越好的分类器权重越大。

算法步骤

初始化样本权重:
给定样本 ,初始时,每个样本的权重都相等,初始化为:

循环 T 轮,训练弱分类器:

第 t 轮中:

1. 训练弱分类器:
使用当前的样本权重  训练一个弱分类器 

2. 计算分类误差:
弱分类器在当前权重下的分类误差为:

其中  表示分类错误的样本。

3. 计算分类器权重:
分类器的权重表示其重要性,计算公式为:

4. 更新样本权重:
下一轮的样本权重更新为:

然后进行归一化,使得权重和为 1。

最终分类器:
最终的强分类器是所有弱分类器的加权和:

2. Python 案例

import numpy as np
import matplotlib.pyplot as plt

# 生成虚拟数据集
np.random.seed(42)
X = np.random.randn(10002)
y = np.where(X[:, 0] + X[:, 1] > 01-1)

# 弱分类器:单层决策树 (简单的阈值分类器)
def weak_classifier(X, feature_index, threshold, polarity):
    predictions = np.ones(X.shape[0])
    if polarity == 1:
        predictions[X[:, feature_index] < threshold] = -1
    else:
        predictions[X[:, feature_index] >= threshold] = -1
    return predictions

# 训练一个弱分类器
def train_weak_classifier(X, y, weights):
    n_samples, n_features = X.shape
    best_classifier = {}
    best_error = float('inf')
    for feature_index in range(n_features):
        feature_values = np.sort(X[:, feature_index])
        for threshold in feature_values:
            for polarity in [1-1]:
                predictions = weak_classifier(X, feature_index, threshold, polarity)
                error = np.sum(weights * (predictions != y))
                if error < best_error:
                    best_error = error
                    best_classifier = {
                        'feature_index': feature_index,
                        'threshold': threshold,
                        'polarity': polarity,
                        'predictions': predictions
                    }
    return best_classifier, best_error

# AdaBoost 主流程
def adaboost(X, y, T=10):
    n_samples = X.shape[0]
    weights = np.ones(n_samples) / n_samples
    classifiers = []
    classifier_weights = []

    for t in range(T):
        classifier, error = train_weak_classifier(X, y, weights)
        alpha = 0.5 * np.log((1 - error) / (error + 1e-10))  # 避免除以 0
        classifiers.append(classifier)
        classifier_weights.append(alpha)

        # 更新权重
        weights *= np.exp(-alpha * y * classifier['predictions'])
        weights /= np.sum(weights)  # 归一化

    return classifiers, classifier_weights

# 预测函数
def predict(X, classifiers, classifier_weights):
    n_samples = X.shape[0]
    final_predictions = np.zeros(n_samples)
    for classifier, alpha in zip(classifiers, classifier_weights):
        predictions = weak_classifier(X, classifier['feature_index'],
                                      classifier['threshold'],
                                      classifier['polarity'])
        final_predictions += alpha * predictions
    return np.sign(final_predictions)

# 训练 AdaBoost 模型
T = 10  # 弱分类器数量
classifiers, classifier_weights = adaboost(X, y, T)

# 预测
y_pred = predict(X, classifiers, classifier_weights)

# 可视化
plt.figure(figsize=(128))

# 图 1: 数据点分布
plt.subplot(221)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm', s=50)
plt.title('Data Distribution')

# 图 2: 弱分类器权重分布
plt.subplot(222)
plt.bar(range(1, T+1), classifier_weights, color='lightcoral')
plt.title('Classifier Weights')

# 图 3: 样本权重分布
plt.subplot(223)
weights_final = np.ones(X.shape[0]) / X.shape[0]
for classifier, alpha in zip(classifiers, classifier_weights):
    weights_final *= np.exp(-alpha * y * classifier['predictions'])
weights_final /= np.sum(weights_final)
plt.bar(range(X.shape[0]), weights_final, color='seagreen')
plt.title('Sample Weights')

# 图 4: 分类结果
plt.subplot(224)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='coolwarm', s=50)
plt.title('Predicted Classes')

plt.tight_layout()
plt.show()

图 1:数据点分布

展示了虚拟数据集的分布,红色和蓝色表示不同的类别。

图 2:弱分类器权重分布

每一轮的弱分类器都有一个权重,权重越高表示分类器在这轮中的表现越好。

图 3:样本权重分布

展示了经过多轮迭代后,样本的权重分布。错误分类的样本会获得更大的权重。

图 4:分类结果

最终的分类结果,展示了 AdaBoost 组合多个弱分类器后给出的预测。

最后

整个原理,以及代码手动实现了 AdaBoost 算法,并生成了多个图像,希望帮助到大家理解数据和分类过程中的权重变化。

学术之友
\x26quot;学术之友\x26quot;旨在建立一个综合的学术交流平台。主要内容包括:分享科研资讯,总结学术干货,发布科研招聘等。让我们携起手来共同学习,一起进步!
 最新文章