集成学习也就是我们常说的“博采众长”,通过构建多个机器学习器来完成任务,是非常火爆的机器学习方法之一。
集成学习按照各个弱学习器之间是否存在依赖关系可以分为两类:
- 第一个是个体学习器之间存在强依赖关系,代表算法就是是boosting系列算法。
- 另一类是个体学习器之间不存在强依赖关系,代表算法是bagging和随机森林(Random Forest)系列算法。
这里主要关于boosting系列算法中Adaboost算法的实例应用。Adaboost既可以用作分类,也可以用作回归。具体算法内容可参考这里。
下面主要关于Adaboost算法作简要的说明:
从图中可以看出,Boosting算法的工作机制是首先从训练集用初始权重训练出一个弱学习器1,根据弱学习的学习误差率表现来更新训练样本的权重,使得之前弱学习器1学习误差率高的训练样本点的权重变高,使得这些误差率高的点在后面的弱学习器2中得到更多的重视。然后基于调整权重后的训练集来训练弱学习器2.,如此重复进行,直到弱学习器数达到事先指定的数目T,最终将这T个弱学习器通过集合策略进行整合,得到最终的强学习器。
这里主要针对普通的决策树和Adaboost算法进行算法应用,其次还包含了超参数选择的方法实现,特别是设置嵌套参数
首先是构造数据集
from sklearn.datasets import make_gaussian_quantiles
from matplotlib import pyplot as plt
import numpy as np
%matplotlib inline
# 生成2维正态分布,生成的数据按分位数分为两类,500个样本,2个样本特征,协方差系数为2
X1, y1 = make_gaussian_quantiles(cov=2.5, n_samples=300, n_classes=2, n_features=2, random_state=1)
# X1的数据分布图
print("X1的数据分布")
plt.scatter(X1[:, 0], X1[:, 1], marker="o", c=y1)
plt.show()
# 生成2维正态分布,生成的数据按分位数分为两类,400个样本,2个样本特征均值都为3,协方差系数为2
X2, y2 = make_gaussian_quantiles(cov=1.5, n_samples=400, n_classes=2, n_features=2, random_state=1, mean=(3, 3))
# X2的数据分布图
print("X2的数据分布")
plt.scatter(X2[:, 0], X2[:, 1], marker="o", c=y2)
plt.show()
# 将两数据合并成一个
X = np.concatenate((X1, X2))
y = np.concatenate((y1, -y2 + 1))
print("合并后的数据维度:\n", X.shape)
print("合并后的数据分布")
plt.scatter(X[:, 0], X[:, 1], marker="o", c=y)
plt.show()
X1的数据分布
X2的数据分布
合并后的数据维度:
(700, 2)
合并后的数据分布
使用单个弱分类器进行划分
# 使用单个弱分类器进行划分
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 使用单个的CART树进行分类
clf = DecisionTreeClassifier(max_depth=5)
clf.fit(x_train, y_train)
# 画图(训练集)
x_min, x_max = x_train[:, 0].min() - 1, x_train[:, 0].max() + 1
y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
np.arange(y_min, y_max, 0.1))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.8)
plt.show()
# 测试集的得分
print("测试集得分:\n", clf.score(x_test, y_test))
测试集得分:
0.8514285714285714
使用cv交叉验证进行超参数max_depth的调优
# 使用cv交叉验证对决策树的深度超参数进行优化
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 使用单个的CART树进行分类
params = {"max_depth": list(range(1, 30))}
clf = DecisionTreeClassifier()
gc = GridSearchCV(clf, param_grid=params, cv=10)
gc.fit(x_train, y_train)
# 画图(训练集)
x_min, x_max = x_train[:, 0].min() - 1, x_train[:, 0].max() + 1
y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
np.arange(y_min, y_max, 0.1))
Z = gc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.8)
plt.show()
# 测试集的得分
print(gc.score(x_test, y_test))
print("交叉验证后的最好的方案:\n", gc.best_estimator_)
0.8685714285714285
交叉验证后的最好的方案:
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=22,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort=False, random_state=None,
splitter='best')
使用集成学习方法:Adaboost算法进行分类
# 使用adaboost
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 使用Adaboost
clf = DecisionTreeClassifier(max_depth=2)
bdt = AdaBoostClassifier(base_estimator=clf, algorithm="SAMME", n_estimators=600, learning_rate=0.7)
bdt.fit(x_train, y_train)
# 画图(训练集)
x_min, x_max = x_train[:, 0].min() - 1, x_train[:, 0].max() + 1
y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
np.arange(y_min, y_max, 0.1))
Z = bdt.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.8)
plt.show()
# 测试集的得分
print("测试集得分:\n", bdt.score(x_test, y_test))
测试集得分:
0.8971428571428571
# 使用adaboost
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
# 数据集划分
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 使用单个的CART树进行分类
params = {
"base_estimator__max_depth": list(range(1,20)), # base_estimator指向弱学习器,使用双下滑线指明嵌套参数
"n_estimators": list(range(100, 700, 100))}
clf = DecisionTreeClassifier()
bdt = AdaBoostClassifier(base_estimator=clf, algorithm="SAMME", learning_rate=0.8)
gc = GridSearchCV(bdt, param_grid=params, cv=10)
gc.fit(x_train, y_train)
# 画图(训练集)
x_min, x_max = x_train[:, 0].min() - 1, x_train[:, 0].max() + 1
y_min, y_max = x_train[:, 1].min() - 1, x_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
np.arange(y_min, y_max, 0.1))
Z = gc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.8)
plt.show()
# 测试集的得分
print(gc.score(x_test, y_test))
print("交叉验证后的最好的方案:\n", gc.best_estimator_)
0.8914285714285715
交叉验证后的最好的方案:
AdaBoostClassifier(algorithm='SAMME',
base_estimator=DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=4,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort=False, random_state=None,
splitter='best'),
learning_rate=0.8, n_estimators=100, random_state=None)