目录
第1关:组合相似分类器提高分类性能
任务描述:
相关知识:
一、几种不同的分类器:
二、bagging:基于数据随机重抽样的分类器构建方法:
三、boosting:
编程要求:
测试说明:
本关任务:编写一个组合分类器。
为了完成本关任务,你需要掌握:1.了解几种不同分类器 2.如何遍历数组。
基于数据集多重抽样的分类器 我们可以将不同的分类器组合起来,而这种组合结果则被称为集成方法(ensemblemethod)或者元算法(meta-algorithm)。使用集成方法时会有多种形式:可以是不同算法的集成,也可以是同一算法在不同设置下的集成,还可以是数据集不同部分分配给不同分类器之后的集成。我们将介绍基于同一种分类器多个不同实例的两种计算方法。在这些方法当中,数据集也会不断变化,而后应用于不同的实例分类器上。
自举汇聚法(bootstrap aggregating),是在从原始数据集选择s次后得到s个新数据集的一种技术。新数据集和原数据集的大小相等。每个数据集都是通过在原始 数据集中随机选择一个样本来进行替换而得到的这里的替换就意味着可以多次地选择同一 样本。这一性质就允许新数据集中可以有重复的值,而原始数据集的某些值在新集合中则不 再出现。 在5个数据集建好之后,将某个学习算法分别作用于每个数据集就得到了^个分类器。当我们要对新数据进行分时,就可以应用这s个分类器进行分类。与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。
boosting是一种与bagging很类似的技术,不论在boosting还是在bagging当中,所使用的的多个分类器的类型都是一致的。但是在前者当中,不同的分类器是通过串行训练而获得的,每个新分类器都根据已训练出的分类器的性能来进行训练。boosting是通过集中关注被已有分类器错分的那些数据来获得新的分类器。
由于boosting分类的结果是基于所有分类器的加权求和的结果,因此boosting与bagging不太一样。bagging中的分类器权重是相等的,而boosting的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。
boosting方法有多个版本,我们只关注一个最流行的版本AdaBoost AdaBoost的一般流程
(1)收集数据:可以使用任意方法。
(2)准备数据:依赖于所使用的弱分类器类型,本章使用的是单层决策树,这种分类器可 以处理任何数据类型。当然也可以使用任意分类器作为弱分类器。作为弱分类器,简单分类器的效果更好。 (3)分析数据:可以使用任意方法。
(4)训练算法:AdaBoost的大部分时间都用在训絲上,分类器将多次在同一数据集上训练 弱分类器。
(5)测试算法:计算分类的错误率。
(6)使用算法:同SVM—样,AdaBoost预测两个类别中的一个。如果想把它应用到多个类别的场合,那么就要像多类SVM中的做法一样对AdaBoost进行修改。
在构造AdaBoost的代码时,我们将首先通过一个简单数据来确保在算法上实现一切就绪。我们首先构建一个单层决策树,做好过渡到完整Adaboost算法的准备。
第一个函数将用于测试是否有某个值小于或者大于我们正在测试的阈值。第二个函数则更加复杂一些,它会在一个加权数据集中循环,并找到具有最低错误率的单层决策树。
这个程序的伪代码看起来大致如下:
将最小错误率minError设为+∞
对数据集中的每一个特征(第一层循环):
对每个步长(第二层循环):
对每个不等号(第三层循环):
建立一棵单层决策树并利用加权数据集对它进行测试
如果错误率低于minErr0r,则将当前单层决策树设为最佳 单层决策树 返回最佳单雇决策树
根据提示,在右侧编辑器补充代码,完成单层决策树生成函数
平台会对你编写的代码进行测试:
import numpy as np
import matplotlib.pyplot as plt
'''
Parameters
无
Returns
dataMat - 数据矩阵
classLabels - 数据标签
'''
# 创建单层决策树的数据集
def loadSimpData():
datMat = np.matrix([[ 1. , 2.1],
[ 1.5, 1.6],
[ 1.3, 1. ],
[ 1. , 1. ],
[ 2. , 1. ]])
classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
return datMat,classLabels
'''
Parameters
dataMatrix - 数据矩阵
dimen - 第dimen列,也就是第几个特征
threshVal - 阈值
threshIneq - 标志
Returns
retArray - 分类结果
'''
# 单层决策树分类函数
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
retArray = np.ones((np.shape(dataMatrix)[0],1)) #初始化retArray为1
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果小于阈值,则赋值为-1
else:
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果大于阈值,则赋值为-1
return retArray
'''
Parameters
dataArr - 数据矩阵
classLabels - 数据标签
D - 样本权重
Returns
bestStump - 最佳单层决策树信息
minError - 最小误差
bestClasEst - 最佳的分类结果
'''
# 找到数据集上最佳的单层决策树
def buildStump(dataArr,classLabels,D):
#########
#请在此处添加你的代码
#最小误差初始化为正无穷大
#遍历所有特征
#找到特征中最小的值和最大值
#计算步长
#大于和小于的情况,均遍历。ltless than,gtgreater than
#计算阈值
#计算分类结果
#初始化误差矩阵
#分类正确的,赋值为0
#计算误差
#找到误差最小的分类方式
return bestStump,minError,bestClasEst
if __name__ == '__main__':
dataArr,classLabels = loadSimpData()
D = np.mat(np.ones((5, 1)) / 5)
bestStump,minError,bestClasEst = buildStump(dataArr,classLabels,D)
print('bestStumpn', bestStump)
print('minErrorn', minError)
print('bestClasEstn', bestClasEst)
import numpy as np
import matplotlib.pyplot as plt
'''
Parameters
无
Returns
dataMat - 数据矩阵
classLabels - 数据标签
'''
# 创建单层决策树的数据集
def loadSimpData():
datMat = np.matrix([[ 1. , 2.1],
[ 1.5, 1.6],
[ 1.3, 1. ],
[ 1. , 1. ],
[ 2. , 1. ]])
classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
return datMat,classLabels
'''
Parameters
dataMatrix - 数据矩阵
dimen - 第dimen列,也就是第几个特征
threshVal - 阈值
threshIneq - 标志
Returns
retArray - 分类结果
'''
# 单层决策树分类函数
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
retArray = np.ones((np.shape(dataMatrix)[0],1)) #初始化retArray为1
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果小于阈值,则赋值为-1
else:
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果大于阈值,则赋值为-1
return retArray
'''
Parameters
dataArr - 数据矩阵
classLabels - 数据标签
D - 样本权重
Returns
bestStump - 最佳单层决策树信息
minError - 最小误差
bestClasEst - 最佳的分类结果
'''
# 找到数据集上最佳的单层决策树
def buildStump(dataArr,classLabels,D):
#########
#请在此处添加你的代码
#最小误差初始化为正无穷大
#遍历所有特征
#找到特征中最小的值和最大值
#计算步长
#大于和小于的情况,均遍历。ltless than,gtgreater than
#计算阈值
#计算分类结果
#初始化误差矩阵
#分类正确的,赋值为0
#计算误差
dataMatrix = np.mat(dataArr); labelMat = np.mat(classLabels).T
m,n = np.shape(dataMatrix)
numSteps = 10.0; bestStump = {}; bestClasEst = np.mat(np.zeros((m,1)))
minError = float('inf') #最小误差初始化为正无穷大
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):
for inequal in ['lt', 'gt']: #大于和小于的情况,均遍历。ltless than,gtgreater than
threshVal = (rangeMin + float(j)*stepSize) #计算阈值
predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)#计算分类结果
errArr = np.mat(np.ones((m,1))) #初始化误差矩阵
errArr[predictedVals == labelMat] = 0 #分类正确的,赋值为0
weightedError = D.T*errArr #计算误差
print("split: dim %d, thresh %.2f, thresh ineqal %s, the weighted error is %.3f "% (i, threshVal, inequal, weightedError))
if weightedError < minError: #找到误差最小的分类方式
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
#找到误差最小的分类方式
return bestStump,minError,bestClasEst
if __name__ == '__main__':
dataArr,classLabels = loadSimpData()
D = np.mat(np.ones((5, 1)) / 5)
bestStump,minError,bestClasEst = buildStump(dataArr,classLabels,D)
print('bestStumpn', bestStump)
print('minErrorn', minError)
print('bestClasEstn', bestClasEst)