python实现AdaBoost算法的示例

代码

'''
数据集:Mnist
训练集数量:60000(实际使用:10000)
测试集数量:10000(实际使用:1000)
层数:40
------------------------------
运行结果:
  正确率:97%
  运行时长:65m
'''

import time
import numpy as np

def loadData(fileName):
  '''
  加载文件
  :param fileName:要加载的文件路径
  :return: 数据集和标签集
  '''
  # 存放数据及标记
  dataArr = []
  labelArr = []
  # 读取文件
  fr = open(fileName)
  # 遍历文件中的每一行
  for line in fr.readlines():
    # 获取当前行,并按“,”切割成字段放入列表中
    # strip:去掉每行字符串首尾指定的字符(默认空格或换行符)
    # split:按照指定的字符将字符串切割成每个字段,返回列表形式
    curLine = line.strip().split(',')
    # 将每行中除标记外的数据放入数据集中(curLine[0]为标记信息)
    # 在放入的同时将原先字符串形式的数据转换为整型
    # 此外将数据进行了二值化处理,大于128的转换成1,小于的转换成0,方便后续计算
    dataArr.append([int(int(num) > 128) for num in curLine[1:]])
    # 将标记信息放入标记集中
    # 放入的同时将标记转换为整型

    # 转换成二分类任务
    # 标签0设置为1,反之为-1
    if int(curLine[0]) == 0:
      labelArr.append(1)
    else:
      labelArr.append(-1)
  # 返回数据集和标记
  return dataArr, labelArr

def calc_e_Gx(trainDataArr, trainLabelArr, n, div, rule, D):
  '''
  计算分类错误率
  :param trainDataArr:训练数据集数字
  :param trainLabelArr: 训练标签集数组
  :param n: 要操作的特征
  :param div:划分点
  :param rule:正反例标签
  :param D:权值分布D
  :return:预测结果, 分类误差率
  '''
  # 初始化分类误差率为0
  e = 0
  # 将训练数据矩阵中特征为n的那一列单独剥出来做成数组。因为其他元素我们并不需要,
  # 直接对庞大的训练集进行操作的话会很慢
  x = trainDataArr[:, n]
  # 同样将标签也转换成数组格式,x和y的转换只是单纯为了提高运行速度
  # 测试过相对直接操作而言性能提升很大
  y = trainLabelArr
  predict = []

  # 依据小于和大于的标签依据实际情况会不同,在这里直接进行设置
  if rule == 'LisOne':
    L = 1
    H = -1
  else:
    L = -1
    H = 1

  # 遍历所有样本的特征m
  for i in range(trainDataArr.shape[0]):
    if x[i] < div:
      # 如果小于划分点,则预测为L
      # 如果设置小于div为1,那么L就是1,
      # 如果设置小于div为-1,L就是-1
      predict.append(L)
      # 如果预测错误,分类错误率要加上该分错的样本的权值(8.1式)
      if y[i] != L:
        e += D[i]
    elif x[i] >= div:
      # 与上面思想一样
      predict.append(H)
      if y[i] != H:
        e += D[i]
  # 返回预测结果和分类错误率e
  # 预测结果其实是为了后面做准备的,在算法8.1第四步式8.4中exp内部有个Gx,要用在那个地方
  # 以此来更新新的D
  return np.array(predict), e

def createSigleBoostingTree(trainDataArr, trainLabelArr, D):
  '''
  创建单层提升树
  :param trainDataArr:训练数据集数组
  :param trainLabelArr: 训练标签集数组
  :param D: 算法8.1中的D
  :return: 创建的单层提升树
  '''

  # 获得样本数目及特征数量
  m, n = np.shape(trainDataArr)
  # 单层树的字典,用于存放当前层提升树的参数
  # 也可以认为该字典代表了一层提升树
  sigleBoostTree = {}
  # 初始化分类误差率,分类误差率在算法8.1步骤(2)(b)有提到
  # 误差率最高也只能100%,因此初始化为1
  sigleBoostTree['e'] = 1

  # 对每一个特征进行遍历,寻找用于划分的最合适的特征
  for i in range(n):
    # 因为特征已经经过二值化,只能为0和1,因此分切分时分为-0.5, 0.5, 1.5三挡进行切割
    for div in [-0.5, 0.5, 1.5]:
      # 在单个特征内对正反例进行划分时,有两种情况:
      # 可能是小于某值的为1,大于某值得为-1,也可能小于某值得是-1,反之为1
      # 因此在寻找最佳提升树的同时对于两种情况也需要遍历运行
      # LisOne:Low is one:小于某值得是1
      # HisOne:High is one:大于某值得是1
      for rule in ['LisOne', 'HisOne']:
        # 按照第i个特征,以值div进行切割,进行当前设置得到的预测和分类错误率
        Gx, e = calc_e_Gx(trainDataArr, trainLabelArr, i, div, rule, D)
        # 如果分类错误率e小于当前最小的e,那么将它作为最小的分类错误率保存
        if e < sigleBoostTree['e']:
          sigleBoostTree['e'] = e
          # 同时也需要存储最优划分点、划分规则、预测结果、特征索引
          # 以便进行D更新和后续预测使用
          sigleBoostTree['div'] = div
          sigleBoostTree['rule'] = rule
          sigleBoostTree['Gx'] = Gx
          sigleBoostTree['feature'] = i
  # 返回单层的提升树
  return sigleBoostTree

