题目:详解Python AdaBoost算法的实现
什么是AdaBoost算法?
AdaBoost算法是一种利用加法模型(Additive Model)与前向分步算法(Forward Stagewise Algorithm)实现分类和回归任务的有力算法。AdaBoost中的“Ada”代表“Adaptive”,意思是“自适应”。AdaBoost在功能和设计上与支持向量机(SVM)非常相似,都可以使用多项式内核进行非线性分类和回归任务。
AdaBoost强大的分类器来自于将多个弱分类器进行加权组合,弱分类器是指分类效果仅略好于随机分类器的分类器。
AdaBoost训练过程
AdaBoost训练过程如下:
- 初始化训练集中每个样本的权重 $w_i=\frac1{n}$,其中 $n$ 为样本数。
- 针对当前训练集,训练一个弱分类器 $h_i(x)$,弱分类器一般采用决策树桩(即深度为1的决策树)来实现,用于对样本进行分类。分类器 $h_i(x)$ 的输出为 $+1$ 或 $-1$。
- 计算分类器 $h_i(x)$ 对该训练集中每个样本的分类错误率 $e_i$,即分类器将样本分为正确的和错误的的比例。
- 计算分类器 $h_i(x)$ 的权重 $\alpha_i$,权重越大的分类器对于最终集成分类器的贡献也越大。$\alpha_i=\frac12\log(\frac{1-e_i}{e_i})$。
- 更新训练集样本的权重 $w$,对于分类正确的样本减小权重、对于分类错误的样本增加权重。$w_i'=\frac{w_i}{Z}e^{-\alpha_iy_ih_i(x_i)}$,其中 $Z$ 为规范化因子,用于将更新后的权重总和变为1。
- 重复步骤2到5 $T$ 次,产生 $T$ 个弱分类器。
- 将 $T$ 个弱分类器进行加权组合形成最终的分类器 $H(x)=\text{sign}(\sum_{t=1}^T\alpha_th_t(x))$。
由于AdaBoost使用加权组合的方式产生最终的分类器,因此每个弱分类器的权重和分类错误率都影响着最终分类器的效果。
AdaBoost代码实现
Python中scikit-learn库提供了AdaBoost算法的实现,使用AdaBoost需要先安装scikit-learn库。以下以UCI的鸢尾花数据集为例来尝试使用AdaBoost算法分类。
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=7)
# 创建分类器
clf = DecisionTreeClassifier(max_depth=1)
# 创建AdaBoost分类器
ada = AdaBoostClassifier(base_estimator=clf)
# 训练分类器
ada.fit(X_train, y_train)
# 预测测试集数据
y_pred = ada.predict(X_test)
# 输出分类器预测结果
print(y_pred)
上述代码中,采用鸢尾花数据集加载,数据集特征包括花萼长度、花萼宽度、花瓣长度、花瓣宽度。首先将数据集划分成训练集和测试集。接着创建决策树桩分类器,然后使用AdaBoostClassifier创建AdaBoost分类器,并使用训练集对其进行训练,再使用测试集验证分类器的效果。最后输出预测结果。
除了scikit-learn库之外,我们也可以自己手动实现AdaBoost算法。以下使用一个简单的双峰数据集为例子进行解释。
import numpy as np
import matplotlib.pyplot as plt
# 生成数据集
def create_dataset(num):
X = np.zeros((num, 2))
y = np.zeros((num, 1))
for i in range(num):
x1 = np.random.normal(1.0, 0.5)
y1 = np.random.normal(2.0, 0.5)
x2 = np.random.normal(2.0, 0.5)
y2 = np.random.normal(1.0, 0.5)
if i % 2 == 0:
X[i] = [x1, y1]
y[i] = 1
else:
X[i] = [x2, y2]
y[i] = -1
return X, y
# 初始化训练集样本权重
def init_weight(num):
w = np.zeros((num, 1))
for i in range(num):
w[i] = 1 / num
return w
# 训练弱分类器
def train_clf(X, y, w):
num = X.shape[0]
min_error = float('inf')
for j in range(X.shape[1]):
feature = X[:, j]
dist = np.sort(feature)
for i in range(num - 1):
theta = (dist[i] + dist[i+1]) / 2
for k in [1, -1]:
error = np.dot(w.T, np.abs(y - k * np.sign(feature - theta)))
if error < min_error:
min_error = error
G = k * np.sign(feature - theta)
h_t = G
feature_idx = j
threshold = theta
alpha_t = 0.5 * np.log((1 - min_error) / min_error)
return h_t, feature_idx, threshold, alpha_t
# 根据弱分类器组合产生最终分类器
def predict(X, clfs, feature_idx, thresholds, alpha_ts):
num = X.shape[0]
Y = np.zeros((num, 1))
for i in range(len(alpha_ts)):
h_t = clfs[i]
feature = X[:, feature_idx[i]]
threshold = thresholds[i]
alpha_t = alpha_ts[i]
Y += alpha_t * (np.sign(feature - threshold) != np.sign(h_t))
return np.sign(Y)
# 训练AdaBoost分类器
def AdaBoost(X, y, num_iter):
num = X.shape[0]
w = init_weight(num)
clfs = []
feature_idx = []
thresholds = []
alpha_ts = []
for i in range(num_iter):
h_t, idx, threshold, alpha_t = train_clf(X, y, w)
clfs.append(h_t)
feature_idx.append(idx)
thresholds.append(threshold)
alpha_ts.append(alpha_t)
w = w * np.exp(-alpha_t * y * np.sign(h_t))
w /= w.sum()
return clfs, feature_idx, thresholds, alpha_ts
# 可视化
def plot(X, y, clfs, feature_idx, thresholds, alpha_ts):
X1 = X[np.where(y.flatten() == 1), :][0]
X2 = X[np.where(y.flatten() == -1), :][0]
plt.scatter(X1[:, 0], X1[:, 1], c='r')
plt.scatter(X2[:, 0], X2[:, 1], c='b')
x_min, x_max = min(X[:, 0]), max(X[:, 0])
y_min, y_max = min(X[:, 1]), max(X[:, 1])
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
Z = predict(np.c_[xx.ravel(), yy.ravel()], clfs, feature_idx, thresholds, alpha_ts)
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.15, cmap='coolwarm')
plt.show()
X, y = create_dataset(200)
clfs, feature_idx, thresholds, alpha_ts = AdaBoost(X, y, 20)
plot(X, y, clfs, feature_idx, thresholds, alpha_ts)
上述代码中,首先生成了一个双峰数据集用于分类,然后采用开局结束,即缺省权重,初始化数据集权重,接着训练弱分类器,并将训练好的弱分类器进行加权组合,生成最终的分类器。最后使用可视化方式展示最终分类器效果。
结语
本文简单介绍了AdaBoost算法的基本原理、训练过程和代码实现。通过通过scikit-learn库和手动实现方法使用了AdaBoost算法分类,并进行了一些简单的数据处理和可视化。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Python AdaBoost算法的实现 - Python技术站