假设您现在已经熟悉了随机森林的工作原理和OOP,现在让我们开始用Python实现我们自己版本的随机森林。然后,我们将把结果与Sci-kit learn的RandomForestRegressor实现进行比较。
在这里,我们定义了一个名为TreeEnsemble的类。
构造函数__init__在每次启动时都会创建一个TreeEnsemble对象。参数描述如下:
X:输入X矩阵y:因变量n_trees:n _ trees的个数:Ensemble sample_sz:传递给每棵树的X矩阵的样本大小(减少过拟合,因为每棵树不能访问完整的输入X)min_leaf:停止进一步分裂self的元素个数trees=是Python中的一个列表合成,它创建n _ trees的个数,这是create_tree()方法首先从X矩阵中选择一个等于样本大小的随机索引。然后将这些随机索引传递给决策树。每个决策树接收相同样本大小的不同索引排列。(如果你对我们为什么要把随机索引传递给决策树感到困惑,那么这是为了最小化每个估计量之间的相关性,创建弱分类器,它们共同构成强分类器。)predict()方法返回每行每棵树的预测均值,最终得到随机森林的预测结果。所以调用np.mean(,axis=0)会从len(self.trees)中的每棵树得到预测数,并得到它们的mean(),从而得到树整合的最终预测,也就是随机森林。
你可能已经注意到,在我们自顶向下的方法中,我们假设决策树已经存在。现在,我们将实现一个决策树对象,并一起创建我们的随机森林集。
这里,我们定义了类DecisionTree()并将所有参数传递给TreeEnsemble(),只有n_trees是不相关的。
决策树构造函数__init__创建了一个决策树实例,它具有与我们的随机森林相同的变量和含义。我们只关心创建分裂和返回每棵树的预测。
Self.n,self.c=len(idxs),shape1,只需在self.n中存储行数,在self.c中存储列数。Self.val是给定节点的预测值,即给定节点所有样本的因变量值的均值()。
看看使用Ames Housing机器学习数据集创建的决策树
住宅数据
在每个节点,从顶部开始,我们有123,250,90,133.样本数,最低节点有67个样本。对于每个节点,决策树的预测值只是节点中每个样本的因变量的平均值。
因此,顶部节点的预测值为11.807,底部节点的预测值为12.775。
接下来,我们需要一种在决策树中跟踪信息增益的方法,以获得最佳分割。这是使用一个分数变量来完成的,该变量指示分割的好坏。由于所有其他节点leaf_nodes都有分数,而此时我们还没有做任何分割,最初分数是无穷大。
接下来,我们继续介绍find_varsplit()方法,该方法为提供最大信息增益或最大错误损失的变量值对找到最佳输出。为此,我们调用find_bettersplit()方法,我们将在本文稍后定义该方法,并首先准备所有其他部分。
我们还定义了某些属性,例如:
Split_name它返回要拆分的列/变量split_col:这个特定列的值是_leaf返回给定节点是否为叶子的值。
在这个阶段,我们初始化了随机森林类和决策树类。难题的下一部分是定义一个在每个节点上分裂的方法。这是使用find_better_split()方法实现的,如下所述。
如果您还记得的话,决策树通过循环遍历每个变量来查找拆分,这是可能的值,并返回变量值具有最高信息增益的对。
基于分割条件,分割将样本分割为左和右。Self.n表示观察的行数。因此,对于每个索引,我们遍历每一行,为该行的每个值拆分样本,并基于拆分定义lhs和rhs。
。如果lhs或rhs中的样本数量大于min_samples_leaf,则继续并存储standard_deviation左侧和右侧各自的值。最小化std偏差与最小化RMSE相同。(为什么?将每个分裂想象成猫和狗之间的二元分裂。我们希望每个分裂在每一侧都有同质的分类,即一侧是猫,另一侧是狗。因此,最小化std_error)
每个值/观察值处的split的curr_score定义为lhs和rhs的平均得分。如果找到一个分数较低的更好的variable-value对,则将该变量传递给var_idx,并将行传递给self.split。我们继续这个过程,直到找到最好的拆分。
对于每个观察,树循环遍历每个列self.c到find_better_split。如果节点是is_leaf,我们可以停止该进程,因为不能进一步拆分叶节点。如果它不是叶节点,则将x定义为进行拆分的列,根据拆分值创建lhs和rhs,并在左侧和右侧递归创建决策树,该决策树将被进一步拆分,直到到达叶节点。
lass TreeEnsemble(): def __init__(self, x, y, n_trees, sample_sz, min_leaf=5): np.random.seed(42) self.x,self.y,self.sample_sz,self.min_leaf = x,y,sample_sz,min_leaf self.trees =