def createBosstingTree(trainDataList, trainLabelList, treeNum=50):
  '''
  创建提升树
  创建算法依据“8.1.2 AdaBoost算法” 算法8.1
  :param trainDataList:训练数据集
  :param trainLabelList: 训练测试集
  :param treeNum: 树的层数
  :return: 提升树
  '''
  # 将数据和标签转化为数组形式
  trainDataArr = np.array(trainDataList)
  trainLabelArr = np.array(trainLabelList)
  # 没增加一层数后,当前最终预测结果列表
  finallpredict = [0] * len(trainLabelArr)
  # 获得训练集数量以及特征个数
  m, n = np.shape(trainDataArr)

  # 依据算法8.1步骤(1)初始化D为1/N
  D = [1 / m] * m
  # 初始化提升树列表,每个位置为一层
  tree = []
  # 循环创建提升树
  for i in range(treeNum):
    # 得到当前层的提升树
    curTree = createSigleBoostingTree(trainDataArr, trainLabelArr, D)
    # 根据式8.2计算当前层的alpha
    alpha = 1 / 2 * np.log((1 - curTree['e']) / curTree['e'])
    # 获得当前层的预测结果,用于下一步更新D
    Gx = curTree['Gx']
    # 依据式8.4更新D
    # 考虑到该式每次只更新D中的一个w,要循环进行更新知道所有w更新结束会很复杂(其实
    # 不是时间上的复杂,只是让人感觉每次单独更新一个很累),所以该式以向量相乘的形式,
    # 一个式子将所有w全部更新完。
    # 该式需要线性代数基础,如果不太熟练建议补充相关知识,当然了,单独更新w也一点问题
    # 没有
    # np.multiply(trainLabelArr, Gx):exp中的y*Gm(x),结果是一个行向量,内部为yi*Gm(xi)
    # np.exp(-1 * alpha * np.multiply(trainLabelArr, Gx)):上面求出来的行向量内部全体
    # 成员再乘以-αm,然后取对数,和书上式子一样,只不过书上式子内是一个数,这里是一个向量
    # D是一个行向量,取代了式中的wmi,然后D求和为Zm
    # 书中的式子最后得出来一个数w,所有数w组合形成新的D
    # 这里是直接得到一个向量,向量内元素是所有的w
    # 本质上结果是相同的
    D = np.multiply(D, np.exp(-1 * alpha * np.multiply(trainLabelArr, Gx))) / sum(D)
    # 在当前层参数中增加alpha参数,预测的时候需要用到
    curTree['alpha'] = alpha
    # 将当前层添加到提升树索引中。
    tree.append(curTree)

    # -----以下代码用来辅助,可以去掉---------------
    # 根据8.6式将结果加上当前层乘以α,得到目前的最终输出预测
    finallpredict += alpha * Gx
    # 计算当前最终预测输出与实际标签之间的误差
    error = sum([1 for i in range(len(trainDataList)) if np.sign(finallpredict[i]) != trainLabelArr[i]])
    # 计算当前最终误差率
    finallError = error / len(trainDataList)
    # 如果误差为0,提前退出即可,因为没有必要再计算算了
    if finallError == 0:
      return tree
    # 打印一些信息
    print('iter:%d:%d, sigle error:%.4f, finall error:%.4f' % (i, treeNum, curTree['e'], finallError))
  # 返回整个提升树
  return tree

def predict(x, div, rule, feature):
  '''
  输出单独层预测结果
  :param x: 预测样本
  :param div: 划分点
  :param rule: 划分规则
  :param feature: 进行操作的特征
  :return:
  '''
  # 依据划分规则定义小于及大于划分点的标签
  if rule == 'LisOne':
    L = 1
    H = -1
  else:
    L = -1
    H = 1

  # 判断预测结果
  if x[feature] < div:
    return L
  else:
    return H

