美文网首页
《机器学习实战》Adaboost算法中buildstump函数的

《机器学习实战》Adaboost算法中buildstump函数的

作者: 白日梦蓝_ | 来源:发表于2019-12-15 14:10 被阅读0次

    学习《机器学习实战》Adaboost算法时,发现书中对build_stump函数的讲解非常笼统,理解起来有难度,而这个函数又是理解后面完整Adaboost算法的重点与基础,因此写此文详细阐述我对buildstump函数的理解

    相关代码详解

    单层决策树分类函数stump_classify

    def stump_classify(data_mat, dimen, thresh_val, thresh_ineq):
        """
        :param data_mat: Mat据集
        :param dimen: 特征的哪一个列
        :param thresh_val: 特征列要比较的值
        :param thresh_ineq: 分类标志
        :return: np.array
        """
        ret_array = np.ones((np.shape(data_mat)[0], 1))  #将分类向量的值先全部初始化为1
    
        if thresh_ineq == 'lt':   #若标志为"lt"则把小于阈值的点判定为"-1"类,否则把大于阈值的点判定为"-1"类
            ret_array[data_mat[:, dimen] <= thresh_val] = -1.0      # data_mat[:, dimen] 表示数据集中第dimen列的所有值
        else:
            ret_array[data_mat[:, dimen] > thresh_val] = -1.0
        return ret_array
    

    建立单层决策树的弱分类器函数buildstump

    def buildstump(data_arr, class_labels, D):
        """
        :param data_arr: 特征标签集合
        :param class_labels: 分类标签集合
        :param D: 最初的特征权重值
        :return: bestStump    最优的分类器模型
                 min_error     错误率
                 best_class_est  训练后的结果集
        """
        data_mat = np.mat(data_arr)   #将导入的数据集转化为矩阵
        label_mat = np.mat(class_labels).T  #将导入的标签转化为行向量
        m, n = np.shape(data_mat)  #得到数据集的个数与特征数
        num_steps = 10.0   #设置遍历完整个数据要走的步数
        best_stump = {}    #建立最优单层决策树的特征列列表
        best_class_est = np.mat(np.zeros((m, 1)))   #建立一个初始值全为1的分类列表
        min_err = np.inf      # 无穷大
        
        for i in range(n):   #第一层循环,对数据集中每一个特征(每一列)
            range_min = data_mat[:, i].min()
            range_max = data_mat[:, i].max()
            step_size = (range_max - range_min) / num_steps  #得出该特征下最大值与最小值的差,除以步数以后即为每一步的距离
            for j in range(-1, int(num_steps) + 1):   #第二层循环,即对每一步的跨度,下面的图可以很好的说明,也就是垂直于X轴的一条条直线
    
                for inequal in ['lt', 'gt']:   #这里太长,见下<1>
                    thresh_val = (range_min + float(j) * step_size)  #计算阈值,即为划分轴在x轴上的值
                    predicted_vals = stump_classify(data_mat, i, thresh_val, inequal)  #带入stump_classify函数 得到返回的分类列表
                    err_arr = np.mat(np.ones((m, 1)))   #先将错误向量的值全部初始化为1
                    err_arr[predicted_vals == label_mat] = 0  #若得到的分类列表的值与训练集的类标签值一直,则设置为0
                    
                    weighted_err = D.T * err_arr   #这里太长,见下<2>
                    print("split:第%d列,阈值:%.2f,标志:%s,错误率:%.3f"%(i,thresh_val,inequal,weighted_err))
                    if weighted_err < min_err:    #这里就简单了,找到错误率最小的那个步长所代表的分割轴,并将得到最好分类树的结果存进列表
                        min_err = weighted_err
                        best_class_est = predicted_vals.copy()
                        best_stump['dim'] = i
                        best_stump['thresh'] = thresh_val
                        best_stump['ineq'] = inequal
        # best_stump 表示分类器的结果,在第几个列上,用大于/小于比较,阈值是多少 (单个弱分类器)
        print("最优分类器为%s\n最小错误率为:%.6f\n最优分类结果为\n%s"%(best_stump, min_err, best_class_est))
        return best_stump, min_err, best_class_est
    
    

    <1>第三层循环,这里书上说是对每个不等号,太难懂了,其实这里lt的意思是less tan少于,gt的意思是great than 多于,也就是在当前步长的划分下,分别对数据进行"lt"和"gt"的标示,然后将数据集带入stum_classify进行错误测试,lt表示把小于阈值的点判成是"-1"类,gt标示把大于阈值的点判成"-1"类,逐一对比在同一个步长的划分下,哪种标示方法的错误率低

    <2>这里是矩阵乘法,要重点说明一下,这个乘法得到的是一个具体的数值,即错误率,例如,当数据集有4行时,因为D=[1/4,1/4,1/4,1/4],若在当前的步长与标志下,err_arr中前3个判定值是正确的,即err_arr=[0,0,0,1],计算得weighted_err=1/4,正好是:判错数目/总样本数,现在能体会到上面设置为1或0的巧妙了吧?另外,weighted_err也是与Adaboost分类器交互的地方,利用它计算每个弱分类器的α值,从而进一步更新特征权重矩阵D,在原有的基础上得到更准确的D,该部分内容可以参考书P117页的讲解,还是比较好理解的

    理解了上面的注解后,接下来我们跑一下函数

    1.导入数据
    import adaboost
    datMat,classLabels=adaboost.load_sim_data()

    在这里插入图片描述
    2.给特征权重D赋初始值
    D = mat(ones( (5,1) / ) 5 )
    3.加载buidstump函数
    adaboost.buidstump(datMat,classLebels,D)
    分别打印每一循环遍历得到的分类器结果,最后打印出最优结果
    利用图讲接树桩分类器的构建过程,再加深一下大家的理解.
    image

    如上图,biuldstump其实就是在构建一个单决策树的弱分类器,之所以弱, 是因为你找不到任何一种单层决策树(其实就是与坐标轴平行的分割线)能将数据完全正确的分割开来,在构建过程中,通过对每个特征下的数值,以一定的步长进行遍历(取决于你设置的步数),其实就相当于上图黄线逐渐向右移动,对比移动到哪个位置的时候错误率最低,于是就能得到该数据集下的最优单层决策树,理解了这些,在此基础上,利用错误率计算出→α,再用α计算出新的特征权重矩阵D→D,最后,利用这几次得到几个弱分类器集合,就能得到不错的分类结果了。

    最后,Adboost实战代码参考

    相关文章

      网友评论

          本文标题:《机器学习实战》Adaboost算法中buildstump函数的

          本文链接:https://www.haomeiwen.com/subject/ofgknctx.html