import numpy as np
import matplotlib.pyplot as plt
def loadSimpData():
dataMat = np.matrix([[1., 2.1],
[2., 1.1],
[1.3, 1.],
[1., 1.],
[2., 1.]]) classLabels = [1.0, 1.0, -1.0, -1.0, 1.0] return dataMat, classLabels def showDataSet(dataMat, label):
"""
数据可视化
Parameters:
dataMat - 数据矩阵
label - 数据标签
Returns:

""" # 方法一 via CHJ
data = np.array(dataMat)
#print(data)
for i in range(len(data)):
if label[i] == 1.0:
#用plt.scatter画散点图也行
plt.plot(data[i][0], data[i][1], marker = 'o', color = 'red')
else:
plt.plot(data[i][0], data[i][1], marker = 's',color = 'blue') plt.show() # # 方法二
# data_plus = [] #正样本
# data_mins = [] #负样本
# for i in range(len(dataMat)):
# if label[i] > 0:
# data_plus.append(dataMat[i])
# else:
# data_mins.append(dataMat[i]) # data_plus_np = np.array(data_plus) #转换成numpy矩阵 #[[[1. 2.1]], [[2. 1.1]], [[2. 1. ]]]
# data_mins_np = np.array(data_mins) #转换成numpy矩阵 #[[[1.3 1. ]], [[1. 1. ]]]
# #需要转置,否则绘图不正确
# x = np.transpose(data_plus_np) # [[[1. 2. 2. ]], [[2.1 1.1 1. ]]]
# y = np.transpose(data_mins_np) # [[[1.3 1. ]], [[1. 1. ]]]
# plt.scatter(x[0], x[1]) # 正样本散点图
# plt.scatter(y[0], y[1]) # 负样本散点图
# plt.show() print("------------7.4节:基于单层决策树构建分类器-----------------------") def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
"""
(将数据集,按照feature列的value进行 二分法切分比较来赋值分类)
单层决策树分类函数
Parameters:
dataMatrix - 数据矩阵
dimen - 第dimen列,也就是第几列特征
threshVal - 阈值(特征列要比较的值)
threshIneq - 阈值不等式(这里有两个:lt和gt)
Returns:
retArray - 分类结果(np.array类型)
"""
retArray = np.ones((np.shape(dataMatrix)[0], 1)) # 生成m 行1列的单位矩阵
# thresh_ineq == 'lt'表示阈值不等式取lt(less than)
if threshIneq == 'lt':
# data_mat[:, dimen] 表示数据集中第dimen列的所有值
retArray[dataMatrix[:, dimen] <= threshVal] = -1.0 # 如果小于等于阈值,则赋值为-1 else: # 表示阈值不等式取gt(great than)
retArray[dataMatrix[:, dimen] > threshVal] = -1.0 # 如果大于阈值,则赋值为-1 return retArray def buildStump(dataArr, classLabels, D): """
找到数据集上的最佳单层决策树 -- 单层决策树是指只考虑其中的一个特征,在该特征的基础上进行分类,
寻找分类错误率最低的阈值即可, 非常简单
例如本文例子中,如果以第一列特征(dimen = 1)为基础,阈值v选择1.3,并且设置lt:<=1.3的为-1,< 1.3的为+1; gt: <1.3的为+1,<= 1.3的为-1,
这样就构造出了一个二分类器
Parameters:
dataArr - 数据矩阵
classLabels - 数据标签
D - 样本权重
Returns:
bestStump - 最佳单层决策树信息
minError - 最小误差
bestClassEst - 最佳的分类结果
""" dataMatrix = np.mat(dataArr)
labelMat = np.mat(classLabels).T
m, n = np.shape(dataMatrix) # m行n列 # numSteps用于在特征的所有可能值上进行遍历
numSteps = 10.0
bestStump = {}
bestClassEst = np.mat(np.zeros((m, 1)))
minError = float('inf') # np.inf # 最小误差初始化为正无穷大
# 第一层循环:对n列特征进行遍历(如本例中,n =2 )
for i in range(n):
rangeMin = dataMatrix[:, i].min() # 每次找到该特征中最小的值和最大的值
rangeMax = dataMatrix[:, i].max() stepSize = (rangeMax - rangeMin) / numSteps # 计算步长(确定需要多大的步长) -- 阈值查询的步长
# 第二层循环
for j in range(-1, int(numSteps) + 1):
'''
lt(less than)是指在该阈值下,如果<阈值,则分类为-1
gt(greater than)是指在该阈值下,如果>阈值,则分类为-1
就这个题目来说,两者加起来误差肯定为1
'''
#第三层循环是在大于和小于之间切换不等式
for inequal in ['lt', 'gt']: # 遍历小于和大于的情况。
threshVal = (rangeMin + float(j) * stepSize) # 计算阈值
predictedVals = stumpClassify(dataMatrix, i , threshVal, inequal) # 计算分类结果
errArr = np.mat(np.ones((m,1))) # 初始化误差矩阵 errArr[predictedVals == labelMat] = 0 # 分类正确的,赋值为0
# 基于权重向量D而不是其他错误指标来评价分类器的,不同的分类器计算方法不一样
weightedError = D.T * errArr # 计算误差--这里没有采用常规方法来评价这个分类器的分类准确率,而是乘上了权重
# print('split: dim %d, thresh %.2f, thresh inequal: %s, the weighted error is %.3f' \
# %(i, threshVal, inequal, weightedError))
if weightedError < minError:
minError = weightedError
bestClassEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal return bestStump, minError,bestClassEst print("----------7.4:完整AdaBoost算法的实现----------------------")
def adaBoostTrainDS(dataArr, classLabels, numIt= 40):
"""
使用AdaBoost算法提升分类器性能
Parameters:
dataArr - 数据矩阵
classLabels - 数据标签
numIt - 最大迭代次数
Returns:
weakClassArr - 训练好的分类器
aggClassEst - 类别估计累计值
"""
weakClassArr = []
m = np.shape(dataArr)[0]
D = np.mat(np.ones((m,1))/m) # 初始化权重
aggClassEst = np.mat(np.zeros((m,1))) for i in range(numIt): # 迭代次数
# 得到决策树的模型
bestStump, error, classEst = buildStump(dataArr, classLabels, D) #构建单个单层决策树
# print("D: ", D.T)
# 计算弱学习算法的权重alpha,使error不等于0,因为分母不能为0
# alpha 目的主要是计算每一个分类器实例的权重(加和就是分类结果)
# 计算每个分类器的 alpha 权重值
alpha = float(0.5 * np.log((1.0 - error) / max(error, 1e-16))) bestStump['alpha'] = alpha # 存储若学习算法的权重 # store Stump Params in Array weakClassArr.append(bestStump) # 存储单层决策树
#print("classEst = ", classEst.T)
expon = np.multiply(-1 * alpha * np.mat(classLabels).T, classEst)
# print("expon = ", expon.T)
D = np.multiply(D, np.exp(expon))
# print("权重分布D = ", D.T)
D = D / D.sum() # 根据样本权重公式,更新样本权重
# print("更新后权重分布D = ", D.T) # 使D成为一个概率分布 #计算AdaBoost的误差,当误差errorRate为0时,退出循环
# 计算所有类别估计累计值--注意 这里包括了目前已经训练好的每一个弱分类器
aggClassEst = aggClassEst + alpha * classEst
#print("aggClassEst: ", aggClassEst.T) #计算分类器集成后的错误矩阵,错误设置为1,便于后续计算
aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T, np.ones((m, 1))) #目前的集成分类器,分类错误
# print("aggErrors = \n", aggErrors)
errorRate = aggErrors.sum() / m
# errorRate:集成分类器分类错误率(平均),如果错误率为0,则整个集成算法停止,训练完成
#print("total error: ", errorRate)
print("集成第%s个弱分类器后的错误率ε = %.3f" %(i, errorRate))
# 如错误率为0,此时分类器以达最佳,循环终止
if errorRate == 0.0:
break return weakClassArr, aggClassEst def adaClassify(datToClass, classifierArr):
"""
Parameters:
datToClass - 待分类样例
classifierArr - 训练好的分类器
Returns:
分类结果
""" dataMatrix = np.mat(datToClass)
m = np.shape(dataMatrix)[0]
aggClassEst = np.mat(np.zeros((m,1)))
for i in range(len(classifierArr)): # 遍历所有的分类器,进行分类
classEst = stumpClassify(dataMatrix, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha'] * classEst
print(aggClassEst) return np.sign(aggClassEst) ##########################7.6 示例: 在一个难数据集上应用AdaBoost##########################
def loadDataSet(fileName):
numFeat = len(open(fileName).readline().split('\t')) #获得特征(包括类别标签列)的个数
# print("特征的个数: ", numFeat) # 输出22个(包括类别标签列)
dataMat = [] ; labelMat = []
fr = open(fileName)
for line in fr.readlines(): # 遍历行数(样本行)
lineArr = []
curLine = line.strip().split('\t') # curLine该行(当前行)的所有特征的数据
# print("curLine = ", curLine)
for i in range(numFeat - 1): # 遍历所有特征(除去类别标签列的)
lineArr.append(float(curLine[i])) # 获得该行(当前行)除最后一列的其他所有特征的数据(格式化为浮点型)
dataMat.append(lineArr)
# i = 0列时,dataMat = [[2.0, 1.0, 38.5, 66.0, 28.0, 3.0, 3.0, 0.0, 2.0, 5.0, 4.0, 4.0, \
# 0.0, 0.0, 0.0, 3.0, 5.0, 45.0, 8.4, 0.0, 0.0]]
# print("dataMat = ", dataMat)
labelMat.append(float(curLine[-1]))
return dataMat, labelMat #################7.7节:非均衡分类问题--TPR和FPR和ROC曲线绘制-########################### def plotRoc(predStrengths, classLabels):
"""
Parameters:
predStrengths--分类器的预测强度
classLabels--类别
Returns:

