小言_互联网的博客

Datawhale集成学习-投票法的原理和案例分析

453人阅读  评论(0)

参考来源:
1、开源学习内容可参考:https://github.com/datawhalechina/team-learning-data-mining
2、《机器学习》,周志华 ,清华大学出版社

一、集成学习

1.1 集成学习概述

集成学习(ensemble learning)是一类机器学习框架,通过构建并结合多个学习器来完成学习任务。有时也被称为多分类器系统(multi-classifier system)、基于委员会的学习(committee-based learning)等。
如下图显示出集成学习的一般结构是:先产生一组“个体学习器”(individual learner),再用某种策略将它们结合起来。

  • 单一的学习器可以被称为个体学习器,聚合的过程对应结合模块

个体学习器一般不称为基学习器,常称为“组件学习器”(component learner)或直接称为个体学习器。

  • 根据学习器是否一致可以分为同质异质

同质:个体学习器通常由一个现有的学习算法从训练数据产生,例如C4.5决策树算法、BP神经网络算法等,此时集成中只包含同种类型的个体学习器,例如“决策数集成”中全是决策树,“神经网络集成”中全是神经网络,这样的集成是“同质”的(homogeneous)。
异质:集成也可包含不同类型的个体学习器,例如同时包含决策树和神经网络,这样的集成是“异质”的(heterogenous)。

  • 同质集成中的个体学习器被称为"基学习器

同质集成中的个体学习器亦称“基学习器”(base learner),相应的学习算法称为“基学习算法”(base learning algorithm)。
异质集成中的个体学习器由不同的学习算法生成,这时就不再有基学习算法

1.2 基学习器的选择

集成学习通过将多个学习进行结合,常可获得比单一学习器显著优越的泛化性能。这对“弱学习器”(week learner)尤为明显,因此集成学习的很多理论研究都是针对弱学习器进行的。

基学习器有时也被直接称为弱学习器。弱学习器常指泛化性能略由于随机猜测的学习器;例如在二分类问题上精度略高于50%的分类器。

但是实践中并不总是集成学习器优于单个学习器,我们需要注重个体学习器的质量,下面来看一个例子:
在二分类任务中,假定三个分类器在三个测试样本上的表现如图8.2所示,其中√表示分类正确,X代表分类错误,集成学习的结果通过投票法(voting)产生,即“少数服从多数”

  • 图a,每个个体学习器准确率是66.6% ,但是集成之后准确率可以达到100%,那么集成提升性能
  • 图b,每个个体学习率准确率是66.7 % ,三个分类器没有差别,集成之后性能没有提高。那么集成之后准确率依旧
  • 图c,每个分类器的精度都只有33.3%,集成学习效果变得更糟,那么集成起到了负作用

这个简单的例子显示出:要获得好的集成,个体学习器应“好而不同”,即个体学习器要有一定的“准确性”,并且要有“多样性”(diversity),即学习器间具有差异性。

那么可以看出有效的个体学习器可以提升集成学习器的性能, 那么我们此时需要思考一个问题,如何选择优秀的个体学习器 :

  • 个体学习器要有一定的准确性,即学习器不能太坏,至少不差于弱学习器。
  • 个体学习器要有多样性,学习器之间要有差异性,这样有利于范化

可以知道个体学习器的选取,便是集成学习的难点和核心

根据个体学习器的生成方式,目前集成学习根据并行/串行,或者说是否更新后序学习器的样本数据权重可以分成两大类:

  • voting(投票分类器) /Bagging/ 随机森林,并行运行所有个体学习器,然后聚合预测结果。
  • bosting, 重训运行每个个体学习器,然后每次训练完一个便更新预测错误的样本权重,使得下一个个体学习器,可以更加关注这些样本。

二、集成学习中的投票法

2.1 投票法的思路

投票法是集成学习中常用的技巧,可以帮助我们提高模型的泛化能力,减少模型的错误率。

举个例子,在航空航天领域,每个零件发出的电信号都对航空器的成功发射起到重要作用。如果我们有一个二进制形式的信号:
11101100100111001011011011011
在传输过程中第二位发生了翻转
10101100100111001011011011011

这导致的结果可能是致命的。一个常用的纠错方法是重复多次发送数据,并以少数服从多数的方法确定正确的传输数据。一般情况下,错误总是发生在局部,因此融合多个数据是降低误差的一个好方法,这就是投票法的基本思路。

  • 对于回归模型来说,投票法最终的预测结果是多个其他回归模型预测结果的平均值。
  • 对于分类模型,硬投票法的预测结果是多个模型预测结果中出现次数最多的类别,软投票对各类预测结果的概率进行求和,最终选取概率之和最大的类标签。

2.2 投票发原理分析

