Datawhale 202104 集成学习(中)| 投票法与bagging

投票法简介


痛点:
算法得出的单一结果可能存在偏差,因此融合多个数据是降低误差的一个好方法,这就是投票法的基本思路。

分类(投票可以用于分类和回归模型中):

按模型类型可分为:

  • 回归投票法:输出为所有结果的加权(平均)值;
  • 分类投票法:输出出现最多的结果;

分类模型的投票可分为:

  • 硬投票:结果为投票出现最多的类;
  • 软投票:结果为每个模型概率加和最大的类;

硬投票和软投票举例:

硬投票:
模型1的预测结果:类别A
模型2的预测结果:类别B
模型3的预测结果:类别B
- 最后统计输出最多的是B
软投票:
模型1 预测类别A的概率为 99%
模型2 预测类别A的概率为 49%
模型3 预测类别A的概率为 49%
- 最后统计类别A的预测结果平均是(99+49+49)/3=65.67%,软投票的结果根据加权平均计算;

投票法中注意点:

考虑不同基模型可能产生的影响,需要具备两个条件:

  • 基模型之间的效果不能太大,否则很可能成为噪声;
  • 基模型之间应有较小的同质性,例如在结果相似的情况下,线性模型和树模型的组合往往比两个树模型效果好。

投票合集能得到清晰的类别标签,适合用硬投票。
投票集合中使用的模型能预测类别的概率,适合用软投票。

投票法基础案例分析(基于sklean pipe管道的使用以及voting的使用)

  • 由教程中得到

模型需要的预处理操作,可以为他们定义Pipeline完成模型预处理。
模型提供了voting参数让我们选择软投票或硬投票。

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import VotingClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

models = [('lr', LogisticRegression()), 
          ('svm', make_pipeline(StandardScaler(), SVC()))
         ]
ensemble = VotingClassifier(estimators=models, voting='soft')

硬投票法(学习教程baseline)

训练基模型为KNN 并进行评估

# 构建样本并训练模型分类器
import numpy as np

from sklearn.datasets import make_classification
from sklearn.neighbors import KNeighborsClassifier

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score 
from sklearn.model_selection import RepeatedStratifiedKFold


# 得到训练数据
def get_dataset():
    X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, 
                               n_redundant=5, random_state=2)
    return X,y

# 训练模型投票
def get_voting():
    # 定义基础模型
    models = list()
    models.append(('knn1', KNeighborsClassifier(n_neighbors=1)))
    models.append(('knn3', KNeighborsClassifier(n_neighbors=3)))
    models.append(('knn5', KNeighborsClassifier(n_neighbors=5)))
    models.append(('knn7', KNeighborsClassifier(n_neighbors=7)))
    models.append(('knn9', KNeighborsClassifier(n_neighbors=9)))
    
    # 定义投票集成
    ensemble = VotingClassifier(estimators=models, voting='hard')
    return ensemble

# 创建模型列表评估单个模型
def get_models():
    models = dict()
    models['knn1'] = KNeighborsClassifier(n_neighbors=1)
    models['knn3'] = KNeighborsClassifier(n_neighbors=3)
    models['knn5'] = KNeighborsClassifier(n_neighbors=5)
    models['knn7'] = KNeighborsClassifier(n_neighbors=7)
    models['knn9'] = KNeighborsClassifier(n_neighbors=9)
    models['hard_voting'] = get_voting()
    return models

# 十倍交叉验证 三次重复的分数列表返回
def evaluate_model(model, X, y):
    cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
    scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1,
                             error_score='raise')
    return scores
# 训练模型 评估性能
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot

# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()

# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
    scores = evaluate_model(model, X, y)
    results.append(scores)
    names.append(name)
    print('>%s %.3f (%.3f)' % (name, np.mean(scores), np.std(scores)))
    
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

硬投票结果显示

models = get_voting()
clf = models.fit(X, y)
y_pred = clf.predict(X)
micro = metrics.precision_score(y, y_pred, average='micro')  # 微平均,精确率

print("模型精确率为:", micro)

模型精确率为: 0.95

软投票法案例

  • 根据给出的baseline做出修改 采用软投票法
import numpy as np

from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, VotingClassifier

from sklearn.datasets import make_classification
from sklearn.neighbors import KNeighborsClassifier

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score 
from sklearn.model_selection import RepeatedStratifiedKFold

def get_dataset():
    X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, 
                               n_redundant=5, random_state=2)
    return X, y


