adaBoost

adaBoost是一种复杂模型,是将多个弱分类器组合在一起的模型,一般使用提升树来实现二分类问题

  • [ ] adaBoost的实现
  • 处理数据
# 处理数据
def loadDataset(fileName):
    """

    :param fileName: 文件路径
    :return: 数据集,标签集
    """
    dataMat = []
    labelMat = []
    featureNum = len(open(fileName).readline().split("\t"))
    file = open(fileName)
    for line in file.readlines():
        lineData = []
        curLine = line.strip().split("\t")
        for i in range(featureNum - 1):
            lineData.append(float(curLine[i]))
        dataMat.append(lineData)
        labelMat.append(float(curLine[-1]))
    return dataMat, labelMat

这里处理数据是将数据进行划分,前n-1项为特征,最后一项为标签。使用strip()函数消除空格并用split()函数进行分隔,==这里注意,数据的存储一定要置换为float形式,因为之后我们要使用矩阵进行计算,矩阵的计算必须使用flaot形式==

  • 对数据集进行分类
# 数据集进行分类
def stumpyClassify(dataMat, dimen, threshVal, threshIneq):
    """

    :param dataMat: 数据集
    :param dimen: 特征
    :param threshVal: 分类阈值
    :param threshIneq: 关于大于还是小于
    :return: classifyedResult:更新后的标签
    """
    classifyedResult = np.ones((np.shape(dataMat)[0], 1))  # 分类后的标签
    if threshIneq == "less_than":
        classifyedResult[dataMat[:, dimen] <= threshVal] = -1.0
    else:
        classifyedResult[dataMat[:, dimen] > threshVal] = -1.0
    return classifyedResult

这里通过阈值以及分类信息,将对应特征的数据进行分类

  • 建立单层决策树
# 单层决策树
def build_tree(dataMat, classLabels, D):
    """
    :param dataMat: 数据集
    :param classLabels: 标签集
    :param D: 权重
    :return: bestTree:最优决策树信息
             minError:最小误差和
             classifyResult:分类结果
    """
    dataMatrix = np.mat(dataMat)
    labelMatrix = np.mat(classLabels).T
    m, n = np.shape(dataMatrix)  # m为样本个数,n为特征个数
    bestTree = {}  # 最优决策树
    minError = np.inf  # 最小误差和
    classifyResult = np.mat(np.zeros((m, 1)))  # 分类后结果
    step = 10.0
    for i in range(n):
        rangeMin = dataMatrix[:, i].min()
        rangeMax = dataMatrix[:, i].max()
        stepSize = (rangeMax - rangeMin) / step
        for j in range(-1, int(step) + 1):
            for ineq in ["less_than", "greater_than"]:
                threshVal = (rangeMin + float(j) * stepSize)
                predictions = stumpyClassify(dataMatrix, i, threshVal, ineq)
                errorArr = np.mat(np.ones((m, 1)))
                errorArr[predictions == labelMatrix] = 0
                error = D.T * errorArr
                if error < minError:
                    classifyResult = predictions.copy()
                    minError = error
                    bestTree["dimen"] = i
                    bestTree["threshVal"] = threshVal
                    bestTree["ineq"] = ineq
    return bestTree, minError, classifyResult

这也是代码中较为重要的地方,这里我们由于使用提升树所以建立单层决策树,而其他的KNN等若分类器也可以拿来使用。这里分别对最优决策树的信息进行存储,找出弱分类器单层决策树的最小误差,返回最优决策树信息,最小误差以及分类后的标签

  • 对adaBoost进行训练
