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. JQUERY实现的小巧简洁的无限级树形菜单

    JQUERY实现的小巧简洁的无限级树形菜单,可用于后台或前台侧栏菜单!兼容性也比较好. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tra ...

  2. 【BZOJ2213】[Poi2011]Difference DP

    [BZOJ2213][Poi2011]Difference Description A word consisting of lower-case letters of the English alp ...

  3. Cocos2d-x Lua中Sprite精灵类

    精灵类是Sprite,它的类图如下图所示. Sprite类图 Sprite类直接继承了Node类,具有Node基本特征.此外,我们还可以看到Sprite类的子类有:PhysicsSprite和Skin ...

  4. Android获取应用程序的信息

    1.获取应用程序的版本号: private String getAppVersionName() { String versionName = ""; try { PackageM ...

  5. linux解压war包

    可以用unzip命令 unzip project.war -d project 这样就在当前目录下解压project.war到project目录里面,参数-d的意思是创建project目录 附:unz ...

  6. ehcarts之toolbox,工具栏

    toolbox 工具栏.内置有导出图片,数据视图,动态类型切换,数据区域缩放,重置五个工具. feature各工具配置项.具体显示功能 1.saveAsImage 保存为图片. 2.restore 还 ...

  7. JDBC 入门

    1. JDBC 简介 JDBC (Java DataBase Connectivity) 就是 Java 数据库连接, 说白了就是用 Java 语言向 数据库发送 SQL 语句. JDBC 其实是访问 ...

  8. bzoj3007 解救小云公主

    3007: 解救小云公主 Time Limit: 5 Sec  Memory Limit: 512 MB Submit: 159  Solved: 71 [id=3007" style=&q ...

  9. time 和 datetime 模块

    在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行“type(time.time( ...

  10. 启动hadoop集群

    1.配置core-site.xml(每个节点上都要配置) 路径: /usr/local/hadoop-2.7.3/etc/hadoop/core-site.xml 配置项1: name: fs.def ...