AdaBoost元算法

项目代码

元算法

元算法(meta-algorithm)是对其他算法进行组合的一种方式。(或称集成方法,ensemble method)
集成方法的不同形式:

  1. 不同算法的集成
  2. 同一算法在不同设置下的集成
  3. 数据集不同部分分配给不同分类器之后的集成
  4. 基于同一种分类器在多个不同实例下的集成

bagging:基于数据随机重抽样的分类器构建方法

bagging也称自举汇聚法(bootstrap aggregating)。
核心思想:假设训练集有 N N N个样本,从中随机抽取 S S S次,每次有放回的获取 M M M个样本,用某个单独的算法对 S S S个数据集(每个数据集有 M M M个样本)进行训练,这样就可以获得 S S S个分类器,最后通过投票来获取最后的结果。
随机森林(Random Forest,RF)是bagging方法的一种,其基于决策树,不仅对数据随机化抽取,也对特征随机化抽取。
1. 数据的随机化:利用bootstrap方法有放回地随机抽取 S S S个新的样本集。
2. 特征随机化 n n n个特征,每棵树随机选择 m m m个特征划分数据集。

boosting

boosting方法是先在原数据集上训练出一个分类器,然后将前一个分类器没能完美分类的数据样本重新赋权重(weight),用新的权重数据样本再训练出一个分类器,以此循环,最终的分类结果由加权投票决定。

  1. boosting和bagging均使用单个学习算法。
  2. boosting是串行算法(必须依赖上一个分类器),bagging是并行算法(可以同时进行);
  3. boosting的分类器权重不同,bagging相同。
boosting:AdaBoost

AdaBoost是boosting最流行的一个版本。
AdaBoost的基础理论:使用弱分类器和多个实例构建一个强分类器,弱意味着分类器的性能比随机猜测的要略好,但不会好太多,而强分类器的错误率要低很多。
AdaBoost的算法流程:

  1. 给每个训练样本赋权重,这些权重构成向量 D D D(初始权重相等,如1000个数据,那每个数据样本初始权重为1/1000)。
  2. 在该数据上训练一个弱分类器并计算错误率和该分类器的权重值 α \alpha α(基于每个弱分类器的错误率进行计算)。
  3. 基于该 α \alpha α值重新计算权重(分错的样本权重变大,分对的权重变小)。
  4. 循环2,3步,在完成给定的迭代次数或错误阈值时,停止循环。
  5. 最终的分类结果由加权投票决定。
    错误率
    ε = 分 类 错 误 的 样 本 数 所 有 样 本 数 目 \varepsilon=\frac{分类错误的样本数}{所有样本数目} ε=
    α \alpha α值的计算
    α = 1 2 l n 1 − ε ε \alpha=\frac{1}{2}ln\frac{1-\varepsilon}{\varepsilon} α=21lnε1ε
    AdaBoost算法示意图(来源机器学习是实战):
    在这里插入图片描述
    计算出 α \alpha α值后,可以对权重向量 D D D进行更新,以使得那些正确分类的样本的权重降低而分错样本的权重增大。
    样本正确分类,其权重修改为:
    D t ( t + 1 ) = D t ( t ) e − α ∑ ( D ) D_t^{(t+1)}=\frac{D_t^{(t)}e^{-\alpha}}{\sum(D)} Dt(t+1)=(D)Dt(t)eα
    样本被错误分类,其权重修改为:
    D t ( t + 1 ) = D t ( t ) e α ∑ ( D ) D_t^{(t+1)}=\frac{D_t^{(t)}e^{\alpha}}{\sum(D)} Dt(t+1)=(D)Dt(t)eα

基于单层决策树构建弱分类器

加载数据:

import numpy as np
import matplotlib.pyplot as plt


def read_data():
    data = np.array([[1, 2.1], [2, 1.1], [1.3, 1], [1, 1], [2, 1]])
    label = [1, 1, -1, -1, 1]
    return data,label


if __name__ =="__main__":
    data,label = read_data()
    x =data[:,0]
    y =data[:,1]
    # print(x)
    plt.scatter(x,y,c=label)
    plt.show()```
构建单层决策树:

```python
import numpy as np


