美文网首页
集成方法与随机森林简介

集成方法与随机森林简介

作者: 南太湖小蚂蚁 | 来源:发表于2023-12-05 16:03 被阅读0次

    集成方法的思想其实很好理解,简单来说就是构建很多个分类器,然后每个分类器分别预测,聚合每个分类器的预测结果,然后投票,将得票最多的结果作为预测类别。



    下面我们通过程序来实现一个投票分类器。首先构建多个分类器,然后把这些分类器合并在一起,组合成一个投票分类器。

    from sklearn.ensemble import VotingClassifier
    from sklearn.linear_model import LogisticRegression
    from sklearn.svm import SVC
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.datasets import load_iris
    
    iris = load_iris()
    X_train = iris.data[:140, 2:] # 长和宽
    y_train = iris.target[:140]
    X_test = iris.data[140:-1, 2:]
    y_test = iris.target[140:-1]
    
    log_clf = LogisticRegression() # 逻辑回归分类器
    svm_clf = SVC()
    # 支持向量机分类器
    tree_clf = DecisionTreeClassifier() # 决策树分类器
    voting_clf = VotingClassifier(estimators=[('lr',log_clf),('svm',svm_clf),('tree',tree_clf)], voting='hard') # 合并为一个分类器
    voting_clf.fit(X_train,y_train)
    
    from sklearn.metrics import accuracy_score
    
    for clf in (log_clf, svm_clf, tree_clf, voting_clf):
        clf.fit(X_train, y_train)
        y_pred = clf.predict(X_test)
        print(clf.__class__.__name__, accuracy_score(y_test, y_pred))
        
    # 输出:
    LogisticRegression 1.0
    SVC 1.0
    DecisionTreeClassifier 1.0
    VotingClassifier 1.0
    

    可能是因为鸢尾花数据集数据量比较小,所以输出的结果得分都是1.0。我们换成手写数字识别数据集再来看看。

    from sklearn import datasets
    digits = datasets.load_digits()
    x = digits['data']
    y = digits['target']
    
    X_train = x[:1600]
    y_train = y[:1600]
    X_test = x[1600:]
    y_test = y[1600:]
    
    for clf in (log_clf, svm_clf, tree_clf, voting_clf):
        clf.fit(X_train, y_train)
        y_pred = clf.predict(X_test)
        print(clf.__class__.__name__, accuracy_score(y_test, y_pred))
        
    # 输出:
    LogisticRegression 0.9289340101522843
    SVC 0.9390862944162437
    DecisionTreeClassifier 0.7868020304568528
    VotingClassifier 0.934010152284264
    

    可以看到,现在输出就有差别了,不过由于支持向量机的性能确实突出,多个分类器投票后,居然还拉低了一点投票分类器的分数。不过也确实说明了投票分类器的结果是几个分类器投票集成的结果。

    from sklearn.datasets import make_moons
    
    X,y = make_moons(n_samples=10000, noise=0.15)
    X_train = X[:9000]
    y_train = y[:9000]
    X_test = X[9000:]
    y_test = y[9000:]
    
    for clf in (log_clf, svm_clf, tree_clf, voting_clf):
        clf.fit(X_train, y_train)
        y_pred = clf.predict(X_test)
        print(clf.__class__.__name__, accuracy_score(y_test, y_pred))
        
    # 输出:
    LogisticRegression 0.87
    SVC 0.992
    DecisionTreeClassifier 0.991
    VotingClassifier 0.992
    

    可以看到,在卫星数据集上,投票分类器和SVM分类器的结果是非常接近的,因为几个分类器的结果都有了提升,因此集成在一起的精度也有提升。

    bagging和pasting

    bagging和pasting是两种不同的集成算法策略。如果使用同一种分类器训练,但是在不同的训练数据集上进行训练,这个训练数据集是原始训练数据集的子集,也就是一种抽样。如果是有放回的抽样,那么就是bagging算法,如果采样时样本不放回,那就是pasting算法。
    代码如下:

    bagging

    from sklearn.ensemble import BaggingClassifier
    
    bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, bootstrap=True, n_jobs=-1, oob_score=True)
    bagging_clf.fit(X_train, y_train)
    y_pred = bagging_clf.predict(X_test)
    accuracy_score(y_test, y_pred)
    
    #输出:0.993
    

    pasting

    from sklearn.ensemble import BaggingClassifier
    
    bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, bootstrap=False, n_jobs=-1)
    bagging_clf.fit(X_train, y_train)
    y_pred = bagging_clf.predict(X_test)
    accuracy_score(y_test, y_pred)
    
    #输出:0.991
    

    可以看到bagging和pasting的预测得分很接近,不过还是bagging的效果略好与pasting。

    随机森林

    随机森林算法就是决策树的集成算法,可以用bagging方法也可以用pasting方法。借助sklearn,我们可以很方便的是使用随机森林。

    from sklearn.ensemble import RandomForestClassifier
    
    rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1)
    rnd_clf.fit(X_train, y_train)
    y_pred = rnd_clf.predict(X_test)
    accuracy_score(y_test, y_pred)
    
    #输出:0.99
    

    可以看到,预测的打分也达到了0.99。

    AdaBoosting和梯度提升

    AdaBoosting是一组有前后顺序的分类器,把前一个分类器结果中错分的样本,提升其权重,输入到第二个分类器,继续更新权重,以此类推,使得模型越来越好;梯度提升和AdaBoosting的区别在于,梯度提升法的分类器是拟合前一个分类器的预测结果和真实结果的误差,通过不断地拟合这个误差来提升模型的训练精度,使得模型越来越好。

    AdaBoosting

    from sklearn.ensemble import AdaBoostClassifier
    
    ada_clf = AdaBoostClassifier(DecisionTreeClassifier(), n_estimators=500, algorithm="SAMME.R", learning_rate=0.5)
    ada_clf.fit(X_train, y_train)
    y_pred = ada_clf.predict(X_test)
    accuracy_score(y_test, y_pred)
    
    #输出:0.99
    

    打印出决策边界看看:

    from sklearn.datasets import make_moons
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    
    ada_clf = AdaBoostClassifier(DecisionTreeClassifier(), n_estimators=500, algorithm="SAMME.R", learning_rate=0.5)
    ada_clf.fit(X, y)
    
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 # 生成两个坐标轴的范围,生成密集可以看得更清楚
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    h=0.01
    print(np.arange(y_min,y_max,h).shape)
    xx,yy=np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))
    print(xx.shape)
    print(yy.shape)
    z=ada_clf.predict(np.c_[xx.ravel(),yy.ravel()]) # ravel表示把数组拉成一维数组,np.c_表示把按列拼接两个矩阵
    z=z.reshape(xx.shape) # 转换成跟xx一样的维度
    plt.contourf(xx, yy, z, cmap=plt.cm.Paired, alpha=0.8) # 按z来画出决策边界
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired) # 按y来画出原始数据的散点图
    plt.show()
    

    可以看到边界比较清晰的划分出来了。

    梯度提升

    from sklearn.ensemble import GradientBoostingClassifier
    
    gb_clf = GradientBoostingClassifier(learning_rate=0.5, n_estimators=100)
    gb_clf.fit(X_train, y_train)
    y_pred = gb_clf.predict(X_test)
    accuracy_score(y_test, y_pred)
    
    #输出:0.992
    

    同样的,我们也输出决策边界:

    from sklearn.datasets import make_moons
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    
    gb_clf = GradientBoostingClassifier(learning_rate=0.5, n_estimators=100)
    gb_clf.fit(X, y)
    
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 # 生成两个坐标轴的范围,生成密集可以看得更清楚
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    h=0.01
    print(np.arange(y_min,y_max,h).shape)
    xx,yy=np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))
    print(xx.shape)
    print(yy.shape)
    z=gb_clf.predict(np.c_[xx.ravel(),yy.ravel()]) # ravel表示把数组拉成一维数组,np.c_表示把按列拼接两个矩阵
    z=z.reshape(xx.shape) # 转换成跟xx一样的维度
    plt.contourf(xx, yy, z, cmap=plt.cm.Paired, alpha=0.8) # 按z来画出决策边界
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired) # 按y来画出原始数据的散点图
    plt.show()
    

    和Adaboosting算法的结果非常接近,虽然有少个几个样本分类错误,但总体上非常准确的划分了数据集。

    相关文章

      网友评论

          本文标题:集成方法与随机森林简介

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