"""
import matplotlib.pyplot as plt
cur = (1.0, 1.0) # 绘制光标的位置
ySum = 0.0 # 用于计算AUC面积
numPosClas = np.sum(np.array(classLabels) == 1.0) # 统计正类的数量
yStep = 1 / float(numPosClas) # y轴步长
xStep = 1 / float(len(classLabels) - numPosClas) # x轴步长 sortedIndicies = predStrengths.argsort() # 预测强度排序,从低到高
# print("sortedIndicies = \n", sortedIndicies)
fig = plt.figure()
fig.clf()
ax = plt.subplot(111)
# print("sortedIndicies.tolist()[0] = \n", sortedIndicies.tolist()[0])
for index in sortedIndicies.tolist()[0]:
if classLabels[index] == 1.0:
delX = 0 ; delY = yStep
else:
delX = xStep; delY = 0
# 高度累加(xStep是固定的,最后ySum * xStep即可求AUC面积)
ySum = ySum + cur[1] # 注意每次cur[1]都可能变化了
# 绘制ROC(两点一线) 每次点(cur[0],cur[1])和点(cur[0] - delX, cur[1] - delY)连成一条直线
ax.plot([cur[0], cur[0] - delX], [cur[1], cur[1] - delY], c = 'b')
cur = (cur[0] - delX, cur[1] - delY) # 更新绘制光标的位置
#print("cur ====== \n",cur) ax.plot([0,1], [0,1], 'b--') # 画虚线(即随机猜测的结果曲线)
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC curve for AdaBoost Horse Colic Detection System')
ax.axis([0,1,0,1])
print("AUC面积为:", ySum * xStep)
plt.show() if __name__ == '__main__': dataMat, classLabels = loadSimpData()
# print(dataMat, classLabels)
# showDataSet(dataMat, classLabels)
D = np.mat(np.ones((5,1))/5)
# print(buildStump(dataMat, classLabels, D))
weakClassArr, aggClassEst = adaBoostTrainDS(dataMat, classLabels, 9)
# print("weakClassArr = ", weakClassArr) # 打印出所有弱分类器
# print("aggClassEst = ", aggClassEst)
# print('-------分割线-------')
# print(adaClassify([0,0], weakClassArr))
# print('=======分割线=======')
# print(adaClassify([[5,5], [0,0]], weakClassArr))
print() print("-----第7.6节 示例:在一个难数据集上应用AdaBoost-----")
print()
dataArr, LabelArr = loadDataSet('horseColicTraining2.txt')
weakClassArr, aggClassEst = adaBoostTrainDS(dataArr, LabelArr)
print("----------用在测试集试试-----------------------")
testArr, testLabelArr = loadDataSet('horseColicTest2.txt')
# print("weakClassArr = ", weakClassArr)
predictions = adaClassify(dataArr,weakClassArr)
errArr = np.mat(np.ones((len(dataArr), 1)))
print("训练集上的错误数:%s" %(errArr[predictions != np.mat(LabelArr).T].sum()))
print('训练集上的错误率: %.3f%%' %float(errArr[predictions != np.mat(LabelArr).T].sum() / len(dataArr) * 100)) predictions = adaClassify(testArr, weakClassArr)
errArr = np.mat(np.ones((len(testArr), 1)))
print("测试集上的错误数:%s" %(errArr[predictions != np.mat(testLabelArr).T].sum()))
print('测试集上的错误率: %.3f%%' %float(errArr[predictions != np.mat(testLabelArr).T].sum() / len(testArr) * 100))
print("-------------7.7节:非均衡分类问题--TPR和FPR和ROC曲线绘制--------------------")
print()
plotRoc(aggClassEst.T, LabelArr)

《机器学习实战第7章:利用AdaBoost元算法提高分类性能》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. WPF TextBox 验证输入

    //验证输入为数字private void txt_time_KeyDown(object sender, KeyEventArgs e){ if (!((e.Key >= Key.D0 &am ...

  2. CentOS 7.0 防火墙

    CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙.firewall:systemctl start firewalld.service#启动firewalls ...

  3. std::vector<std::vector<> >

    上次看到这个有点晕了,其实这个vector保存的是std::vector<> #include <vector> #include <iostream> using ...

  4. [CTSC1999][网络流24题] 星际转移

    36. [CTSC1999][网络流24题] 星际转移 ★★★☆   输入文件:home.in   输出文件:home.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: ...

  5. Problem H. Hotel in Ves Lagos

    Problem H. Hotel in Ves Lagos Input le: hotel.in Output le: hotel.out Time limit: 1 second Memory li ...

  6. RabbitMQ指南之三:发布/订阅模式(Publish/Subscribe)

    在上一章中,我们创建了一个工作队列,工作队列模式的设想是每一条消息只会被转发给一个消费者.本章将会讲解完全不一样的场景: 我们会把一个消息转发给多个消费者,这种模式称之为发布-订阅模式. 为了阐述这个 ...

  7. How to make asynchronous HTTP requests in PHP 4种PHP异步执行的常用方式

    [是否等待返回就执行下一步] How to make asynchronous HTTP requests in PHP - Stack Overflow https://stackoverflow. ...

  8. 删除datatable中的行

    今天遇到一问题,无论如何也删除不干净datatable.我想全部删除.但总是得不到想要的结果. ; i < dt.Rows.Count; i++) { //dt.Rows.Remove(dt.R ...

  9. JVM 指令讲解

    挺有意思的  转载记录下 转载自 https://www.cnblogs.com/f1194361820/p/8524666.html    原作者: 房继诺 JVM 指令 1.Demo 2.Clas ...

  10. TGraphicControl(自绘就2步,直接自绘自己,不需要调用VCL框架提供的函数重绘所有子控件,也不需要自己来提供PaintWindow函数让管理框架来调用)与TControl关键属性方法速记(Repaint要求父控件执行详细代码来重绘自己,还是直接要求Invalidate无效后Update刷新父控件,就看透明不透明这个属性,因为计算显示的区域有所不同)

    TGraphicControl = class(TControl) private FCanvas: TCanvas; procedure WMPaint(var Message: TWMPaint) ...