GcForest原理
gcforest采用Cascade结构,也就是多层级结构,每层由四个随机森林组成,两个随机森林和两个极端森林,每个极端森林包含1000(超参数)个完全随机树,每个森林都会对的数据进行训练,每个森林都输出结果,我们把这个结果叫做森林生成的类向量,为了避免过拟合,我们喂给每个森林训练的数据都是通过k折交叉验证的,每一层最后生成四个类向量,下一层以上一层的四个类向量以及原有的数据为新的train data进行训练,如此叠加,最后一层将类向量进行平均,作为预测结果
个人认为这种结构非常类似于神经网络,神经网络的每个单位是神经元,而深度森林的单位元却是随机森林,单个随机森林在性能上强于单个神经元的,这就是使得深度森林很多时候尽管层级和基础森林树不多,也能取得好的结果的主要原因
GcForest代码实现原理图
我们需要做出一个layer的结构,每个layer由二种四个森林组成
每个layer都输出两个结果:每个森林的预测结果、四个森林的预测的平均结果
为了防止过拟合我们的layer都由k折交叉验证产生
同时为了保留数据全部的特征我们将得到的小layer叠在一起定义一个Biger Layer
之后我们就可以构建深度森林了
GcForest代码
layer.py
extraTree(极端树)使用的所有的样本,只是特征是随机选取的,因为分裂是随机的,所以在某种程度上比随机森林得到的结果更加好
from sklearn.ensemble import ExtraTreesRegressor#引入极端森林回归
from sklearn.ensemble import RandomForestRegressor#引入随机森林回归
import numpy as np
class Layer:#定义层类
def __init__(self, n_estimators, num_forests, max_depth=30, min_samples_leaf=1):
self.num_forests = num_forests # 定义森林数
self.n_estimators = n_estimators # 每个森林的树个数
self.max_depth = max_depth#每一颗树的最大深度
self.min_samples_leaf = min_samples_leaf#树会生长到所有叶子都分到一个类,或者某节点所代表的样本数已小于min_samples_leaf
self.model = []#最后产生的类向量
def train(self, train_data, train_label, weight, val_data):#训练函数
val_prob = np.zeros([self.num_forests, val_data.shape[0]])#定义出该层的类向量,有self.num_forersts行,val_data.shape[0]列,这里我们认为val_data应该就是我们的weight
for forest_index in range(self.num_forests):#对具体的layer内的森林进行构建
if forest_index % 2 == 0:#如果是第偶数个设为随机森林
clf = RandomForestRegressor(n_estimators=self.n_estimators#子树的个数,
n_jobs=-1, #cpu并行树,-1表示和cpu的核数相同
max_depth=self.max_depth,#最大深度
min_samples_leaf=self.min_samples_leaf)
clf.fit(train_data, train_label, weight)#weight是取样比重Sample weights
val_prob[forest_index, :] = clf.predict(val_data)#记录类向量
else:#如果是第奇数个就设为极端森林
clf = ExtraTreesRegressor(n_estimators=self.n_estimators,#森林所含树的个数
n_jobs=-1, #并行数
max_depth=self.max_depth,#最大深度
min_samples_leaf=self.min_samples_leaf