集成学习Day7 投票法
1. 投票法
(1)投票法原理
集成学习(ensemble learning)是通过构建并结合多个学习器来完成学习任务。而投票法是集成学习的常用技巧,它是一种遵循少数服从多数原则的集成学习模型,使用投票法可以有效提升模型的泛化能力,减少模型的错误率。在理想情况下,投票法的预测结果应当优于任何一个基模型的预测结果。投票法同时适用于回归模型和分类模型。
对于回归模型来说,投票法的预测结果是多个其他回归模型预测结果的平均值;对于分类模型来说,硬投票法的预测结果是多个模型预测结果中出现次数最多的类别,软投票对各类预测结果的概率进行求和,最终选择概率之和最大的类标签。
例如硬投票:有2/3的模型预测结果是B,因此硬投票法的预测结果是B
对于某个样本:
模型 1 的预测结果是 类别 A
模型 2 的预测结果是 类别 B
模型 3 的预测结果是 类别 B
例如软投票:最终对于类别A的预测概率的平均是 (99 + 49 + 49) / 3 = 65.67%,因此软投票法的预测结果是A。
对于某个样本:
模型 1 的预测结果是 类别 A 的概率为 99%
模型 2 的预测结果是 类别 A 的概率为 49%
模型 3 的预测结果是 类别 A 的概率为 49%
从上面的结果可以看出,软投票和硬投票可以得出完全不同的结论,相比于硬投票,软投票考虑到了预测概率这一信息。并且在投票法中,我们还需要考虑到不同的基模型可能产生的影响,理论上的基模型可以是任意已被训练好的模型,但是在实际应用中要想让投票法产生较好的结果,需要满足两个条件:
- 基模型之间的效果差别不能太大,如果某个基模型相比于其他基模型太差,该模型很可能成为噪声;
- 基模型应该具有较小的同质性。例如在基模型预测效果相近的情况下,两个基于树模型的或者两个线性模型的投票可能差于基于树模型和线性模型的投票。
(2)sklearn代码(pipe管道+voting)
Sklearn中提供了 VotingRegressor 与VotingClassifier 两个投票方法。 这两种模型的操作方式相同,并采用相同的参数。使用模型需要提供一个模型列表,列表中每个模型采用Tuple的结构表示,第一个元素代表名称,第二个元素代表模型,需要保证每个模型必须拥有唯一的名称。
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 sklearn.datasets import make_classification # test classification dataset
from sklearn.model_selection import cross_val_score # evaluate a given model using cross-validation
from sklearn.model_selection import RepeatedStratifiedKFold # k
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot
import numpy as np
def get_dataset(): # generate 1000 random samples (every sample contains 20 features)
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(): # get a voting ensemble of models
# define the base model
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 model
ensemble = VotingClassifier(estimators=models, voting='hard') # choose hard voting
return ensemble
def get_models(): # get a list of models to evaluate
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): # evalute a give model using cross-validation
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() # receive dataset
models = get_models() # get models to evaluate
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)))
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
硬投票结果:
软投票结果:
可见软投票结果不一定好于硬投票,但通过箱型图可以看到投票法对性能的提升还是很不错的。下节将继续介绍Bagging。