mirror of
https://github.com/apachecn/ailearning.git
synced 2026-05-08 23:12:06 +08:00
更新 AdaBoost 的项目内容
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
|
||||

|
||||
|
||||
### 项目实战: 随机森林
|
||||
### 项目案例: 随机森林
|
||||
|
||||

|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
* 适用数据类型:数值型和标称型数据。
|
||||
```
|
||||
|
||||
### 项目实战: 马疝病的预测
|
||||
### 项目案例: 马疝病的预测
|
||||
|
||||
> 项目流程图
|
||||
|
||||
@@ -111,6 +111,111 @@
|
||||
基于单层决策树构建弱分类器
|
||||
* 单层决策树(decision stump, 也称决策树桩)是一种简单的决策树。
|
||||
|
||||
#### 项目概述
|
||||
|
||||
预测患有疝气病的马的存活问题,这里的数据包括368个样本和28个特征,疝气病是描述马胃肠痛的术语,然而,这种病并不一定源自马的胃肠问题,其他问题也可能引发疝气病,该数据集中包含了医院检测马疝气病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外,除了部分指标主观和难以测量之外,该数据还存在一个问题,数据集中有30%的值是缺失的。
|
||||
|
||||
#### 开发流程
|
||||
|
||||
```
|
||||
收集数据:提供的文本文件。
|
||||
准备数据:确保类别标签是+1和-1,而非1和0。
|
||||
分析数据:手工检查数据。
|
||||
训练数据:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器。
|
||||
测试数据:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对 AdaBoost 和 Logistic 回归的结果进行完全对等的比较。
|
||||
使用算法:观察该例子上的错误率。不过,也可以构建一个 Web 网站,让驯马师输入马的症状然后预测马是否会死去。
|
||||
```
|
||||
|
||||
> 收集数据:提供的文本文件。
|
||||
|
||||
训练数据:horseColicTraining.txt
|
||||
测试数据:horseColicTest.txt
|
||||
|
||||
```
|
||||
2.000000 1.000000 38.500000 66.000000 28.000000 3.000000 3.000000 0.000000 2.000000 5.000000 4.000000 4.000000 0.000000 0.000000 0.000000 3.000000 5.000000 45.000000 8.400000 0.000000 0.000000 -1.000000
|
||||
1.000000 1.000000 39.200000 88.000000 20.000000 0.000000 0.000000 4.000000 1.000000 3.000000 4.000000 2.000000 0.000000 0.000000 0.000000 4.000000 2.000000 50.000000 85.000000 2.000000 2.000000 -1.000000
|
||||
2.000000 1.000000 38.300000 40.000000 24.000000 1.000000 1.000000 3.000000 1.000000 3.000000 3.000000 1.000000 0.000000 0.000000 0.000000 1.000000 1.000000 33.000000 6.700000 0.000000 0.000000 1.000000
|
||||
```
|
||||
|
||||
> 准备数据:确保类别标签是+1和-1,而非1和0。
|
||||
|
||||
```python
|
||||
def loadDataSet(fileName):
|
||||
# 获取 feature 的数量, 便于获取
|
||||
numFeat = len(open(fileName).readline().split('\t'))
|
||||
dataArr = []
|
||||
labelArr = []
|
||||
fr = open(fileName)
|
||||
for line in fr.readlines():
|
||||
lineArr = []
|
||||
curLine = line.strip().split('\t')
|
||||
for i in range(numFeat-1):
|
||||
lineArr.append(float(curLine[i]))
|
||||
dataArr.append(lineArr)
|
||||
labelArr.append(float(curLine[-1]))
|
||||
return dataArr, labelArr
|
||||
```
|
||||
|
||||
> 分析数据:手工检查数据。
|
||||
|
||||
过拟合(overfitting, 也称为过学习)
|
||||
* 发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。
|
||||
|
||||

|
||||
|
||||
> 训练数据:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器。
|
||||
|
||||
```python
|
||||
def adaBoostTrainDS(dataArr, labelArr, numIt=40):
|
||||
"""adaBoostTrainDS(adaBoost训练过程放大)
|
||||
Args:
|
||||
dataArr 特征标签集合
|
||||
labelArr 分类标签集合
|
||||
numIt 实例数
|
||||
Returns:
|
||||
weakClassArr 弱分类器的集合
|
||||
aggClassEst 预测的分类结果值
|
||||
"""
|
||||
weakClassArr = []
|
||||
m = shape(dataArr)[0]
|
||||
# 初始化 D,设置每个特征的权重值,平均分为m份
|
||||
D = mat(ones((m, 1))/m)
|
||||
aggClassEst = mat(zeros((m, 1)))
|
||||
for i in range(numIt):
|
||||
# 得到决策树的模型
|
||||
bestStump, error, classEst = buildStump(dataArr, labelArr, D)
|
||||
|
||||
# alpha目的主要是计算每一个分类器实例的权重(组合就是分类结果)
|
||||
# 计算每个分类器的alpha权重值
|
||||
alpha = float(0.5*log((1.0-error)/max(error, 1e-16)))
|
||||
bestStump['alpha'] = alpha
|
||||
# store Stump Params in Array
|
||||
weakClassArr.append(bestStump)
|
||||
|
||||
print "alpha=%s, classEst=%s, bestStump=%s, error=%s " % (alpha, classEst.T, bestStump, error)
|
||||
# -1主要是下面求e的-alpha次方; 如果判断正确,乘积为1,否则成绩为-1,这样就可以算出分类的情况了
|
||||
expon = multiply(-1*alpha*mat(labelArr).T, classEst)
|
||||
# 判断正确的,就乘以-1,否则就乘以1, 为什么? 书上的公式。
|
||||
print '(-1取反)预测值expon=', expon.T
|
||||
# 计算e的expon次方,然后计算得到一个综合的概率的值
|
||||
# 结果发现: 判断错误的特征,D对于的特征的权重值会变大。
|
||||
D = multiply(D, exp(expon))
|
||||
D = D/D.sum()
|
||||
|
||||
# 预测的分类结果值,在上一轮结果的基础上,进行加和操作
|
||||
print '当前的分类结果:', alpha*classEst.T
|
||||
aggClassEst += alpha*classEst
|
||||
print "叠加后的分类结果aggClassEst: ", aggClassEst.T
|
||||
# sign 判断正为1, 0为0, 负为-1,通过最终加和的权重值,判断符号。
|
||||
# 结果为:错误的样本标签集合,因为是 !=,那么结果就是0 正, 1 负
|
||||
aggErrors = multiply(sign(aggClassEst) != mat(labelArr).T, ones((m, 1)))
|
||||
errorRate = aggErrors.sum()/m
|
||||
# print "total error=%s " % (errorRate)
|
||||
if errorRate == 0.0:
|
||||
break
|
||||
return weakClassArr, aggClassEst
|
||||
```
|
||||
|
||||
```
|
||||
发现:
|
||||
alpha 目的主要是计算每一个分类器实例的权重(组合就是分类结果)
|
||||
@@ -121,13 +226,54 @@ D 的目的是为了计算错误概率: weightedError = D.T*errArr,求最佳
|
||||
|
||||

