导语:
本次任务的主题是“投票法的原理与实践”。
学习链接:
集成学习: EnsembleLearning项目-github.
1.投票法原理简介
在生活中,处理同一个问题,不同的人可能有不同的意见,只是角度不同,没有明显的对错之分。但是为了客观的评价和产生结果,往往都会采用“少数服从多数”的投票机制。那么在机器学习中,也有类似的用法:针对同一个数据集,不同的模型由于本身的特性不同或是同一个模型由于超参数的设置不同等都会产生不同的预测结果,那么为了平衡单模型进行错误的预测(或是误差比较大的预测),我们自然地想到可以用多个模型的均值(回归)或是众数(分类)来作为最终的结果,投票法的简单正是此意。
投票法是一种遵循少数服从多数原则的集成学习模型,通过多个模型的集成降低方差,从而提高模型的鲁棒性。在理想情况下,投票法的预测效果应当优于任何一个基模型的预测效果。
投票法在回归模型与分类模型上均可使用:
- 回归投票法:预测结果是所有模型预测结果的平均值。
- 分类投票法:预测结果是所有模型种出现最多的预测结果。
分类投票法又可以被划分为硬投票与软投票:
- 硬投票:预测结果是所有投票结果最多出现的类。
- 软投票:预测结果是所有投票结果中概率加和最大的类。
下面以一个简单的例子说明硬投票与软投票的区别:
从上图可以看出,硬投票基于众数的角度进行判定,而软投票基于概率加和的角度进行判定,而且有时候两者得出的结果是不一样的。具体什么什么场景用什么方法呢?
一般来说,当投票合集中使用的模型能预测出清晰的类别标签时,适合使用硬投票。当投票集合中使用的模型能预测类别的概率时,适合使用软投票。软投票同样可以用于那些本身并不预测类成员概率的模型,只要他们可以输出类似于概率的预测分数值(例如支持向量机、k-最近邻和决策树)。
需要注意的是:
(1)几个单模型的效果应该相近,若某一个模型的预测误差特别大,那么这个大的误差也会被算进投票机制里,因此,所有单模型对最终结果的预测的贡献是一样的,这其实也是投票法的一个弊端。最理想的情况就是,不同模型的最终效果相近,但预测的具体值在不同区域不一样,这样通过投票就可以形成一种“误差互相平衡”的状态。
(2)不同模型尽可能有较大的本质差异,这样才真正能从不同模型的本质角度,去综合评价一个问题,最终才能使得投票法发挥出它的威力。举一个例子:若要对一个人进行评价,若只考虑他好朋友的看法是缺乏客观性的,往往会看不到真正的结果,若多方面综合不同人对他的评价,这样才能获得最客观、准确的结论。
2.投票法实践
学习教程 EnsembleLearning项目-github.基于分类问题做了案例分析,详细介绍了基于Sklearn中提供的 VotingRegressor() 与 VotingClassifier ()方法实现投票。那么本文,以之前Boston房价数据集,基于回归问题,进行回归投票法的实践:
首先导入数据集:
#数据导入
from sklearn import datasets
import pandas as pd
from sklearn.model_selection import train_test_split
boston = datasets.load_boston() # 返回一个类似于字典的类
X = boston.data
y = boston.target
features = boston.feature_names
boston_data = pd.DataFrame(X,columns=features)
boston_data["Price"] = y
#boston_data.head()
导入接下来会用到的包:
#导包
from sklearn import linear_model
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler # 标准化数据
from sklearn.pipeline import make_pipeline # 使用管道,把预处理和模型形成一个流程
from sklearn.ensemble import RandomForestRegressor
import xgboost as xgb
import lightgbm as lgb
from numpy import mean
from numpy import std
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import VotingRegressor
import matplotlib.pyplot as plt
我们分别使用线性回归、决策树和SVM作为基模型,定义投票集成模型:
注意这里的VotingRegressor()参数不需要选择voting参数,上面说了只有分类投票才有“软硬”之分哦!
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('lin_reg', linear_model.LinearRegression()))
models.append(('DTR', DecisionTreeRegressor(criterion = "mse",min_samples_leaf = 5)))
models.append(('reg_svr ', make_pipeline(StandardScaler(), SVR(C=1.0, epsilon=0.2))))
# define the voting ensemble
ensemble = VotingRegressor(estimators=models)
return ensemble
接下来,我们用get_models函数将我们所要比较的模型进行封装,除了基模型外,我们还使用了后面会介绍的bagging类方法:随机森林、XGBoost、Lightgbm.
# get a list of models to evaluate
def get_models():
models = dict()
models['lin_reg'] = linear_model.LinearRegression()
models['DTR'] = DecisionTreeRegressor(criterion = "mse",min_samples_leaf = 5)
models['reg_svr'] = make_pipeline(StandardScaler(), SVR(C=1.0, epsilon=0.2))
models['voting'] = get_voting()
models['RFR'] = RandomForestRegressor()
models['xgb'] = xgb.XGBRegressor()
models['lgb'] = lgb.LGBMRegressor()
return models
采用十折交叉验证的方式对模型进行评估,评估函数选择均方误差MSE:
def evaluate_model(model, X, y):
scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=10, n_jobs=-1, error_score='raise')
return scores
训练模型,保存分数,并展示可视化最终结果:
# 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, mean(scores), std(scores)))
# plot model performance for comparison
plt.boxplot(results, labels=names, showmeans=True)
plt.show()
如上图所示,可以明显看出投票方法“voting”比三个基模型的效果都要好。基础模型中,特别是SVR的效果最差,MSE直接到了40.325,当然由于前述”投票法的弊端“,SVR的误差也被带进了投票模型中!
针对这种现象,有什么好的办法解决呢?
从图中可以看出,随机森林、XGB、LGB的效果都优于投票模型,这也正是接下来要介绍的bagging类方法的魅力所在!