机器学习全解 - 集成学习&Adaboost(含算法讲解,公式全解,手写代码实现,调包实现)

1. 集成学习

1.1 集成学习的概念

集成学习(Ensemble learning)就是将若干个弱分类器通过一定的策略组合之后产生一个强分类器。 弱分类器(Weak Classifier)指的就是那些分类准确率只比随机猜测略好一点的分类器,而强分类器( Strong Classifier)的分类准确率会高很多。这里的"强"&"弱"是相对的。弱分类器又被称 为“基分类器”。

通俗来讲就是三个臭皮匠 胜过诸葛亮,构建若干个模型,再将这些模型组合就是集成学习需要做的事。

1.2 bagging

是一种根据均匀概率分布从数据集中重复抽样的技术。每个新数据集大小相等。由于新数据集中的每个样本都是从 原始数据集中有放回的随机抽样出来的,所以新数据集中可能有重复的值,而原始数据集中的某些样本可能根本就没出现在新数据集中。

比方高中数学所学概率论,抽小球再放回,假设抽了10次,那么这10个球作为一个训练样本参与模型的构建。不断重复以上过程,最后得到n个训练样本,n个训练样本得到n个模型,这些模型我们就称之为“弱分类器”;

使用这些模型时,我们将n个训练样本投喂我们的测试样本,然后根据每个弱分类器返回的结果,我们可以采用一定的组合策略得到我们最后需要的强分类器。

其中的代表算法就是我们老生常谈的随机森林了。

1.3 boosting

boosting与bagging有部分异曲同工之妙。

boosting是先有n种弱分类器,是一个迭代算法,我们不断改变训练样本数据的权重去训练不同的弱分类器,最后再通过组合策略得到强分类器。

boosting中每个弱分类器用得到都是同一个训练样本,只是权重不同。当一个弱分类器获得训练样本投喂后,将会自动调整训练样本权重,然后带权重的训练样本再去投喂下一个弱分类器。不断迭代,最后集成得到强分类器。

2. 选择方式

2.1 平均法

对于预测数值的模型而言,平均法是最常见的,各个基分类器所预测的数值加总求平均得到最后的预测数值。

2.2 投票法

对于分类问题,最常用的是投票法,如同现实生活一般,每个基分类器预测出的类别进行投票,少数服从多数。

3. Adaboost算法流程

3.1 计算样本权重

赋予训练集中每个样本一个权重,构成权重向量D,将权重向量D初始化相等值。设定我们有m个样本,每个样本的权重都相等,则权重为:

3.2 计算错误率

错误率=(分类错误的样本数量 / 样本总数量)* 样本的权重

之前就已经被错误分类的样本权重更大

3.3 计算弱分类器权重

为当前分类器赋予权重值alpha,则alpha计算公式为:

3.4 调整权重值

根据上一次的训练结果,我们需要对样本的权重进行更新,被分类错误的样本权重增大,使得新的基分类器能够更好的去识别

-根据当前弱分类器的表现更新每个样本的权重,如果样本被错误分类,权重就会增加,如果正确分类,权重就会减小。

3.5 归一化权重

为了确保在下一轮迭代形成有效的概率分布,需要将权重归一化,使所有的权重总和为1.

3.6 迭代

设置迭代次数或者迭代结束条件,将强分类器生成。

举例说明

假设有4个样本,初始权重各为0.25,经过一轮训练后,弱分类器的错误率为0.3

1. 计算分类器权重:

2. 更新权重

3. 归一化权重

这样不断调整样本权重,使得后续的弱分类器能够更多的关注被前一轮分类错误的样本,从而提高模型的整体性能。

4. 手写代码实现

首先为了打比方,我们先构建基分类器:

#单层决策树生成函数
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq): #把这个函数当作两个分类器
    #dimen为datamat的列索引值,threshVal为阈值对比方式
    retArray = np.ones((np.shape(dataMatrix)[0],1))
    if threshIneq == 'lt': #lt代表小于
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = 1.0
    return retArray

构建一个函数,获得在目前权重样本下最后基分类器以及对应的权重错误率:

def buildStump(dataArr,classLabels,D):
    dataMatrix = np.mat(dataArr);labelMat = np.mat(classLabels).T
    m,n = np.shape(dataMatrix)
    numSteps = 10.0
    bestStump = {} #存储最佳决策树
    bestClasEst = np.mat(np.zeros((m,1)))
    minError = 1000
    for i in range(n): #遍历每个特征 相当于要找出那个分类器最好的分类特征
        rangeMin = dataMatrix[:,i].min();rangeMax = dataMatrix[:,i].max()
        for j in range(-1,int(numSteps)+1):
            for inequal in ['lt','gt']: #不同阈值方式进行比较 相当于遍历不同的分类器
                threshVal = (rangeMin + rangeMax)/numSteps
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
                errArr = np.mat(np.ones((m,1))) #错误
                errArr[predictedVals == labelMat] = 0 #没错的记为0
                weightedError = D.T * errArr #计算加权错误
                print(weightedError)
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i #最好的分类维度
                    bestStump['thresh'] = threshVal #最好的分类阈值
                    bestStump['ineq'] = inequal #最好的过滤方式
    return bestStump,minError,bestClasEst #返回最好的分类器,特征

不断迭代基分类器,获得强分类器:

#基于单层决策树的AdaBoost训练
def adaBoostTrainsDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    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): #迭代多少次 40次基分类器
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        print(D)
        alpha = float(0.5*np.log((1.0-error)/max(error,1e-16)))
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)
        expon = np.multiply(D,np.exp(expon))
        D = D/D.sum() #归一化处理
        aggClassEst += alpha*classEst #更新
        aggErrors = np.multiply(sign(aggClassEst) != np.mat(classLabels).T,np.ones((m,1)))
        errorRate = aggErrors.sum() / m #计算错误率
        if errorRate == 0.0:break
    return weakClassArr#返回分类器

调用我们最终的强分类器:

#调用AdaBoost分类函数
def adaClassify(datToClass,classifierArr):
    dataMatrix = np.mat(datToClass)
    m = np.shape(dataMatrix)[0]
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(len(classifierArr)): #根据分类器个数
        classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],classifierArr[i]['thresh'],classifierArr[i]['ineq'])
        aggClassEst += classifierArr[i]['alpha']*classEst #权重与结果想乘的和
    return sign(aggClassEst)

5. 调包实现

from sklearn.model_selection import train_test_split
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 数据切分
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)

# 初始化AdaBoost分类器
clf = AdaBoostClassifier(base_estimator=DecisionTreeClassifier(max_depth=1),
                         n_estimators=50,
                         learning_rate=1.0,
                         random_state=42)

# 训练模型
clf.fit(X_train, y_train)

# 预测
y_pred = clf.predict(X_test)

# 评估
accuracy = accuracy_score(y_test, y_pred)
print(f"Test Accuracy: {accuracy}")

6. Adaboost优点与局限性

6.1 优点

1. 提高分类性能:通过迭代调整样本权重,使分类器更关注那些难以分类的样本,从而提高整体分类准确率

2. 适应性强:Adaboost能够自适应地调整样本权重,以此聚焦难分类的样本

3. 无需特征选择:对特征的选择没有强烈的依赖,可以在不进行特征选择的情况下直接应用于原始数据

6.2 局限性

1. 模型解释性差:Adaboost是多个弱分类器的加权组合,这种模型的解释性差,不容易理解每个特征的具体贡献

2. 对弱分类器的依赖: Adaboost性能高度依赖于弱分类器的表现,如果错误率接近50%,其提升风险可能不明显

3. 对噪声敏感:由于在每次迭代中增加错误分类样本的权重,噪声数据对最终模型产生较大的影响

4. 计算成本高:算法需要进行多次迭代,每次迭代都会重新训练一个弱分类器,这在处理大规模数据集时可能会导致较高的计算成本

7. 应用前景

1. 图像分类与识别:

-人脸识别:将弱分类器组合为强分类器,能够有效识别人脸特征

-目标检测:在计算机视觉中, 可以用于检测和识别各种目标

2. 网络安全:

-入侵检测:通过组合多个简单的特征分类器来检测异常网络和入侵行为

-恶意软件检测

3. 自动驾驶与智能交通:

交通流量预测:提供更加准确的交通管理决策

4. 自然语言处理:

文本分类:如垃圾邮件过滤,情感分析,主题分类等

信息检索:在信息检索系统中,Adaboost可以用于提高文档的相关性排序性能,帮助更准确地检索用户所需信息

8. 参考资料

机器学习算法: AdaBoost 详解 - 知乎

《机器学习实战》

  • 33
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以通过以下代码实现不使用机器学习的Adaboost算法的Python实现: ``` import numpy as np # 生成训练数据 def getData(): X = np.array([ [-1, -1], [-1, 1], [1, -1], [1, 1] ]) y = np.array([1, 1, -1, -1]) return X, y # 实现Adaboost算法 def Adaboost(X, y, T): n_samples, n_features = X.shape w = np.ones(n_samples) / n_samples models = [] for t in range(T): # 训练弱分类器 model = {'feature': None, 'threshold': None, 'alpha': None} min_error = float('inf') for f in range(n_features): feature_vals = np.unique(X[:, f]) for threshold in feature_vals: predicted = np.ones(n_samples) predicted[X[:, f] < threshold] = -1 error = np.sum(w[y != predicted]) if error < min_error: min_error = error model['feature'] = f model['threshold'] = threshold model['alpha'] = 0.5 * np.log((1 - min_error) / min_error) # 更新权重和模型 predicted = np.ones(n_samples) predicted[X[:, model['feature']] < model['threshold']] = -1 w *= np.exp(-model['alpha'] * y * predicted) w /= np.sum(w) models.append(model) return models # 对测试数据进行预测 def predict(X_test, models): n_samples = X_test.shape[0] y_pred = np.zeros(n_samples) for model in models: predicted = np.ones(n_samples) predicted[X_test[:, model['feature']] < model['threshold']] = -1 y_pred += model['alpha'] * predicted y_pred = np.sign(y_pred) return y_pred # 测试 X_train, y_train = getData() models = Adaboost(X_train, y_train, T=3) X_test = np.array([[-1, -1], [-1, 1], [1, -1], [1, 1]]) y_pred = predict(X_test, models) print(y_pred) ``` 注意,这只是一个简单的Adaboost实现,仅供参考。在实际应用中,我们通常会使用机器学习中已经实现好的Adaboost算法,以获得更好的性能和更广泛的应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值