1、一般流程
1)收集数据:可以使用任意方法
2)准备数据:依赖于所使用 的弱分类器类型,本次使用单层决策树,这种分类器可以处理任何数据类型。当然也可以使用
任意分类器作为弱分类器。作为若分类器,简单分类器的效果更好。
3)分析数据:任何方法
4)训练算法: AdaBoost的大部分时间都用在训练上,分类器将多次在同一数据集上训练弱分类器
5)测试算法:计算分类器的错误率
6)使用算法:同SVM一样,AdaBoost预测两个类别中的一个。如果想把它应用到多个分类,需要修正
2、AdaBoost优缺点
优点:泛化错误率低,易于编码,可以应用在大部分分类器上, 无参数调整
缺点:对离群点敏感
适用数据类型: 数值型和标称型数据
该算法在之前文章中实现过一次,是针对《统计学习方法》的一个例题实现的,更加的贴近数学公式,详见Python__Adaboost简单实现
3、算法实现
算法的核心是: 是基于错误率迭代,增加错误分类的权重,加重优分类器的权重。
-
算法总共分为三块:
-
1、弱分类器构建
2、弱分类器分类及错误率计算
3、AdaBoost算法迭代实现分类
出来结果为各个弱分类器,最终分类还需要构建一个整合分类器进行最后分类输出
1、弱分类器构建
import numpy as np
import copy
def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
# 通过阈值对 数据进行比较
retArray = np.ones((np.shape(dataMatrix)[0], 1))
if threshIneq == 'lt': #如果小于 little than
retArray[dataMatrix[:, dimen] <= threshVal] = -1.0
else:
retArray[dataMatrix[:, dimen] > threshVal] = -1.0
return retArray
2、弱分类器分类及错误率计算
def buildStump(dataArr, classLabels, D):
# 单层决策树,遍历每个特征找到错误率最小的特征
data_in = np.mat(dataArr)
label = np.mat(classLabels).T
m, n = np.shape(data_in)
numstep = 10.0
beststump = {}
best_clasest = np.mat(np.zeros((m, 1))) # 变成列
minErro = np.inf
for i in range(n): # 列(特征)遍历
col_min, col_max = data_in[:, i].min(), data_in[:, i].max()
step_size = (col_max - col_min) / numstep
for j in range(-1, np.int(numstep) + 1): # 阈值区间
for compare in ['lt', 'gt']:
threshVal = (col_min + np.float(j) * step_size) # 阈值
predictedVals = stumpClassify(data_in, i, threshVal, compare)
errArr = np.mat(np.ones((m, 1)))
errArr[predictedVals == label] = 0
weight_Error = D.T * errArr ## 更新错误的权重 adaboost中
#print('特征 %d, 阈值 %.2f, 阈值上下: %s, 错误率: %.3f' %(i, threshVal, compare, weight_Error))
if weight_Error < minErro:
minErro = weight_Error
best_clasest = copy.deepcopy(predictedVals)
beststump['dim'] = i
beststump['thresh'] = threshVal
beststump['ineq'] = compare
return beststump, minErro, best_clasest
3、AdaBoost算法迭代实现分类
def Adaboost_DC(dataArr, classLabels, numIt = 40):
# 弱分类器集
week_class_arr = []
# 初始分布
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):
best_stump, error, ClassEst = buildStump(dataArr, classLabels, D)
# 分类器权重
alpha = np.float(0.5 *np.log((1 - error) / max(error, 1e-16) ))
best_stump['alpha'] = alpha
week_class_arr.append(best_stump)
# 下一次的分布
## 增大错误样本权重
expon = np.multiply(-1 * alpha * np.mat(classLabels).T, ClassEst) # 对应位置相乘
D = np.multiply(D, np.exp(expon))
aggClassEst += alpha * ClassEst
#print('叠加分类结果',aggClassEst.T)
aggErrors = (np.sign(aggClassEst) != np.mat(classLabels).T )* 1
errorRate = aggErrors.sum() / m
print('总错误率:' , errorRate,'\n')
if errorRate == 0.0 :
break
return week_class_arr, aggClassEst
4、输出分类结果
def Ada_classify(datToClass, classifierArr):
# 分类函数
data_in = np.mat(datToClass)
m = np.shape(data_in)[0]
aggClassEst = np.mat(np.zeros((m, 1)))
for i in range(len(classifierArr)):
classEst = stumpClassify(data_in, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha'] * classEst
#print(aggClassEst)
return np.sign(aggClassEst)
4、算法应用
由于算法原因需要指定的数据结构,所以需要函数得到指定的数据结构
import os
import pandas as pd
def get_data(fil):
data_all = pd.read_csv(fil, sep = '\t', header = None )
m = data_all.shape[1]
data_out = np.array(data_all.iloc[:, list(range(0, m - 1))])
return data_out, list(data_all.iloc[:, -1])
预测与简单评估
fil_root = 'C:/Users/---/Desktop/l/'
file_name = 'horseColicTraining2.txt'
fil = os.path.join(fil_root, file_name)
file_name1 = 'horseColicTest2.txt'
fil1 = os.path.join(fil_root, file_name1)
if __name__ == '__main__':
# train
data, label = get_data(fil)
classifierArr,aggClassEst = Adaboost_DC(data, label, 100)
# 测试
data_t, label_t = get_data(fil1)
prd = Ada_classify(data_t, classifierArr)
print("错误个数:",sum(prd != np.mat(label_t).T),'\n错误率:', sum(prd != np.mat(label_t).T)/len(prd))
5、ROC曲线绘制
import matplotlib.pyplot as plt
plt.style.use('ggplot')
def plotROC(predStrengths, classLabels):
cur = (1.0, 1.0)
y_sum = 0
pos_sum = sum(np.array(classLabels) == 1)
y_sp = 1 / pos_sum
x_sp = 1 / (len(classLabels) - pos_sum)
sort_index = np.array(predStrengths).flatten().argsort()
ax = plt.subplot(111)
for i in sort_index.tolist():
if classLabels[i] == 1:
del_x = 0
del_y = y_sp
else:
del_x = x_sp
del_y = 0
y_sum += cur[1]
ax.plot([cur[0], cur[0] - del_x], [cur[1], cur[1] - del_y], c = 'b')
cur = (cur[0] - del_x, cur[1] - del_y)
ax.plot([0, 1], [0, 1], 'b--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC curve: The AUC is %.2f'%(y_sum * x_sp)) # 积分
ax.axis([-0.01, 1.01, 0, 1.01])
plt.show()
plotROC(aggClassEst, label)