|
||||
|
||||
### 知识点补充
|
||||
> 测试数据:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对 AdaBoost 和 Logistic 回归的结果进行完全对等的比较。
|
||||
|
||||
> 过拟合(overfitting, 也称为过学习)
|
||||
```python
|
||||
def adaClassify(datToClass, classifierArr):
|
||||
"""adaClassify(ada分类测试)
|
||||
Args:
|
||||
datToClass 多个待分类的样例
|
||||
classifierArr 弱分类器的集合
|
||||
Returns:
|
||||
sign(aggClassEst) 分类结果
|
||||
"""
|
||||
# do stuff similar to last aggClassEst in adaBoostTrainDS
|
||||
dataMat = mat(datToClass)
|
||||
m = shape(dataMat)[0]
|
||||
aggClassEst = mat(zeros((m, 1)))
|
||||
|
||||
* 发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。
|
||||
# 循环 多个分类器
|
||||
for i in range(len(classifierArr)):
|
||||
# 前提: 我们已经知道了最佳的分类器的实例
|
||||
# 通过分类器来核算每一次的分类结果,然后通过alpha*每一次的结果 得到最后的权重加和的值。
|
||||
classEst = stumpClassify(dataMat, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
|
||||
aggClassEst += classifierArr[i]['alpha']*classEst
|
||||
return sign(aggClassEst)
|
||||
```
|
||||
|
||||
> 使用算法:观察该例子上的错误率。不过,也可以构建一个 Web 网站,让驯马师输入马的症状然后预测马是否会死去。
|
||||
|
||||
```python
|
||||
# 马疝病数据集
|
||||
# 训练集合
|
||||
dataArr, labelArr = loadDataSet("input/7.AdaBoost/horseColicTraining2.txt")
|
||||
weakClassArr, aggClassEst = adaBoostTrainDS(dataArr, labelArr, 40)
|
||||
print weakClassArr, '\n-----\n', aggClassEst.T
|
||||
# 计算ROC下面的AUC的面积大小
|
||||
plotROC(aggClassEst.T, labelArr)
|
||||
# 测试集合
|
||||
dataArrTest, labelArrTest = loadDataSet("input/7.AdaBoost/horseColicTest2.txt")
|
||||
m = shape(dataArrTest)[0]
|
||||
predicting10 = adaClassify(dataArrTest, weakClassArr)
|
||||
errArr = mat(ones((m, 1)))
|
||||
# 测试:计算总样本数,错误样本数,错误率
|
||||
print m, errArr[predicting10 != mat(labelArrTest).T].sum(), errArr[predicting10 != mat(labelArrTest).T].sum()/m
|
||||
```
|
||||
|
||||
[完整代码地址](https://github.com/apachecn/MachineLearning/blob/master/src/python/7.AdaBoost/adaboost.py): <https://github.com/apachecn/MachineLearning/blob/master/src/python/7.AdaBoost/adaboost.py>
|
||||
|
||||
#### 要点补充
|
||||
|
||||

|
||||
|
||||
> 非均衡现象:
|
||||
|
||||
|
||||
@@ -209,8 +209,8 @@ def plotROC(predStrengths, classLabels):
|
||||
predStrengths 最终预测结果的权重值
|
||||
classLabels 原始数据的分类结果集
|
||||
"""
|
||||
print 'predStrengths=', predStrengths
|
||||
print 'classLabels=', classLabels
|
||||
# print 'predStrengths=', predStrengths
|
||||
# print 'classLabels=', classLabels
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
# variable to calculate AUC
|
||||
@@ -225,7 +225,7 @@ def plotROC(predStrengths, classLabels):
|
||||
# get sorted index, it's reverse
|
||||
sortedIndicies = predStrengths.argsort()
|
||||
# 测试结果是否是从小到大排列
|
||||
print 'sortedIndicies=', sortedIndicies, predStrengths[0, 176], predStrengths.min(), predStrengths[0, 293], predStrengths.max()
|
||||
# print 'sortedIndicies=', sortedIndicies, predStrengths[0, 176], predStrengths.min(), predStrengths[0, 293], predStrengths.max()
|
||||
|
||||
# 开始创建模版对象
|
||||
fig = plt.figure()
|
||||
@@ -244,7 +244,7 @@ def plotROC(predStrengths, classLabels):
|
||||
ySum += cur[1]
|
||||
# draw line from cur to (cur[0]-delX, cur[1]-delY)
|
||||
# 画点连线 (x1, x2, y1, y2)
|
||||
print cur[0], cur[0]-delX, cur[1], cur[1]-delY
|
||||
# print cur[0], cur[0]-delX, cur[1], cur[1]-delY
|
||||
ax.plot([cur[0], cur[0]-delX], [cur[1], cur[1]-delY], c='b')
|
||||
cur = (cur[0]-delX, cur[1]-delY)
|
||||
# 画对角的虚线线
|
||||
|
||||
Reference in New Issue
Block a user