投票法是一种遵循少数服从多数原则的集成学习模型,通过多个模型的集成降低方差,从而提高模型的鲁棒性。在理想情况下,投票法的预测效果应当优于任何一个基模型的预测效果。

  • 投票法在回归模型与分类模型上均可使用:
    回归投票法:预测结果是所有模型预测结果的平均值。
    分类投票法:预测结果是所有模型种出现最多的预测结果。

  • 分类投票法又可以被划分为硬投票与软投票:
    硬投票:预测结果是所有投票结果最多出现的类。
    软投票:预测结果是所有投票结果中概率加和最大的类。

下面我们使用一个例子说明硬投票:

对于某个样本:
模型 1 的预测结果是 类别 A
模型 2 的预测结果是 类别 B
模型 3 的预测结果是 类别 B
有2/3的模型预测结果是B,因此硬投票法的预测结果是B

同样的例子说明软投票:

对于某个样本:
模型 1 的预测结果是 类别 A 的概率为 99%
模型 2 的预测结果是 类别 A 的概率为 49%
模型 3 的预测结果是 类别 A 的概率为 49%
最终对于类别A的预测概率的平均是 (99 + 49 + 49) / 3 = 65.67%,因此软投票法的预测结果是A。

软投票法与硬投票法可以得出完全不同的结论。相对于硬投票,软投票法考虑到了预测概率这一额外的信息,因此可以得出比硬投票法更加准确的预测结果。

在投票法中,我们还需要考虑到不同的基模型可能产生的影响。理论上,基模型可以是任何已被训练好的模型。但在实际应用上,想要投票法产生较好的结果,需要满足两个条件:

  • 基模型之间的效果不能差别过大。当某个基模型相对于其他基模型效果过差时,该模型很可能成为噪声。
  • 基模型之间应该有较小的同质性。例如在基模型预测效果近似的情况下,基于树模型与线性模型的投票,往往优于两个树模型或两个线性模型。

当投票合集中使用的模型能预测出清晰的类别标签时,适合使用硬投票。当投票集合中使用的模型能预测类别的概率时,适合使用软投票。软投票同样可以用于那些本身并不预测类成员概率的模型,只要他们可以输出类似于概率的预测分数值(例如支持向量机、k-最近邻和决策树)。

通过以上的例子我们可以看出,不论是硬投票还是软投票,它对所有模型的处理是一样的,这意味着所有模型对预测的贡献是一样的。我们还可以调整每个不同分类器的权值,使其对整体模型的贡献度不同,来改良模型预测准确性。

2.3 投票法的局限

投票法的局限性在于,它对所有模型的处理是一样的,这意味着所有模型对预测的贡献是一样的。如果一些模型在某些情况下很好,而在其他情况下很差,这是使用投票法时需要考虑到的一个问题。

三、投票法的案例分析

3.1 基于sklearn,介绍pipe管道的使用以及voting的使用

Sklearn中提供了 VotingRegressorVotingClassifier 两个投票方法。 这两种模型的操作方式相同,并采用相同的参数。使用模型需要提供一个模型列表,列表中每个模型采用Tuple的结构表示,第一个元素代表名称,第二个元素代表模型,需要保证每个模型必须拥有唯一的名称。

例如,我们可以这样定义两个模型:

models = [('lr',LogisticRegression()),('svm',SVC())]
ensemble = VotingClassifier(estimators=models)

有时某些模型需要一些预处理操作,我们可以为他们定义Pipeline完成模型预处理工作:

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

pipline的作用是,可以将多个处理步骤合并为单个Scikit-Learn估计器。而在本例中,就是将数据标准化之后,再进行svm操作。

模型还提供了voting参数让我们选择软投票或者硬投票(soft为软投票,hard为硬投票):

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

下面我们使用一个完整的例子演示投票法的使用:

# 加载和调取包
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
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.neighbors import KNeighborsClassifier
from matplotlib import pyplot
from sklearn.datasets import make_classification

# 构造数据集:一个1000个样本,20个特征的随机数据集:
from sklearn.datasets import make_classification
def get_dataset():
    X, y = make_classification(n_samples=1000, 
    n_features=20, n_informative=15, n_redundant=5, random_state=2)
    # summarize the dataset
    return X,y

# 建立模型,选择多个KNN模型作为基模型演示投票法
models = [('lr',LogisticRegression()),('svm',make_pipeline(StandardScaler(),SVC()))]
ensemble = VotingClassifier(estimators=models)

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)))
    # define the voting ensemble
    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

# K折交叉验证
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

# 模型检验
X, y = get_dataset()
models = get_models()
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, mean(scores), std(scores)))

# 绘制箱线图
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

最终输出结果如下:

结论: 
1、 显然投票的效果略大于任何一个基模型。
2、 通过箱形图我们可以看到硬投票方法对交叉验证整体预测结果分布带来的提升。


转载:https://blog.csdn.net/weixin_42007974/article/details/115707842
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场