目录 一、认识集成学习 二、基于多数票机制的集成分类器实现 1、多数票机制原理 2、构建多数票分类器 3、多数票分类器实际应用 4、模型评估 三、套袋法(Bagging) 1、葡萄酒数据集样本分类 2、决策区域结果 四、自适应增强法(Adaboost) 五、总结
一、认识集成学习
集成学习(Ensemble Learning),它在机器学习、深度学习中有重要的应用。所谓集成,就是把不同模型通过某些机制或设定标准进行融合,目标得到一个更加强大稳健的模型,使它有着更强的泛化能力,也避免了单个模型过拟合等问题。 下面将通过实例分析,循序渐进学习,详细介绍集成学习的几种技术,目标是组合不同的分类器模型,使得融合模型得到更好的效果。 包括:
- 多数票机制
- 套袋法
- Adaboost
二、基于多数票机制的集成分类器实现(MajorityVoted)
1、多数票机制原理
集成学习中最常见的集成方法就是多数票机制,顾名思义,通过投票选择,多者获胜的原理,把不同的分类器按适当的权重组合起来,建立一个更强大的超级分类器。 例如,在一个二分类问题p={0,1}中,基于分类概率的加权分类方法,得到3个分类器的预测结果。
import numpy as np
ensemble=np.array([[0.9,0.1],[0.8,0.2],[0.6,0.4]])
p=np.average(ensemble,axis=0,weights=[0.2,0.2,0.6])
print(p)
classp=np.argmax(p) print(classp)
结果:[0.7 0.3] 0 因此,对预测结果综合,结果为类别0. 这里一个简单理解原理的例子,使用numpy的average
和argmax函数,下面将自己构建一个多数票分类器。
2、构建多数票分类器
导入相关第三方工具包和函数方法
"""
encoding: utf-8
@author: Charzous
@license: Copyright © 2021 Charzous
@software: Pycharm
@file: MajorVoteClassifier.py
@time: 2021/1/31 18:06
"""
from sklearn.base import BaseEstimator, ClassifierMixin, clone
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import _name_estimators
import six
import numpy as np
实现类MajorityVoteClassifier
各个方法: (1)初始化方法
class MajorityVoteClassifier(BaseEstimator, ClassifierMixin):
def __init__(self, classifiers, vote='classlabel', weights=None):
self.classifiers = classifiers
self.named_classifiers = {key: value for key, value in _name_estimators(classifiers)}
self.vote = vote
self.weights = weights
(2)适应集成分类器
def fit(self, X, y):
self.lablenc_ = LabelEncoder()
self.lablenc_.fit(y)
self.classes_ = self.lablenc_.classes_
self.classifiers_ = []
for clf in self.classifiers:
fitted_clf = clone(clf).fit(X, self.lablenc_.transform(y))
self.classifiers_.append(fitted_clf)
return self
(3)预测分类标签方法
def predict(self, X):
if self.vote == 'probability':
maj_vote = np.argmax(self.predict_proba(X), axis=1)
else:
predictions = np.asarray([clf.predict(X) for clf in self.classifiers_]).T
maj_vote = np.apply_along_axis(lambda x: np.argmax(np.bincount(x, weights=self.weights)), axis=1,
arr=predictions)
maj_vote = self.lablenc_.inverse_transform(maj_vote)
return maj_vote
(4)计算标签平均概率以及返回分类器参数
def predict(self, X):
if self.vote == 'probability':
maj_vote = np.argmax(self.predict_proba(X), axis=1)
else:
predictions = np.asarray([clf.predict(X) for clf in self.classifiers_]).T
maj_vote = np.apply_along_axis(lambda x: np.argmax(np.bincount(x, weights=self.weights)), axis=1,
arr=predictions)
maj_vote = self.lablenc_.inverse_transform(maj_vote)
return maj_vote
def predict_proba(self, X):
probas = np.asarray([clf.predict_proba(X) for clf in self.classifiers_])
avg_proba = np.average(probas, axis=0, weights=self.weights)
return avg_proba
def get_params(self, deep=True):
if not deep:
return super(MajorityVoteClassifier, self).get_params(deep=False)
else:
out = self.named_classifiers.copy()
for name, step in six.iteritems(self.named_classifiers):
for key, value in six.iteritems(step.get_params(deep=True)):
out['%s__%s' % (name, key)] = value
return out
到此,多数票机制的类以及方法全部实现,接下来使用该类进行实际应用。
3、多数票分类器实际应用
使用scikit-learn数据模块,加载鸢尾花数据集,选取其中2个特征:萼片宽度和花瓣长度,进行二分类问题的预测。
"""
encoding: utf-8
@author: Charzous
@license: Copyright © 2021 Charzous
@software: Pycharm
@file: MajorVotePredict.py
@time: 2021/1/31 18:31
"""
from sklearn import datasets
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.metrics import auc, roc_curve
import matplotlib.pyplot as plt
from itertools import product
iris = datasets.load_iris()
X, y = iris.data[50:, [1,2]], iris.target[50:]
le = LabelEncoder()
y = le.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2021, stratify=y)
使用3中分类器进行训练:逻辑回归、决策树、K-近邻。 使用5者交叉验证,7:3划分训练集和测试集,其中逻辑回归和KNN方法进行了管道归一化等处理,原理可以查看我写的上一篇:基于sklearn库的机器学习模型与调优实践详细步骤
clf1 = LogisticRegression(penalty='l2', C=0.01, random_state=2021)
clf2 = DecisionTreeClassifier(max_depth=1, criterion='entropy', random_state=2021)
clf3 = KNeighborsClassifier(n_neighbors=1, p=2, metric='minkowski')
pipe1 = Pipeline([['sc', StandardScaler()], ['clf', clf1]])
pipe3 = Pipeline([['sc', StandardScaler()], ['clf', clf3]])
clf_labels = ['Logistic regression', 'Decision tree', 'KNN']
print('5 fold cross validation:\n')
for clf, label in zip([pipe1, clf2, pipe3], clf_labels):
scores = cross_val_score(estimator=clf, X=X_train, y=y_train, cv=5, scoring='roc_auc')
print("ROC AUC :%0.2f(+/-%0.2f) [%s]" % (scores.mean(), scores.std(), label))
结果: 5 fold cross validation: ROC AUC :0.94(+/-0.04) [Logistic regression] ROC AUC :0.93(+/-0.08) [Decision tree] ROC AUC :0.93(+/-0.09) [KNN] 3个模型构建完成之后,开始使用多数票机制来集成一个分类器,也就是前面构建好的多数票分类器。
mv_clf = MajorityVoteClassifier(classifiers=[pipe1, clf2, pipe3])
clf_labels += ['Majority Voting']
all_clf = [pipe1, clf2, pipe3, mv_clf]
for clf, label in zip(all_clf, clf_labels):
scores = cross_val_score(estimator=clf, X=X_train, y=y_train, cv=5, scoring='roc_auc')
print("ROC AUC :%0.2f(+/-%0.2f) [%s]" % (scores.mean(), scores.std(), label))
结果有了显著提升,4个百分点左右。 ROC AUC :0.94(+/-0.04) [Logistic regression] ROC AUC :0.93(+/-0.08) [Decision tree] ROC AUC :0.93(+/-0.09) [KNN] ROC AUC :0.97(+/-0.04) [Majority Voting]
4、模型评估可视化
# 评估集成分类器
colors = ['black', 'orange', 'blue', 'green']
linestyles = [':', '-.', '--', '-']
for clf, label, clr, ls in zip(all_clf, clf_labels, colors, linestyles):
y_pred = clf.fit(X_train, y_train).predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=y_pred)
roc_auc = auc(x=fpr, y=tpr)
plt.plot(fpr, tpr, color=clr, linestyle=ls, label='%s (auc = %0.2f) ' % (label, roc_auc))
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], linestyle='--', color='gray', linewidth=2)
plt.xlim([-0.1, 1.1])
plt.ylim([-0.1, 1.1])
plt.grid(alpha=0.5) # 网格
plt.xlabel('FP rate')
plt.ylabel('TP rate')
plt.show()
可视化图:
很明显,在ROC结果图中,多数票集成分类器表现最好,而逻辑回归也不错,主要是因为数据集规模和特征选取,在更复杂的任务中,多数票会显得更有优势。 所以,我进一步探索,选取另外几个特征进行实验:
X, y = iris.data[50:, [2, 3]], iris.target[50:]
得到一些可视化结果显示:
# 按[0,3],[2,3]两个特征划分,决策区域的区别较明显,[0,2]划分ROC-AUC曲线较明显,[0,1]划分结果最差,[1,2],[1,3]决策区域差别不大
[1,2]特征的决策区域:不明显
[2,3]特征的决策区域:差别显著
获取分类器参数则用:
# 获取分类器参数 print(mv_clf.get_params())
返回的模型详细参数:
三、套袋法(Bagging)
从原始样本集中使用Bootstrap方法随机抽取n个训练样本,共进行k轮抽取,得到k个训练集。(k个训练集之间相互独立,元素可以有重复) 对于k个训练集,训练k个模型(k个模型可以选择决策树,knn等),每个分类器拟合引导样本时,采用多数票机制进行组合预测。
1、葡萄酒数据集样本分类
"""
encoding: utf-8
@author: Charzous
@license: Copyright © 2021 Charzous
@software: Pycharm
@file: baggingAdaboost.py
@time: 2021/2/1 11:25
"""
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder,StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier, AdaBoostClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
加载葡萄酒数据集,选取其中两个特征
# load data
df_wine = pd.read_csv('..\\wine_data\\wine.data', header=None) # 本地加载
# df_wine=pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)#服务器加载
df_wine.columns = ['class label', 'alcohol', '苹果酸', '灰', '灰的碱度', '镁', '总酚', '黄酮类化合物', '非黄烷类酚类', '原花青素', '色彩亮度',
'色调', '稀释酒', '脯氨酸']
df_wine = df_wine[df_wine['class label'] != 1]
y = df_wine['class label'].values
X = df_wine[['alcohol','稀释酒']].values#'脯氨酸'
le = LabelEncoder()
y = le.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2021, stratify=y)
构建决策数模型,以及Bagging模型
tree = DecisionTreeClassifier(max_depth=None, criterion='entropy', random_state=2021)
bag = BaggingClassifier(base_estimator=tree, n_estimators=500, max_samples=1.0, max_features=1.0, bootstrap=True,
bootstrap_features=False, n_jobs=1, random_state=2021)
决策树分类器性能
tree = tree.fit(X_train, y_train)
y_train_pred = tree.predict(X_train)
y_test_pred = tree.predict(X_test)
tree_train = accuracy_score(y_train, y_train_pred)
tree_test = accuracy_score(y_test, y_test_pred)
print('Decision tree train/test ACC %.3f/%.3f' % (tree_train, tree_test))
套袋分类器性能
bag=bag.fit(X_train,y_train)
y_train_pred = bag.predict(X_train)
y_test_pred = bag.predict(X_test)
bag_train = accuracy_score(y_train, y_train_pred)
bag_test = accuracy_score(y_test, y_test_pred)
print('Bagging train/test ACC %.3f/%.3f' % (bag_train, bag_test))
结果正确率对比:可见Bagging之后模型表现提升 Decision tree train/test ACC 1.000/0.833 Bagging train/test ACC 1.000/0.875
2、决策区域结果
# 分类器决策区域可视化
x_min = X_train[:, 0].min() - 1
x_max = X_train[:, 0].max() + 1
y_min = X_train[:, 1].min() - 1
y_max = X_train[:, 1].min() + 1
plt.rcParams['font.sans-serif'] = ['SimHei']
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1), np.arange(y_min, y_max, 0.1))
f, axarr = plt.subplots(nrows=1, ncols=2, sharex='col', sharey='row', figsize=(8, 3))
for idx, clf, tt in zip([0, 1], [tree,bag,ada], ['DecisionTree','Bagging','AdaBoost']):
clf.fit(X_train, y_train)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
axarr[idx].contourf(xx, yy, Z, alpha=0.3)
axarr[idx].scatter(X_train[y_train == 0, 0], X_train[y_train == 0, 1], c='blue', marker='^',s=50)
axarr[idx].scatter(X_train[y_train == 1, 0], X_train[y_train == 1, 1], c='green', marker='o', s=50)
axarr[idx].set_title(tt)
axarr[0].set_ylabel('酒精',fontsize=12)
axarr[0].set_xlabel('稀释酒',fontsize=12)
plt.show()
可视化直观看出,Bagging之后的决策区域明显更加准确。
四、自适应增强法(Adaboost)
这里简单了解一下Adaboost算法,它是集成学习中一种自适应增强方法,与套袋Bagging相比,Adaboost从训练集无替换抽取样本子集来训练模型,得到多个弱学习分类器,特点是从错误中学习,由此建立强大的分类器。 继续使用上面的数据集,使用sklearn实现Adaboost,在前面基础上增加模型,具体如下:
bag = BaggingClassifier(base_estimator=tree, n_estimators=500, max_samples=1.0, max_features=1.0, bootstrap=True,
bootstrap_features=False, n_jobs=1, random_state=2021)
# AdaBoost分类器性能
ada=ada.fit(X_train,y_train)
y_train_pred = ada.predict(X_train)
y_test_pred = ada.predict(X_test)
ada_train = accuracy_score(y_train, y_train_pred)
ada_test = accuracy_score(y_test, y_test_pred)
print('AdaBoost train/test ACC %.3f/%.3f' % (ada_train,ada_test))
五、总结
这篇记录集成学习的重要知识,在实际案例中更好地掌握的集成学习的基本原理机制和方法。集成学习(Ensemble Learning),它在机器学习、深度学习中有重要的应用。所谓集成,就是把不同模型通过某些机制或设定标准进行融合,目标得到一个更加强大稳健的模型,使它有着更强的泛化能力,也避免了单个模型过拟合等问题。 下面将通过实例分析,循序渐进学习,详细介绍集成学习的几种技术。 包括:多数票机制、套袋法、Adaboost。 多数票机制原理是整个的基本,所以进行了具体地分析和学习,由此引申更深入的集成方法! 如果觉得不错欢迎三连哦,点赞收藏关注,一起加油进步!原创作者:Charzous.