步骤:
def buildStump(dataArr,classLabels,D):
1。循环取出数据集中的一个特征(一列)输入 (for:)
2。循环调整阀值threshVal (for:)
3,。分成两个子树
左边:特征值xi<=threshVal 为-1,否则为1
获得预测结果1
右边:特征值xi>threshVal 为-1,否则为-1
获得预测结果2
4。分别把预测结果同真实标签比较,获得一个向量(对的为零,错误为1)
5。和权重向量D相乘,获得一个值(权重错误值,用来计算alpha),评判分类器的好坏。
5。获得最低的错误率结果保存起来
返回:单层决策树(弱分类器),最小错误,预测的标签
循环结束后,每一个特征都对应一个阀值,而这个阀值,可以最大准确度地分割特征
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上的过程就实现一个分类器,接下来通过训练,来获取一定数量较好的弱分类器
def buildStump(dataArr,classLabels,D):
1。 初始化权重D(它与上述过程中的权重D是同一个,它的作用是增加错误分类的权重,降低正确分类的权重)
2。 迭代过程(for:迭代次数)
3。 buildStump(dataArr,classLabels,D):(调用上面的过程,创建一个弱分类器)
4。 计算alpha(Adaboost为每一个弱分类器都分配一个权重alpha,这些alpha值都是基于每一个弱分类器的错误率进行计算)
5。 保存alpha到决策树集合(弱分类器)中,同时也保存这个分类器
6。 更新权重向量D
7。 和真实的标签相比计算错误分类的个数
8。 计算错误率
9。 直到错误率为零则退出循环
返回:弱分类器的集合
这个过程结束,就获得一个弱分类器的集合,整体来说分类的效果越来越好
---------------------------------------------------------------------------------------------------------------------------------------------------------
调用训练好的模型进行分类
传入要分类的数据datToClass,传入弱分类器集合classifierArr(也就是训练好的模型)
def adaClassify(datToClass,classifierArr):
(for:弱分类器的个数)
1。使用弱分类器i预测结果标签labeli
2。乘以它的这个弱分类器的权重alpha
3。累加每一个弱分类器的这个结果(其实就是一个投票过程)
4。获得结果
用一个图表示就是这样的
为了更好的了解分类器的性能,我们通过画出ROC曲线,来更好的了解。
什么是ROC :https://www.cnblogs.com/zhxuxu/p/9911660.html
接下来是机器学习实战中的代码(详细注释),代码和上面的流程搭配看,希望对你有帮助。
#coding=utf-8 from numpy import * def loadSimpData(): datMat = matrix([[1.0,2.1], [ 2. , 1.1], [ 1.3, 1. ], [ 1. , 1. ], [ 2. , 1. ]]) classLabels = [1.0, 1.0, -1.0, -1.0, 1.0] return datMat,classLabels def loadDataSet(fileName): numFeat = len(open(fileName).readline().split(' ')) dataMat = [];labelMat = [] fr = open(fileName) for line in fr.readlines(): lineArr = [] curLine = line.strip().split(' ') for i in range(numFeat - 1): lineArr.append(float(curLine[i])) dataMat.append(lineArr) labelMat.append(float(curLine[-1])) return dataMat,labelMat def stumpClassify(dataMatrix,dimen,threshVal,threshIneg): #初始化数据类别都为+1 #分左右子树 #与阀值比较,左子树小于阀值为-1,大于阀值为1。右侧大于阀值为-1,小于阀值为1。 #这两种分法,最后取错误率最低的分法 retArray = ones((shape(dataMatrix)[0],1)) if threshIneg =='lt': retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 else: retArray[dataMatrix[:,dimen] > threshVal] = -1.0 return retArray def buildStump(dataArr,classLabels,D): dataMatrix = mat(dataArr); labelMat = mat(classLabels).T m,n = shape(dataMatrix) numSteps = 10.0; bestStump = {}; bestClasEst = mat(zeros((m,1))) minError = inf #循环取样本的第i个特征 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']: #计算阀值 threshVal = (rangeMin + float(j) * stepSize) #计算预测标签 predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal) #错误矩阵,用来记录预测错误的样本 errArr = mat(ones((m,1))) #实际标签与预测标签相等的为0 errArr[predictedVals == labelMat] = 0 #权重向量D乘错误矩阵,预测正确的权重为零,权重就无需更改 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 print ("bestsplit: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (bestStump['dim'], bestStump['thresh'], bestStump['ineq'], minError)) #返回的是bestStump中保存的单层决策树(就是选择出了两类中能使错误率降到最低的特征) #最小错误率,最好的类别预测 return bestStump,minError,bestClasEst def adaBoostTrainDS(dataArr,classLabels,numIt=40): weakClassArr = [] m = shape(dataArr)[0] #D是一个概率分布向量,其和要等于1,因此要除以m #权重的初始化可以是一样的随着迭代次数增加 #增加错误分类的权重,降低错误分类的权重 D = mat(ones((m,1))/m) aggClassEst = mat(zeros((m,1))) for i in range(numIt): #创建一个弱学习器(树根) bestStump,error,classEst = buildStump(dataArr,classLabels,D) print ("D:",D.T) #Adaboost为每一个弱分类器都分配一个权重alpha #这些alpha值都是基于每一个弱分类器的错误率进行计算 #计算公式alpha = 1/2ln(1-c/c) #c是错误率c=错误分类的样本个数/所有样本总数 #为了防止分母为零,增加1e-16 alpha = float(0.5*log((1.0-error)/max(error,1e-16))) #存到树根中 bestStump['alpha'] = alpha weakClassArr.append(bestStump) print ("classEst: ",classEst.T) #更新权重向量D #正确分类的expon为负(权重影响小) #错误分类的expon为正(权重影响大) #这里正确标签和预测样本标签相乘,标签一样为正,不一样为负 expon = multiply(-1*alpha*mat(classLabels).T,classEst) D = multiply(D,exp(expon)) D = D/D.sum() aggClassEst += alpha*classEst #sign if a>0 return 1,if a<0 return -1,if a==0 return 0 #计算错误分类的个数 aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1))) #错误率 errorRate = aggErrors.sum()/m print ("total error: ",errorRate) if errorRate == 0.0: break #返回每一次迭代获得的最好结果的分类器 #弱分类器参数集合,和每一个弱分类器对应的alpha(权重) return weakClassArr,aggClassEst def adaClassify(datToClass,classifierArr): dataMatrix = mat(datToClass) m = shape(dataMatrix)[0] aggClassEst = mat(zeros((m,1))) #classifierArr是最优分类器的集合 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 sign(aggClassEst) #ROC曲线的绘制及AUC计算函数 def plotROC(predStrengths, classLabels): import matplotlib.pyplot as plt cur = (1.0,1.0) #AUC的值 ySum = 0.0 #计算分类为正的个数 numPosClas = sum(array(classLabels)==1.0) yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas) #predStrengths是投票预测结果(非整数),argsort()从大到小排序,返回下标 #也就是预测结果接近于1(分类为正)的排在前面 sortedIndicies = predStrengths.argsort() #print('predStrengths',predStrengths) #print('classLabels',classLabels) fig = plt.figure() fig.clf() ax = plt.subplot(111) #classLabels是真实结果,通过比较,为正类,移动y轴,否则移动x轴 for index in sortedIndicies.tolist()[0]: if classLabels[index] == 1.0: delX = 0; delY = yStep; else: delX = xStep; delY = 0; ySum += cur[1] ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b') cur = (cur[0]-delX,cur[1]-delY) 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]) plt.show() def test(): datMat,classLabels = loadSimpData() #D = mat(ones((5,1))/5) #buildStump(datMat,classLabels,D) #以上就构成了一个弱分类器 #接下来训练出多个弱分类器,构成Adaboost算法 classifierArray = adaBoostTrainDS(datMat,classLabels,numIt=9) print(classifierArray) #接下来进行测试 #实例对马疝病数据集分类使用Adaboost def app(): datArr,labelArr = loadDataSet('horseColicTraining2.txt') classifierArray = adaBoostTrainDS(datArr,labelArr,10) testArr,testLabelArr = loadDataSet('horseColicTest2.txt') prediction10 = adaClassify(testArr,classifierArray) errArr = mat(ones((67,1))) errArr[prediction10!=mat(testLabelArr).T].sum() #画ROC曲线图 def plotROCtest(): datArr,labelArr = loadDataSet('horseColicTraining2.txt') classifierArray,aggClassEst = adaBoostTrainDS(datArr,labelArr,10) plotROC(aggClassEst.T, labelArr)
测试代码时,可以分别运行
def test()
def app()
def plotROCtest()
实现具体的功能