1 项目简介
GBDT 的全称是 Gradient Boosting Decision Tree,梯度提升树,在传统机器学习算法中,GBDT 算的上 TOP3 的算法。
本开源项目完整讲解了梯度提升树的算法原理,剖析了 GBDT 的重要组件:决策树和梯度提升,包括 GBDT 算法的公式推导。本来试图将这些讲解完全编辑到公众号中,由于目前公众号对公式的支持很不友好,尽管花费了1个多小时,但公式的排版、格式依然混乱。Freemanzxp 将其发布在博客中,地址如下:
https://blog.youkuaiyun.com/zpalyq110/article/details/79527653
将重点转向作者实现的完整代码和例子阐述中 。利用 python 实现 GBDT 算法的回归、二分类以及多分类,代码完整,注释详细,并带有例子及其可视化,帮助大家庖丁解牛地理解 GBDT. 这个项目开源在了 Github 中,欢迎 star
https://github.com/Freemanzxp/GBDT_Simple_Tutorial
2 数据介绍
如下表所示:一组数据,特征为年龄、体重,身高为标签值。共有 5 条数据,前四条为训练样本,最后一条为要预测的样本。
编号 | 年龄(岁) | 体重(kg) | 身高(m)(标签值) |
---|---|---|---|
0 | 5 | 20 | 1.1 |
1 | 7 | 30 | 1.3 |
2 | 21 | 70 | 1.7 |
3 | 30 | 60 | 1.8 |
4 | 25 | 65 | ? |
3 完整代码
3.1 依赖环境
操作系统:Windows/Linux
编程语言:Python3
Python库:pandas、PIL、pydotplus,
其中pydotplus库会自动调用Graphviz,所以需要去Graphviz官网下载graphviz的-2.38.msi
,先安装,再将安装目录下的bin
添加到系统环境变量,此时如果再报错可以重启计算机。详细过程不再描述,网上很多解答。
3.2 文件结构
example.py 回归/二分类/多分类测试文件
GBDT 主模块文件夹
gbdt.py 梯度提升算法主框架
decision_tree.py 单颗树生成,包括节点划分和叶子结点生成
loss_function.py 损失函数
tree_plot.py 树的可视化
项目模块图
3.3 运行指南
回归测试:
python example.py --model = regression
二分类测试:
python example.py --model = binary_cf
多分类测试:
python example.py --model = multi_cf
其他可配置参数:
lr
-- 学习率,trees
-- 构建的决策树数量即迭代次数,depth
-- 决策树的深度,count
-- 决策树节点分裂的最小数据数量,is_log
-- 是否打印树的生成过程,is_plot
-- 是否可视化树的结构.结果文件: 运行后会生成
results
文件夹,里面包含了每棵树的内部结构和生成日志
3.4 完整代码
列举项目的其中两个核心模块 gbdt.py 和 decision_tree.py 的完整代码:
"""
Created on :2019/03/28
@author: Freeman, feverfc1994
"""
import abc
import math
import logging
import pandas as pd
from GBDT.decision_tree import Tree
from GBDT.loss_function import SquaresError, BinomialDeviance, MultinomialDeviance
from GBDT.tree_plot import plot_tree, plot_all_trees,plot_multi
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
class AbstractBaseGradientBoosting(metaclass=abc.ABCMeta):
def __init__(self):
pass
def fit(self, data):
pass
def predict(self, data):
pass
class BaseGradientBoosting(AbstractBaseGradientBoosting):
def __init__(self, loss, learning_rate, n_trees, max_depth,
min_samples_split=2, is_log=False, is_plot=False):
super().__init__()
self.loss = loss
self.learning_rate = learning_rate
self.n_trees = n_trees
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.features = None
self.trees = {}
self.f_0 = {}
self.is_log = is_log
self.is_plot = is_plot
def fit(self, data):
"""
:param data: pandas.DataFrame, the features data of train training
"""
# 掐头去尾, 删除id和label,得到特征名称
self.features = list(data.columns)[1: -1]
# 初始化 f_0(x)