from numpy import *
import matplotlib.pyplot as plt
#比较阈值,进行分类 threshVal 是阈值,即对某个特征的分割,threshIneq为不等号,确定是大于为-还是小于为-1
def stumpClassify(dataMtrix,dimen,threshVal,threshIneq): #dim为那一列(那个属性)
retArray = ones((shape(dataMtrix)[0],1)) #把类别都先设置为1
if threshIneq == 'lt':
retArray[dataMtrix[:,dimen] <= threshVal] = -1
else:
retArray[dataMtrix[:,dimen] > threshVal] = -1
return retArray
#单层决策树 D为权重
def buildStump(dataArr,classLabels,D):
dataMAtrix = mat(dataArr)
labelMat = mat(classLabels).T
m,n = shape(dataMAtrix) #行数和列数
numSteps = 10.0 #每个特征迭代的步数
bestStump = {} #保存最好的分类的信息
bestClassEst = mat(zeros((m,1))) #保存最好的
minError = 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 inequel in ['lt','gt']:
threshVal = rangeMin + float(j)*stepSize #每一步划分的阈值
predictedVals = stumpClassify(dataMAtrix,i,threshVal,inequel) #预测的分类值
errArr = mat(ones((m,1))) #假全错了
errArr[predictedVals == labelMat] = 0 #分正确的变为0
weightError = D.T*errArr #errArr为1的位置说明是分错的,则对应位子的样本的权重相加
#保存信息
if weightError < minError:
minError = weightError
bestClassEst = predictedVals.copy() #保存最好的分类预测值
bestStump['dim'] = i #最好的列(最好的属性)
bestStump['thred'] = threshVal #属性列最好的分割阈值
bestStump['ineq'] = inequel #最好的符号
return bestStump,minError,bestClassEst
#数据集
def loadData():
dataMat = 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 plotData(dataMat,classLabels):
for index,data in enumerate(dataMat):
# print(data)[[1. 2.1]]
# [[2. 1.1]]
# [[1.3 1. ]]
# [[1. 1.]]
# [[2. 1.]]
if classLabels[index] > 0:
plt.plot(data[0,0],data[0,1],'or')
else:
plt.plot(data[0,0],data[0,1],'ob')
plt.show()
#基于单层的决策树AdaBoost训练函数 numIt指的迭代的次数
def adaBoost(dataArr,classLabels,numIt = 40):
weakClassArr = [] #保存每次迭代器的信息
m = shape(dataArr)[0]
D = mat(ones((m,1))/float(m)) #初始化权重
aggClassESt = mat(zeros((m,1))) #累计每次分类的结果
for i in range(numIt):
bestStump,error,classEst = buildStump(dataArr,classLabels,D)
alpha = float(0.5*log((1 - error)/max(error,1e-16))) #函数的权重
bestStump['alpha'] = alpha #记录权重
weakClassArr.append(bestStump) #保存每一轮的结果信息
#更新权重
expon = multiply(-1 * alpha * mat(classLabels).T, classEst) # 计算指数
D = multiply(D, exp(expon))
D = D / D.sum() # 归一化
#累计每个函数的预测值 (权重 * 预测的类)
aggClassESt += alpha *classEst
errorRate = 1.0 * sum(sign(aggClassESt) != mat(classLabels).T)/m #预测的和真实的标签不应样的个数/总的个数
if errorRate == 0.0:
break #如果提前全部分类真确,则提前停止循环
return weakClassArr
#分类
def adaClassify(datatoClass,classifierArr):#大分类的数据,训练好的分类器
dataMatrix = mat(datatoClass)
m = shape(dataMatrix)[0]
aggClassEst = mat(zeros((m,1))) #保存预测的值 m个数据m个预测值
for i in range(len(classifierArr)): #循环遍历所有的分类器
classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],
classifierArr[i]['thred'],
classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha'] * classEst #第i个分类器的预测值*他的权重
return sign(aggClassEst)
if __name__=='__main__':
dataSet,classLabels = loadData()
weakClassArr = adaBoost(dataSet,classLabels)
data = [
[2.,1.1],
[1.3,1.],
[1.,1.],
[2.,1.]]
ada = adaClassify(data,weakClassArr)
print(ada)
关键点:每个单层的决策树,遍历每个属性,在每个属性上遍历不同的阈值,在每个阈值上确定符号(是大于为-1还是小于为-1)求解某个特征上,某个阈值,某个符号最小的分类器,因为为单层决策树,所以智能选择一个属性进行划分,就看那个属性上划分的分类错误最小,就在那个划分,所有遍历属性,