def test(testDataList, testLabelList, tree):
  '''
  测试
  :param testDataList:测试数据集
  :param testLabelList: 测试标签集
  :param tree: 提升树
  :return: 准确率
  '''
  # 错误率计数值
  errorCnt = 0
  # 遍历每一个测试样本
  for i in range(len(testDataList)):
    # 预测结果值,初始为0
    result = 0
    # 依据算法8.1式8.6
    # 预测式子是一个求和式,对于每一层的结果都要进行一次累加
    # 遍历每层的树
    for curTree in tree:
      # 获取该层参数
      div = curTree['div']
      rule = curTree['rule']
      feature = curTree['feature']
      alpha = curTree['alpha']
      # 将当前层结果加入预测中
      result += alpha * predict(testDataList[i], div, rule, feature)
    # 预测结果取sign值,如果大于0 sign为1,反之为0
    if np.sign(result) != testLabelList[i]:
      errorCnt += 1
  # 返回准确率
  return 1 - errorCnt / len(testDataList)

if __name__ == '__main__':
  # 开始时间
  start = time.time()

  # 获取训练集
  print('start read transSet')
  trainDataList, trainLabelList = loadData('../Mnist/mnist_train.csv')

  # 获取测试集
  print('start read testSet')
  testDataList, testLabelList = loadData('../Mnist/mnist_test.csv')

  # 创建提升树
  print('start init train')
  tree = createBosstingTree(trainDataList[:10000], trainLabelList[:10000], 40)

  # 测试
  print('start to test')
  accuracy = test(testDataList[:1000], testLabelList[:1000], tree)
  print('the accuracy is:%d' % (accuracy * 100), '%')

  # 结束时间
  end = time.time()
  print('time span:', end - start)

程序运行结果

start read transSet
start read testSet
start init train
iter:0:40, sigle error:0.0804, finall error:0.0804
iter:1:40, sigle error:0.1448, finall error:0.0804
iter:2:40, sigle error:0.1362, finall error:0.0585
iter:3:40, sigle error:0.1864, finall error:0.0667
iter:4:40, sigle error:0.2249, finall error:0.0474
iter:5:40, sigle error:0.2634, finall error:0.0437
iter:6:40, sigle error:0.2626, finall error:0.0377
iter:7:40, sigle error:0.2935, finall error:0.0361
iter:8:40, sigle error:0.3230, finall error:0.0333
iter:9:40, sigle error:0.3034, finall error:0.0361
iter:10:40, sigle error:0.3375, finall error:0.0325
iter:11:40, sigle error:0.3364, finall error:0.0340
iter:12:40, sigle error:0.3473, finall error:0.0309
iter:13:40, sigle error:0.3006, finall error:0.0294
iter:14:40, sigle error:0.3267, finall error:0.0275
iter:15:40, sigle error:0.3584, finall error:0.0288
iter:16:40, sigle error:0.3492, finall error:0.0257
iter:17:40, sigle error:0.3506, finall error:0.0256
iter:18:40, sigle error:0.3665, finall error:0.0240
iter:19:40, sigle error:0.3769, finall error:0.0251
iter:20:40, sigle error:0.3828, finall error:0.0213
iter:21:40, sigle error:0.3733, finall error:0.0229
iter:22:40, sigle error:0.3785, finall error:0.0218
iter:23:40, sigle error:0.3867, finall error:0.0219
iter:24:40, sigle error:0.3850, finall error:0.0208
iter:25:40, sigle error:0.3823, finall error:0.0201
iter:26:40, sigle error:0.3825, finall error:0.0204
iter:27:40, sigle error:0.3874, finall error:0.0188
iter:28:40, sigle error:0.3952, finall error:0.0186
iter:29:40, sigle error:0.4018, finall error:0.0193
iter:30:40, sigle error:0.3889, finall error:0.0177
iter:31:40, sigle error:0.3939, finall error:0.0183
iter:32:40, sigle error:0.3838, finall error:0.0182
iter:33:40, sigle error:0.4021, finall error:0.0171
iter:34:40, sigle error:0.4119, finall error:0.0164
iter:35:40, sigle error:0.4093, finall error:0.0164
iter:36:40, sigle error:0.4135, finall error:0.0167
iter:37:40, sigle error:0.4099, finall error:0.0171
iter:38:40, sigle error:0.3871, finall error:0.0163
iter:39:40, sigle error:0.4085, finall error:0.0154
start to test
the accuracy is:97 %
time span: 3777.730945825577

