GBDT算法是集成学习树算法的一种。我们先来说下什么是集成学习。
集成学习
集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务。
集成学习的一般结构:先产生一组“个体学习器”,在用某种策略把这些学习器的结果结合起来。
集成学习可以集成
- 同质的学习器:基学习器全部是全是决策树,或者是全部是神经网络;
- 也可以结合不同类型的个体学习器:例如同时包含决策树和神经网络;
上图就是集成学习,基础的流程框架。
集成学习器有分为两大类:Boosting和Bagging。
Boosting集成学习
Boosting基本机制:
- 先从初始训练集中训练出来一个基学习器;
- 根据基学习器的表现,对训练样本的分布进行调整,调整的目标是:先前基学习器做错的样本得到更多的权重;
终止条件:直至基学习器数目达到实现指定的值T;
最终学习器使用的时候将T个基学习器的结果进行加权求和。
Bagging集成学习
集成学习效果的保证是:“基学习器尽可能的独立”。
因为“独立”在限时任务中无法做到,所以为了使基学习器尽可能具有较大的差异,有一种方法:给定一个训练数据集,对训练样本进行采样,产生出若干个不同的训练数据集,去训练每个单独的基学习器。
Bagging算法最重要的是其抽样方法:
- 给定包含m个样本的数据集;
- 随机取出一个样本放入采样集中;
- 再把该样本放回初始数据集;
- 这种方法抽样m次;
产生得到含m个样本的采样集。
再采取预测的时候,Bagging通常对分类任务使用简单的投票法。
因为我们今天主要讲的是GBDT算法,所以我们这边就简单的介绍下Boosting和Bagging算法。
集成学习器的效果为什么比基学习器效果要好
集成学习器通过将多个学习器进行结合,会比单一的学习器显著优越的泛化性能。这种对“弱学习器”尤其明显。
假设集成通过简单投票方式结合T个分类器,若有超过半数的基分类器准确,则集成分类准确。
根据Hoeffding不等式可知,集成错误率随着集成中个体分类器数目T的增大,集成的错误率将指数下降,最终趋向于零。
但是需要有一个关键的假设:
- 基学习器误差是相互独立的
所以集成学习主要的问题是如何产生并结合“好而不同”的个体学习器。
GBDT算法
GBDT的全称Gradient Boosting Decision Tree,梯度提升决策树。
GBDT算法的弱学习器只限定了是CART回归树模型。
基本思路:
- 第一轮训练的得到强学习器
- 计算损失函数值
- 需要优化得到,让下一轮的损失函数值尽量的小
GBDT的算法基本思路很简单,但是在GBDT中损失函数的拟合方法的计算方式不是那么简单。
Freidman提出了负梯度拟合的方法来解决这个问题。
GBDT在下一轮进行迭代的时候,首先算出训练集合:。
是这一轮需要迭代的残差。
算法流程
1)初始化弱学习器
2) 迭代:t = 1,2,3...T有
a) 对样本i1,2...m,计算负梯度
b) 拟合一棵CART回归树,得到第t棵回归树,对应的叶子节点区域为,其中J为回归树t的叶子节点的个数。
c) 对叶子区域j=1,2,....J,计算最佳拟合值
d) 更新强学习器
3) 强学习器f(x)的表达式
Demo
代码位置:https://github.com/zhangtengji/everyday-algo/tree/master/ensemble-learning/gbdt-demo
#!/usr/bin/env python
# -*- coding:utf8 -*-
"""gbdt algo running"""
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
__author__ = 'ztj'
train = pd.read_csv("../data/titanic/train.csv")
test = pd.read_csv("../data/titanic/test.csv")
print(train.info())
print(test.info())
# set "PassengerId" variable as index
train.set_index("PassengerId", inplace=True)
test.set_index("PassengerId", inplace=True)
# generate training target set (y_train)
y_train = train["Survived"]
# delete column "Survived" from train set
train.drop(labels="Survived", axis=1, inplace=True)
# shapes of train and test sets
print(train.shape)
print(test.shape)
# join train and test sets to form a new train_test set
train_test = train.append(test)
columns_to_drop = ["Name", "Age", "SibSp", "Ticket", "Cabin", "Parch", "Embarked"]
train_test.drop(labels=columns_to_drop, axis=1, inplace=True)
print('-----------------保留的columns-----------------')
print(train_test.columns)
# convert objects to numbers by pandas.get_dummies
train_test_dummies = pd.get_dummies(train_test, columns=["Sex"])
# check the dimension
train_test_dummies.shape
# replace nulls with 0.0
train_test_dummies.fillna(value=0.0, inplace=True)
# generate feature sets (X)
X_train = train_test_dummies.values[0:891]
X_test = train_test_dummies.values[891:]
X_train.shape, X_test.shape
# transform data
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_train_scale = scaler.fit_transform(X_train)
print('X_train shape:' + str(X_train.shape))
X_test_scale = scaler.transform(X_test)
# split training feature and target sets into training and validation subsets
from sklearn.model_selection import train_test_split
X_train_sub, X_validation_sub, y_train_sub, y_validation_sub = train_test_split(X_train_scale, y_train, random_state=0)
# import machine learning algorithms
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc
# train with Gradient Boosting algorithm
# compute the accuracy scores on train and validation sets when training with different learning rates
learning_rates = [0.05, 0.1, 0.25, 0.5, 0.75, 1]
for learning_rate in learning_rates:
gb = GradientBoostingClassifier(n_estimators=20, learning_rate=learning_rate, max_features=2, max_depth = 2, random_state = 0)
gb.fit(X_train_sub, y_train_sub)
print("Learning rate: ", learning_rate)
print("Accuracy score (training): {0:.3f}".format(gb.score(X_train_sub, y_train_sub)))
print("Accuracy score (validation): {0:.3f}".format(gb.score(X_validation_sub, y_validation_sub)))
print()
# Output confusion matrix and classification report of Gradient Boosting algorithm on validation set
gb = GradientBoostingClassifier(n_estimators=20, learning_rate=0.5, max_features=2, max_depth = 2, random_state = 0)
gb.fit(X_train_sub, y_train_sub)
predictions = gb.predict(X_validation_sub)
# ROC curve and Area-Under-Curve (AUC)
y_scores_gb = gb.decision_function(X_validation_sub)
fpr_gb, tpr_gb, _ = roc_curve(y_validation_sub, y_scores_gb)
roc_auc_gb = auc(fpr_gb, tpr_gb)
print("Area under ROC curve = {:0.2f}".format(roc_auc_gb))
print("Confusion Matrix:")
print(confusion_matrix(y_validation_sub, predictions))
print()
print("Classification Report")
print(classification_report(y_validation_sub, predictions))
if __name__ == '__main__':
pass
参考资料
- 《机器学习》-周志华