Python算法总结(七)Adaboost(附手写python实现代码)

注:adaboost可以做分类也可以做回归,本篇以构建二分类模型为例,通过手写代码,加深对算法原理与流程的理解。

一、算法类型

有监督的分类算法

二、算法原理

- 分类器的错误率:
在这里插入图片描述
- 弱分类器的权重:
在这里插入图片描述
注:错误率越高,该分类器的权重越小
- 正确分类的样本权重:
在这里插入图片描述
- 错误分类的样本权重:
在这里插入图片描述
注:初始化样本权重是相等的;如果该样本被错误分类,则在下一轮该样本的权重被提高

三、手写Python算法

def classify(xmat,i,threshold,mark):
    '''
    函数功能:单层决策树分类函数
    参数说明:
        xmat:特征矩阵
        i:第i个特征
        threshold:切分点的特征值
        mark:标志,取值'less_than(含相当)'或'greater_than'
    返回:
        label:二分类结果,暂用1和-1表示,这样做有两个好处,详见下面。
    '''
    label=np.ones((xmat.shape[0],1))
    if mark=='less_than':
        label[xmat[:,i] <= threshold]=-1  #注:不能是0。
    else:
        label[xmat[:,i] > threshold]=-1
    return label
def best_tree_stump(xmat,ymat,W):
    '''
    函数功能:寻找最佳的单层决策树
    参数说明:
        xmat:特征矩阵
        ymat:标签矩阵
        W:样本权重
    返回:
        beststump:最佳单层决策树,字典格式
        minE:最小误差
        bestlabel:最佳的分类结果
    '''
    N,M=xmat.shape
    steps=10 #初始化步数
    beststump={}
    bestlabel=np.mat(np.zeros((N,1)))
    minE=np.inf #初始化为正无穷大
    
    #遍历每个特征
    for i in range(M):
        min_value=xmat[:,i].min()
        max_value=xmat[:,i].max()
        stepsize=(max_value-min_value)/steps #计算步长
        for j in range(-1,int(steps)+1):
            for mark in ['less_than','greater_than']:
                threshold=(min_value+j*stepsize)
                label=classify(xmat,i,threshold,mark)
                error=np.mat(np.ones((N,1))) #初始化误差矩阵
                error[label==ymat]=0 #分类正确,则误差为零
                sum_error=W.T * error #计算总误差值
                
                if sum_error < minE:
                    minE=sum_error
                    bestlabel=label.copy()
                    beststump['feature_index']=i
                    beststump['feature_value_threshold']=threshold
                    beststump['feature_mark']=mark
    return beststump,minE,bestlabel            
def adaboost_train(xmat,ymat,max_iter=50):
    '''
    函数功能:生成各弱分类器及其决策权重
    返回:
        weakclassify:弱分类器集,列表格式
        pre_weighted_label:类别预测值
    '''
    N,M=xmat.shape
    W=np.mat(np.ones((N,1)))/N        #初始化
    pre_weighted_label=np.mat(np.zeros((N,1))) #初始化
    weakclassify=[]
    for i in range(max_iter):
        stump,err,label=best_tree_stump(xmat,ymat,W)
        alpha=float( np.log((1-err) / max(err,1e-16))/2 ) #第i个弱分类的权重
        stump['alpha']=np.round(alpha,2)
        
        weakclassify.append(stump)
        
        #更新权重
        expon=np.multiply(-1* alpha * ymat,label) #正确分类,取负alpha,错误分类,取正alpha。(好处一,方便求取正负alpha)
        W=np.multiply(W,np.exp(expon))
        W=W/ W.sum()
        
        pre_weighted_label += alpha*label
        
        #计算误差
        aggErr=np.multiply(np.sign(pre_weighted_label)!=ymat,np.ones((N,1))) 
        errRate=aggErr.sum()/N
        if errRate==0:break #误差为零,退出循环
            
    return weakclassify,pre_weighted_label
 def adaboostclassify(newdataset,weakclassify):
    '''
    函数功能:二分类预测
    参数说明:
        newdataset:未知样本
        weakclassify:已训练好的分类器
    返回:分类标签
    '''
    newdatamat=np.mat(newdataset)
    N=newdatamat.shape[0]
    pre_weighted_label=np.mat(np.zeros((N,1)))
    
    #遍历所有分类器
    for i in range(len(weakclassify)):
        classest=classify(newdatamat,weakclassify[i]['feature_index'],weakclassify[i]['feature_value_threshold'],weakclassify[i]['feature_mark'])
        pre_weighted_label +=classest*weakclassify[i]['alpha'] #(好处2,方便直接求决策权重)
        return np.sign(pre_weighted_label) # 大于零,说明预测为1的权重之和,大于预测为-1的权重之和,则返回1;小于零,则返回0.   

四、Python调包实现

from sklearn.ensemble import AdaBoostClassifier   
from sklearn.ensemble import AdaBoostRegressor

五、附调用手写函数

Python算法总结(七)Adaboost(附手写python实现代码)_第1张图片
Python算法总结(七)Adaboost(附手写python实现代码)_第2张图片
Python算法总结(七)Adaboost(附手写python实现代码)_第3张图片
Python算法总结(七)Adaboost(附手写python实现代码)_第4张图片

参考:http://edu.cda.cn/course/966

你可能感兴趣的:(Python)