def stump_classify(x, dim, thresh_val, thresh_ineq):
    '''
    通过阈值比较对数据进行分类。
    所有在阈值一边的数据会分到类别-1,而另一边的数据会被分类到+1。
    通过数组过滤实现。
    '''
    retArray = np.ones((x.shape[0], 1))
    if thresh_ineq == 'lt':
        retArray[x[:, dim] <= thresh_val] = -1
    else:
        retArray[x[:, dim] > thresh_val] = -1
    return retArray


def build_stump(x, y, D):
    '''

    :param x: 输入数据
    :param y: 输入数据的标签
    :param D: 权重向量
    :return:
    '''
    x_mat = np.matrix(x)  # 转换成矩阵形式
    y_mat = np.matrix(y).T
    m, n = x.shape
    num_steps = 10
    best_stump = {}
    best_class_est = np.matrix(np.zeros((m, 1)))
    min_err = np.inf
    for i in range(n):  # 遍历所有特征
        row_min = x_mat[:, i].min()
        row_max = x_mat[:, i].max()
        step_size = (row_max - row_min) / num_steps
        for j in range(-1, num_steps + 1):
            for eq in ['lt', 'gt']:
                thresh_val = row_min + j * step_size
                pre_val = stump_classify(x, i, thresh_val, eq)
                err_arr = np.matrix(np.ones((m, 1)))
                err_arr[pre_val == y_mat] = 0
                weight_err = D.T * err_arr
                print("split: dim %d, thresh %.2f, thresh ineqal: %s, "
                      "the weighted error is %.3f"
                      % (i, thresh_val, eq, weight_err))
                if weight_err < min_err:
                    min_err = weight_err
                    best_class_est = pre_val.copy()
                    best_stump['dim'] = i
                    best_stump['thresh'] = thresh_val
                    best_stump['ineq'] = eq

        return best_stump, min_err, best_class_est

分类实现代码:

import numpy as np
from stump import *


def adaboost_trian(x, y, num_it=40):
    week_class_arr = []
    m = x.shape[0]
    D = np.matrix(np.ones((m, 1)) / m)  # 初始化权重向量D
    agg_class_est = np.matrix(np.zeros((m, 1)))
    for i in range(num_it):
        best_stump, err, class_est = build_stump(x, y, D)
        print('D: ', D.T)
        alpha = 0.5 * np.log((1 - err) // max(err, 1e-16))  # 计算alpha值
        best_stump['alpha'] = alpha
        week_class_arr.append(best_stump)
        print('class_est: ', class_est.T)
        expon = np.multiply(np.matrix(-1 * alpha * y).T, class_est)
        D = np.multiply(D, np.exp(expon))
        D = D / np.sum(D)
        agg_class_est += np.multiply(alpha, class_est)
        print('agg_class_est: ', agg_class_est.T)
        agg_err = np.multiply(np.sign(agg_class_est) != np.matrix(y).T, np.ones((m, 1)))
        err_rate = np.sum(agg_err) / m
        print('total error: ', err_rate, '\n')
        if err_rate == 0:
            break
    return week_class_arr


def adaClassify(test, classifierArr):
    dataMatrix = np.matrix(test)  # do stuff similar to last aggClassEst in adaBoostTrainDS
    m = dataMatrix.shape[0]
    aggClassEst = np.matrix(np.zeros((m, 1)))
    for i in range(len(classifierArr)):
        classEst = stump_classify(dataMatrix, classifierArr[i]['dim'],
                                  classifierArr[i]['thresh'],
                                  classifierArr[i]['ineq'])  # call stump classify
        aggClassEst += np.multiply(classifierArr[i]['alpha'], classEst)
        print(aggClassEst)
    return np.sign(aggClassEst)

测试代码:

from adaboost import adaboost_trian,adaClassify
from load_data import read_data

if __name__ =='__main__':
    data,label = read_data()
    classifier_array = adaboost_trian(data,label,9)
    # print(classifier_array)
    re = adaClassify([[5,5],[0,0]],classifier_array)
    print(re)```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值