西瓜书课后题8.5(bagging)

题目

试编程实现Bagging,以决策树桩为基学习器,在西瓜数据集3.0 α \alpha α上训练一个Bagging继承。

原理

  • bootstrap: 假如数据集dataSet有N个数据,bootstrap的过程是随机从dataSet中取N次数据,得到新的数据集用来训练。
  • bagging: 不断bootstrap获得新的数据集,并训练新的学习器。
    因为每次数据集都不太一样,集成起来可以消除方差。

代码

# coding=utf-8
import numpy as np


def getDataSet():
    dataSet = [
        [0.697, 0.460, '是'],
        [0.774, 0.376, '是'],
        [0.634, 0.264, '是'],
        [0.608, 0.318, '是'],
        [0.556, 0.215, '是'],
        [0.403, 0.237, '是'],
        [0.481, 0.149, '是'],
        [0.437, 0.211, '是'],
        [0.666, 0.091, '否'],
        [0.243, 0.267, '否'],
        [0.245, 0.057, '否'],
        [0.343, 0.099, '否'],
        [0.639, 0.161, '否'],
        [0.657, 0.198, '否'],
        [0.360, 0.370, '否'],
        [0.593, 0.042, '否'],
        [0.719, 0.103, '否']
    ]

    for i in range(len(dataSet)):
        if dataSet[i][-1] == '是':
            dataSet[i][-1] = 1
        else:
            dataSet[i][-1] = -1

    return np.array(dataSet)


def bootstrap(dataSet):
    """
    采样得到与源数据集相同大小的数据集。
    :param dataSet:
    :return:
    """
    n = len(dataSet)
    index = np.random.randint(0, n, n)
    newData = dataSet[index]
    return newData


def calErr(dataSet, feature, threshVal, inequal):
    """
    计算决策树桩的错误率
    :param dataSet:     数据集
    :param feature:     属性index
    :param threshVal:   属性阈值
    :param inequal:     不等号
    :return:            错误率
    """
    errCnt = 0
    if inequal == 'lt':
        for data in dataSet:
            if (data[feature] <= threshVal and data[-1] == -1) or \
                    (data[feature] > threshVal and data[-1] == 1):
                errCnt += 1
    else:
        for data in dataSet:
            if (data[feature] >= threshVal and data[-1] == -1) or \
                    (data[feature] < threshVal and data[-1] == 1):
                errCnt += 1
    return errCnt / float(len(dataSet))


def buildStump(dataSet):
    """
    决策树桩
    :param dataSet:
    :return:    返回储存决策树桩的字典。
    """
    m, n = dataSet.shape
    bestErr = np.inf
    bestStump = {}
    for i in range(n - 1):
        for j in range(m):
            threVal = dataSet[j][i]
            for inequal in ['lt', 'gt']:
                err = calErr(dataSet, i, threVal, inequal)
                if err < bestErr:
                    bestErr = err
                    bestStump["feature"] = i
                    bestStump["threshVal"] = threVal
                    bestStump["inequal"] = inequal
                    bestStump["err"] = err

    return bestStump


def predict(data, bestStump):
    """
    通过决策树桩预测数据的类别。
    :param data:        待预测的数据。
    :param bestStump:   决策树桩的字典。
    :return:            预测值。
    """
    if bestStump["inequal"] == 'lt':
        if data[bestStump["feature"]] <= bestStump["threshVal"]:
            return 1
        else:
            return -1
    else:
        if data[bestStump["feature"]] >= bestStump["threshVal"]:
            return 1
        else:
            return -1


def calcAcc(dataSet, G):
    """
    计算分类器的准确度
    :param dataSet:    数据集
    :param G:          通过bagging得到的分类器列表。
    :return:           准确度
    """
    rightCnt = 0
    for data in dataSet:
        preCnt = 0
        for g in G:
            preCnt += predict(data, g)
        if (preCnt > 0 and data[-1] == 1) \
                or (preCnt <= 0 and data[-1] == -1):
            rightCnt += 1
    return rightCnt / float(len(dataSet))


def bagging(dataSet, T):
    """
    通过bootstrap从原数据中得到新的数据,训练新的分类器。
    :param dataSet:     数据集
    :param T:           分类器数量
    :return:            分类器列表
    """
    G = []
    for t in range(T):
        newDataSet = bootstrap(dataSet)
        stump = buildStump(newDataSet)
        G.append(stump)
    return G


def main():
    dataSet = getDataSet()
    for t in [3, 5, 11]:
        G = bagging(dataSet, 11)
        print(f"G{t} = ", G)
        print("prediction = ", calcAcc(dataSet, G))


if __name__ == '__main__':
    main()

输出结果

在这里插入图片描述

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值