参考:http://www.jianshu.com/p/1fa837221360
代码主要在gradient_boosting.py里面,定义了各种loss类以及estimator类,前者定义了loss的计算方式,后者是一些简单基本的estimator类,主要用于LossFunction中init_estimator的计算,即初始预测值的计算。
loss的类层级关系为:
注意:对于ClassificationLossFunction, 代码里计算loss和负梯度的时候,并不是用概率计算而是用决策树的直接累计输出score(pred)计算。
以BinomialDeviance为例,score转成概率要经过sigmoid转化。设p为概率,P为预测值,则BinomialDeviance的loss公式为
原来的公式变成
estimator类的层级关系:
estimator类都有自己的fit函数和predict函数,前者确定数值(均值、中位值等),后者用来输出预测值。除了一些estimator类和loss类,还有3个类:
1. BaseGradientBoosting
带有gb操作的父类,也是个抽象类,为所有的estimator定义了通用的fit函数,后面的分类树和回归树差别只在于loss function不同。
2. GradientBoostingClassifier
用于分类的GBDT,是BaseGradientBoosting的子类
3. GradientBoostingRegressor
用于回归的GBDT,是BaseGradientBoosting的子类
主要有以下几个方法:
- __init__: 传入了超参数,即包括boosting框架和决策树本身。比如loss是损失函数LossFunction的选择,learning_rate为学习率,n_estimators是boosting的次数(迭代次数或者Stage的个数)。通常learning_rate和n_estimators中需要做一个trade_off上的选择。 init参数指的是我们的初始化时候的弱学习器,即默认为每个LossFunction里面的init_estimator,用来计算初始预测值。 warm_start决定是否重用之前的结果并加入更多estimators,或者直接抹除之前的结果。
具体的参数含义可以看 http://www.cnblogs.com/pinard/p/6143927.html
_check_params: 检查超参数是否合法,以及初始化模型参数(包括所用的loss等),初始化了self.max_features_变量和所用的loss类别,变量为self.loss_。
_init_state: 初始化init_estimator以及model中的状态(中间有个six库用于处理跨Py2和Py3的兼容问题),根据self.loss_初始化self.init_,还有初始化self.estimators_, self.train_score_,self.oob_improvement_( 事先根据预设迭代次数申请好空间 ),后三个都是数组,分别存储每一个单模型对应的estimator、训练集得分和outofbag评估的进步。
_clear_state: 清除模型状态,把上面四个变量del掉
_resize_state:调整n_estimators,并调整上面四个变量的size
fit: 训练模型的方法,主要的操作有:
_fit_stages: 迭代训练模型。每次迭代中,
_fit_stage:单次训练模型,其中 loss.K针对的是多分类问题,回归和二分类时K为1 。对于每一类,操作主要有:
# 计算每个样本对应到树的哪一个叶子节点
terminal_regions = tree.apply(X)
# 将outofbag的样本的结果都置为-1(不参与训练过程)
masked_terminal_regions = terminal_regions.copy()
masked_terminal_regions[~sample_mask] = -1
# 更新每个叶子节点上的value,tree.children_left == TREE_LEAF是判断叶子节点的方法。一个很关键的点是这里只更新了叶子节点,而只有LossFunction是LeastSquaresError时训练时生成的决策树上的value和我们实际上想要的某个节点的预测值是一致的。
for leaf in np.where(tree.children_left == TREE_LEAF)[0]:
# _update_terminal_region由每个具体的损失函数具体实现,在LossFunction基类中只提供模板
self._update_terminal_region(tree, masked_terminal_regions, leaf, X, y, residual, y_pred[:, k], sample_weight)
# 更新预测值,tree预测的是负梯度值,预测值通过加上学习率 * 负梯度来更新,这里更新所有inbag和outofbag的预测值
y_pred[:, k] += (learning_rate * tree.value[:, 0, 0].take(terminal_regions, axis=0))
_decision_function: 内部用来输出预测值的函数,fit利用已有模型计算初始预测值的时候用到, 在两个子类中也用到。首先调用_init_decision_function得到初始预测值,然后再调用predict_stages获得累计预测值。
_staged_decision_function: 和上面类似,但是是获取每一个stage的预测值
feature_importances_: 计算公式是每个特征在每个stage所有树的importance的均值之和的均值
_apply:返回样本在每个estimator落入的叶子节点编号。输入尺寸为[n_samples, n_features],输出尺寸为[n_samples, n_estimators, n_classes],Regressor只有前两个维度。
_validate_y
可用loss为’deviance’, ‘exponential’,即ExponentialLoss, MultinomialDeviance, BinomialDeviance。
要注意的是, Classifier用的基分类器也是DecisionTreeRegressor ,Regressors输出的累计预测值要先经过转换才会是类别概率。
新增:
可用loss为’ls’, ‘lad’, ‘huber’, ‘quantile’,即LeastSquaresError, LeastAbsoluteError, HuberLossFunction, QuantileLossFunction。