def get_voting():
    # 定义基础模型
    models = list()
    models.append(('lr' , LogisticRegression(multi_class='multinomial', random_state=5)))
    models.append(('knn', KNeighborsClassifier(n_neighbors=7)))
    models.append(('rf' , RandomForestClassifier(n_estimators=50, random_state=1)))
    models.append(('gnb', GaussianNB()))    
    # 定义投票
    ensemble = VotingClassifier(estimators=models, voting='soft')

    return ensemble


# 创建模型列表评估单个模型
def get_models():
    models = dict()
    models['lr'] = LogisticRegression(multi_class='multinomial', random_state=5)
    models['knn'] = KNeighborsClassifier(n_neighbors=7)
    models['rf'] = RandomForestClassifier(n_estimators=50, random_state=1)
    models['gnb'] = GaussianNB()
    models['soft_voting'] = get_voting()
    return models

# 十倍交叉验证 三次重复的分数列表返回
def evaluate_model(model, X, y):
    cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
    scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1,
                             error_score='raise')
    return scores
# 训练模型 评估性能
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot

# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()

# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
    scores = evaluate_model(model, X, y)
    results.append(scores)
    names.append(name)
    # 注意此时修改为软投票
    print('>%s %.3f (%.3f)' % (name, np.mean(scores), np.std(scores)))
    
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

软投票法结果

from sklearn import metrics

models = get_voting()
clf = models.fit(X, y)
y_pred = clf.predict(X)
micro = metrics.precision_score(y, y_pred, average='micro')  # 微平均,精确率

print("模型精确率为:", micro)

模型精确率为: 0.939

02 Bagging简介

问题痛点:

  • 训练中模型差异不大,需要通过不同的采样方式增加模型的差异性;

解决方法:

  • 核心是自主采样bootstrap,有放回的采样。
    (Eg. 估计全国所有人年龄的平均值,在全国所有人口中随机抽取可能包含交集的集合),计算每个集合平均值,然后将所有平均值的均值作为估计值。

Bagging简介

Bagging的核心是自主采样(bootstrap),即有放回的从数据集中进行采样。同样一个样本可能被多次进行采样,如果希望得到全国所有人口年龄的平均值,我们可以在全国所有人口随机抽取不同集合,再计算几何平均值。

随机取一组样本放入采样集合,再把样本放回初始数据集,重复K次采样,最终可以获得大小为K的样本集合。同样方法,我们可以采样出T个含K个样本的集合,对每个样本集合训练一个基学习器,再将这些基学习器融合。

  • 回归问题的预测是通过预测取平均值进行的;
  • 分类问题的预测是通过预测取多数票预测进行的;

bagging可以降低方差,在不剪枝决策树和神经网络等易受样本扰动的学习器效果明显。实际使用中,加入列采样的Bagging对高维小样本有神奇的效果。

Bagging的案例分析(基于Sklearn 随机森林)

决策树的每个非叶子节点表示样本在一个特征上的判断,节点下方的分支表示对样本的划分。决策树的分支节点所包含的样本“纯度”尽可能高,节点划分过程中所用的指标主要是信息增益和GINI系数。

信息增益衡量的是划分前后信息不确定性成都的减小,信息不确定度通过信息熵度量,计算方式为:
H ( Y ) = − ∑ p i l o g p i H(Y) = - \sum p_i logp_i H(Y)=pilogpi

i表示样本的标签,p表示该样本出现的概率。当我们对样本呢做出划分之后,计算样本的条件熵:
H ( Y ∣ X ) = − ∑ x ∈ X p ( X = x ) H ( Y ∣ X = x ) H(Y|X) = - \sum_{x \in X} p(X = x) H(Y|X=x) H(YX)=xXp(X=x)H(YX=x)

其中x表示用于划分的特征取值,信息增益定义为信息熵与条件熵的差值:$ IG = H(Y) - H(Y|X) $

信息增益IG越大,说明使用该特征划分数据所获得的信息量变化越大,子节点的样本“纯度”越高。

同样,我们可以用Gini指数来衡量数据的不纯度,计算方法如下:
$ Gini = 1 - \sum p_i^2 $

做出划分后,计算划分后的基尼系数:$ Gini_x = \sum_{x \in X} p(X = x)[1-\sum p_i^2] $

一般来说,选择划分后的Gini最小。

from sklearn.datasets import make_classification

X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, 
                           n_redundant=5, random_state=5)
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification

from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
from sklearn.svm import SVC


# 设置数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, 
                           n_redundant=5, random_state=5)

# 定义模型
model = BaggingClassifier(base_estimator=SVC(), n_estimators=10, random_state=0, bootstrap_features=True)

# 分析模型
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1,
                           error_score='raise')
# 评价结果
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值