但是要想获得好的结合或者集成,对基分类器的要求是“好而不同”,即有一定的准确率,而且弱分类器之间要有“多样性”,比如一个判断是否为男性的任务,弱分类器1侧重从鼻子、耳朵这些特征判断是否是男人,分类器2侧重脸和眼睛等等,把这些分类器结合起来就有了所有用来判断是否男性的特征,并且adaboost还可以给每个基分类器赋值不同的权重,比如从脸比鼻子更能判断是否为男性,就可以把分类器2的权重调高一些,这也是adaboost需要学习的内容。
AdaBoost可以表示为基分类器的线性组合:
\[H(\boldsymbol{x})=\sum_{i=1}^{N} \alpha_{i} h_{i}(\boldsymbol{x}) \]其中\(h_i(x),i=1,2,...\)表示基分类器,\(\alpha_i\)是每个基分类器对应的权重,表示如下:
\[\alpha_{i}=\frac{1}{2} \ln \left(\frac{1-\epsilon_{i}}{\epsilon_{i}}\right) \]其中\(\epsilon_{i}\)是每个弱分类器的错误率。
UCI机器学习库的开源数据集:葡萄酒数据集
该数据集包含了178个样本和13个特征,对三个不同品种的葡萄酒进行化学分析的结果,结果包含在三种类型的葡萄酒中发现的13中成分的含量。我们的任务是根据这些数据预测红酒属于哪一类别。
引入数据科学相关工具包
import pandas as pd from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import AdaBoostClassifier from sklearn.model_selection import GridSearchCV import matplotlib.pyplot as plt
加载数据集,并按照8:2的比例分割成训练集和测试集
wine = load_wine() print(f"所有特征:{wine.feature_names}") X = pd.DataFrame(wine.data, columns=wine.feature_names) y = pd.Series(wine.target) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=1)
所有特征:['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']
使用单一决策树建模
base_model = DecisionTreeClassifier(max_depth=1, criterion='gini',random_state=1).fit(X_train, y_train) y_pred = base_model.predict(X_test) print(f"决策树的准确率:{accuracy_score(y_test,y_pred):.3f}")
决策树的准确率:0.694
使用sklearn实现AdaBoost算法建模(基分类器是决策树)
from sklearn.ensemble import AdaBoostClassifier model = AdaBoostClassifier(base_estimator=base_model, n_estimators=50, learning_rate=0.5, algorithm='SAMME.R', random_state=1) model.fit(X_train, y_train) y_pred = model.predict(X_test) print(f"AdaBoost的准确率:{accuracy_score(y_test,y_pred):.3f}")
AdaBoost的准确率:0.972
结果分析
单层决策树对于训练数据欠拟合,而Adaboost模型正确地预测了训练数据的分类标签,准确率有了很大的提高。
x = list(range(2, 102, 2)) y = [] for i in x: model = AdaBoostClassifier(base_estimator=base_model, n_estimators=i, learning_rate=0.5, algorithm='SAMME.R', random_state=1) model.fit(X_train, y_train) model_test_sc = accuracy_score(y_test, model.predict(X_test)) y.append(model_test_sc) plt.style.use('ggplot') plt.title("Effect of n_estimators", pad=20) plt.xlabel("Number of base estimators") plt.ylabel("Test accuracy of AdaBoost") plt.plot(x, y) plt.show()
可以看出:随着迭代次数的升高,测试精度显示升高,后面保持不变,可以选择在精度最高且训练次数比较少的情况下进行。
这个点是(8,1)也就是迭代8次,精度为1
或者(16,1)
x = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] y = [] for i in x: model = AdaBoostClassifier(base_estimator=base_model, n_estimators=50, learning_rate=i, algorithm='SAMME.R', random_state=1) model.fit(X_train, y_train) model_test_sc = accuracy_score(y_test, model.predict(X_test)) y.append(model_test_sc) plt.title("Effect of learning_rate", pad=20) plt.xlabel("Learning rate") plt.ylabel("Test accuracy of AdaBoost") plt.plot(x, y) plt.show()
结果分析:学习率为0.4、0.5测试精度都是最高的
选择 n_estimators=16,learning_rate=0.5得到预测精度为1