介绍
随机森林 (Random Forests) 是一种利用决策树作为基学习器的 Bagging 集成学习算法。随机森林模型的构建过程如下:
数据采样
作为一种 Bagging 集成算法,随机森林同样采用有放回的采样,对于总体训练集 (T),抽样一个子集 (T_{sub}) 作为训练样本集。除此之外,假设训练集的特征个数为 (d),每次仅选择 (k\left(k < d\right)) 个构建决策树。因此,随机森林除了能够做到样本扰动外,还添加了特征扰动,对于特征的选择个数,推荐值为 (k = \log_2 d) 。
树的构建
每次根据采样得到的数据和特征构建一棵决策树。在构建决策树的过程中,会让决策树生长完全而不进行剪枝。构建出的若干棵决策树则组成了最终的随机森林。
随机森林在众多分类算法中表现十分出众 7,其主要的优点包括:
- 由于随机森林引入了样本扰动和特征扰动,从而很大程度上提高了模型的泛化能力,尽可能地避免了过拟合现象的出现。
- 随机森林可以处理高维数据,无需进行特征选择,在训练过程中可以得出不同特征对模型的重要性程度。
- 随机森林的每个基分类器采用决策树,方法简单且容易实现。同时每个基分类器之间没有相互依赖关系,整个算法易并行化。
安装
1 | pip install -U scikit-learn |
安装 graphviz 一个对dot文件进行绘图的软件,可以用于对模型进行可视化。
数据准备
数据准备包括训练集和测试集两部分的数据准备(也可以是一批数据按比例进行拆分,一部分作为训练一部分作为测试)
这里可以下载一份测试数据
数据格式如下(前30行):
1 | id,N_Days,Drug,Age,Sex,Ascites,Hepatomegaly,Spiders,Edema,Bilirubin,Cholesterol,Albumin,Copper,Alk_Phos,SGOT,Tryglicerides,Platelets,Prothrombin,Stage,Status |
打眼一看,我们可以看到数据中有很多文本/类别的信息是使用字符串进行表示的,所以在进行文本读取后,我们需要对数据进行一个整体的预处理过程。
1 | import pandas as pd |
数据概览
1 | import sweetviz |
模型训练
1 | # 模型(也可用单个决策树) |
基于此,我们就完成了一个最基本的模型构建,也可以通过这个模型进行简单的数据分析/预测,完成了入门,当然这个随便确定参数的模型性能可能并不完善,所以接下来我们就要看看怎么进行调参优化。
指标筛选
指标权重
1 | from sklearn.ensemble import RandomForestClassifier |
就可以得到每个指标在最终建模时的权重(权重综合为1),格式如下
1 | 1) Bilirubin 0.195250 |
当变量参数非常多的时候,我们可以基于每个指标的权重进行筛选,对输入参数进行精简。比如在我们这个数据集中,Bilirubin,N_Days等指标重要性比较高,而对应的Ascites、Sex、Drug等指标重要性就相对较低。
参数调优
逐步调优
借助交叉验证得分确定最有决策树数目。
在随机森林里面,决策树越多,在对训练集的建模表现越好,但是对应的资源需求也就越大。所以有时候,我们需要进行评估,构建多少颗决策树更合适。这时候,我们可以使用 cross_val_score 进行不同梯度交叉验证
1 | superpa=[] |
确定决策树数目后,确定决策树深度
基于上述确定的决策数数目,对决策树的最大深度进行遍历,确定最大决策树深度
1 | superpa=[] |
网格调优
1 | from sklearn.ensemble import RandomForestClassifier |
模型可视化
1 | # 提取一个决策树 |
得到的随机森林某一个决策树判断逻辑如下:
模型应用
通过上述步骤,我们已经成功的得到我们所需要的一个随机森林模型 model ,杰西莱我们就需要使用我们的模型,对于全新的测试数据进行处理。
1 | # 因为一般训练集和测试集的数据格式是一样的,所以我们对训练集进行的数据处理过程需要同时对测试集进行处理。 |
自定义优化预测结果
随机森林本身事基于多颗决策树的预测结果。由于每颗树所以来的输入信息事不完全一致的,因此不同的数据集,每颗决策树的表现也会有所不同。
如果偏差不大,一般我们会直接使用每颗树的结果计算均值作为最终结果。但是有时候我们也可以通过自定义函数,对预测结果进行优化。
比如下面的这个示例,我们首先获得每颗决策树的预测结果,然后对所有决策树预测结果进行排序,然后剔除前5%和后5%的数据,然后求平均值作为最终预测结果。相比直接计算均值,可以具有更好的鲁棒性。
1 | def predict_fit(model,data,feature_columns): |