# 训练adaBoost
def train_adaBoost(dataMat, classLabel, numIt=50):
    """

    :param dataMat: 训练数据集
    :param classLabel:标签
    :param numIt:迭代次数(弱分类器个数)
    :return: weakClassEst:决策树桩
             aggClassEst:加权分类结果
    """
    weakClassEst = []  # 决策树桩
    m = np.shape(dataMat)[0]
    D = np.mat(np.ones((m, 1)) / m)
    aggClassEst = np.mat(np.zeros((m, 1)))
    for i in range(numIt):
        bestTree, error, classifyResult = build_tree(dataMat, classLabel, D)
        weakClassEst.append(bestTree)  # 将此弱分类器添加到树桩
        alpha = float(0.5 * math.log((1.0 - error) / max(error, 1e-16)))  # 计算出阿尔法值
        bestTree["alpha"] = alpha
        exponent = np.multiply(-1.0 * alpha * np.mat(classLabel).T, classifyResult)
        res = np.mat([math.exp(x) for x in exponent])
        D = np.multiply(D,res.T)
        D = D / D.sum()  # 更新训练数据集的权值分布
        aggClassEst += alpha * classifyResult  # 所有分类器加权分类的结果
        errorArr = np.multiply(np.sign(aggClassEst) != np.mat(classLabel).T, np.ones((m, 1)))
        errorRate = errorArr.sum() / m  # 所有分类器的误差
        if errorRate == 0.0:
            break
    return weakClassEst, aggClassEst

这里是代码的核心,是对adaBoost进行训练,首先根据建立最优单层决策树返回的最小误差计算出此弱分类器的权值alpha(阿尔法),然后计算e的指数函数来对数据集的权值进行更新,其中D.sum()对应规范化因子Zm,然后当所有分类器的误差率等于0时调出循环,返回最终模型以及加权预测分类结果

  • 使用提升树进行分类
# 使用提升树进行分类
def improve_tree(dataToClass, weakClassEst):
    """

    :param dataToClass: 待分类的数据
    :param weakClassEst: 最终的分类模型
    :return: 分类结果
    """
    dataMatrix = np.mat(dataToClass)
    m = np.shape(dataMatrix)[0]
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(len(weakClassEst)):
        predictions = stumpyClassify(dataMatrix, weakClassEst[i]["dimen"], weakClassEst[i]["threshVal"], weakClassEst[i]["ineq"])
        aggClassEst += weakClassEst[i]["alpha"] * predictions
    return np.sign(aggClassEst)

这部分就比较简单了,输入待分类的数据以及最终模型,根据存储在模型里的信息(主要是alpha值),对待分类结果进行加权分类,最终通过sign函数返回分类结果

  • 计算准确率和召回率
# 计算准确率以及召回率
def evaluate(predictions,classLabels):
    """
    :param predictions: 预测分类
    :param classLabels: 实际分类
    :return: 准确率,召回率
    """
    TP = 0.
    FP = 0.
    TN = 0.
    FN = 0.
    for i in range(len(predictions)):
        if classLabels[i] == 1.0:
            if np.sign(classLabels[i]) == predictions[i]:
                TP += 1.0
            else:
                FP += 1.0
        else:
            if np.sign(classLabels[i]) == predictions[i]:
                TN += 1
            else:
                FN += 1
    return TP / (TP + FP),TP / (TP + FN)

这里就是计算准确率和召回率了,比较简单不在多说

  • 主函数
def main():
    trainingData, trainingLabels = loadDataset(
        r"D:\Python Dataset\Machine-Learning-master\AdaBoost\horseColicTraining2.txt")
    testData, testLabels = loadDataset(r"D:\Python Dataset\Machine-Learning-master\AdaBoost\horseColicTest2.txt")
    model, aggClassEst = train_adaBoost(trainingData, trainingLabels, 50)
    print("The model is :  ", repr(model))
    trainingPredictions = improve_tree(trainingData, model)
    trainingError = np.mat(np.ones((len(trainingData), 1)))
    print("The training error rate is :  ", repr(
        float(trainingError[trainingPredictions != np.mat(trainingLabels).T].sum() / len(trainingPredictions)) * 100))
    print("The prTrain is :  ",repr(evaluate(trainingPredictions,trainingLabels)))
    testPredictions = improve_tree(testData, model)
    testError = np.mat(np.ones((len(testData), 1)))
    print("The test error rate is :  ",
          repr(float(testError[testPredictions != np.mat(testLabels).T].sum() / len(testPredictions)) * 100))
    print("The prTest is :  ",repr(evaluate(testPredictions,trainingLabels)))

Code到这里就结束了,最终run出的结果训练集错误率18%,测试集错误率20%,此时弱分类器为50个。经过测试,这时模型为最佳,低于50会有些欠拟合;高于50则会过拟合。最后,参考博文为

博客1

博客2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容