以上就是python实现AdaBoost算法的示例的详细内容,更多关于python实现AdaBoost算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • python 贪心算法的实现

    贪心算法 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解. 贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关. 基本思路 思想 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解.每一步只考虑一个数据,他的选取应该满足局部优化的条件.若

  • Python 实现国产SM3加密算法的示例代码

    SM3是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布.主要用于报告文件数字签名及验证. Python3代码如下: from math import ceil ############################################################################## # # 国产SM3加密算法 # #####################################################

  • python实现人工蜂群算法

    ABSIndividual.py import numpy as np import ObjFunction class ABSIndividual: ''' individual of artificial bee swarm algorithm ''' def __init__(self, vardim, bound): ''' vardim: dimension of variables bound: boundaries of variables ''' self.vardim = va

  • python机器学习包mlxtend的安装和配置详解

    今天看到了mlxtend的包,看了下example集成得非常简洁.还有一个吸引我的地方是自带了一些data直接可以用,省去了自己造数据或者找数据的处理过程,所以决定安装体验一下. 依赖环境 首先,sudo pip install mlxtend 得到基础环境. 然后开始看看系统依赖问题的解决.大致看了下基本都是python科学计算用的那几个经典的包,主要是numpy,scipy,matplotlib,sklearn这些. LINUX环境下的话,一般这些都比较好装pip一般都能搞定. 这里要说的一

  • python机器学习库xgboost的使用

    1.数据读取 利用原生xgboost库读取libsvm数据 import xgboost as xgb data = xgb.DMatrix(libsvm文件) 使用sklearn读取libsvm数据 from sklearn.datasets import load_svmlight_file X_train,y_train = load_svmlight_file(libsvm文件) 使用pandas读取完数据后在转化为标准形式 2.模型训练过程 1.未调参基线模型 使用xgboost原生库

  • python 机器学习之实现朴素贝叶斯算法的示例

    特点 这是分类算法贝叶斯算法的较为简单的一种,整个贝叶斯分类算法的核心就是在求解贝叶斯方程P(y|x)=[P(x|y)P(y)]/P(x) 而朴素贝叶斯算法就是在牺牲一定准确率的情况下强制特征x满足独立条件,求解P(x|y)就更为方便了 但基本上现实生活中,没有任何关系的两个特征几乎是不存在的,故朴素贝叶斯不适合那些关系密切的特征 from collections import defaultdict import numpy as np from sklearn.datasets import

  • python机器学习实现决策树

    本文实例为大家分享了python机器学习实现决策树的具体代码,供大家参考,具体内容如下 # -*- coding: utf-8 -*- """ Created on Sat Nov 9 10:42:38 2019 @author: asus """ """ 决策树 目的: 1. 使用决策树模型 2. 了解决策树模型的参数 3. 初步了解调参数 要求: 基于乳腺癌数据集完成以下任务: 1.调整参数criterion,使

  • python 如何实现遗传算法

    1.基本概念 遗传算法(GA)是最早由美国Holland教授提出的一种基于自然界的"适者生存,优胜劣汰"基本法则的智能搜索算法.该法则很好地诠释了生物进化的自然选择过程.遗传算法也是借鉴该基本法则,通过基于种群的思想,将问题的解通过编码的方式转化为种群中的个体,并让这些个体不断地通过选择.交叉和变异算子模拟生物的进化过程,然后利用"优胜劣汰"法则选择种群中适应性较强的个体构成子种群,然后让子种群重复类似的进化过程,直到找到问题的最优解或者到达一定的进化(运算)时间.

  • python实现暗通道去雾算法的示例

    何凯明博士的去雾文章和算法实现已经漫天飞了,我今天也就不啰里啰唆,直接给出自己python实现的完整版本,全部才60多行代码,简单易懂,并有简要注释,去雾效果也很不错. 在这个python版本中,计算量最大的就是最小值滤波,纯python写的,慢,可以进一步使用C优化,其他部分都是使用numpy和opencv的现成东东,效率还行. import cv2 import numpy as np def zmMinFilterGray(src, r=7): '''最小值滤波,r是滤波器半径''' ''

  • python实现sm2和sm4国密(国家商用密码)算法的示例

    GMSSL模块介绍 GmSSL是一个开源的加密包的python实现,支持SM2/SM3/SM4等国密(国家商用密码)算法.项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用. 安装模块 pip install gmssl https://github.com/duanhongyi/gmssl/blob/master/README.md官方文档 SM2算法 RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产

  • python 实现关联规则算法Apriori的示例

    首先导入包含apriori算法的mlxtend库, pip install mlxtend 调用apriori进行关联规则分析,具体代码如下,其中数据集选取本博客 "机器学习算法--关联规则" 中的例子,可进行参考,设置最小支持度(min_support)为0.4,最小置信度(min_threshold)为0.1, 最小提升度(lift)为1.0,对数据集进行关联规则分析, from mlxtend.preprocessing import TransactionEncoder fro

随机推荐