2020-05-19 第十章 决策树与随机森林(python)

01 决策树节点字段的选择

模型介绍

决策树属于经典的十大数据挖掘算法之一,是一种类似于流程图的树结构,其规则就是IF...THEN...的思想,可以用于数值型因变量的预测和离散型因变量的分类。
该算法简单直观、通俗易懂,不需要研究者掌握任何领域知识或复杂的数学推理,而且算法的结果输出具有很强的解释性。

image.png

图中的决策树呈现自顶向下的生长过程,深色的椭圆表示树的根节点;浅色的椭圆表示树的中间节点;方框则表示树的叶节点。
对于所有的非叶节点来说,都是用来表示条件判断,而叶节点则存储最终的分类结果,例如中年分支下的叶节点(4,0)表示4位客户购买,0位客户不购买。

信息增益

熵原本是物理学中的一个定义,后来香农将其引申到了信息论领域,用来表示信息量的大小。信息量越大(分类越不“纯净”),对应的熵值就越大,反之亦然。信息熵的计算公式如下:

image.png

在实际应用中,会将概率p_k的值用经验概率替换,所以经验信息熵可以表示为:
image.png

举例:以产品是否被购买为例,假设数据集一共包含14个样本,其中购买的用户有9个,没有购买的用户有5个,所以对于是否购买这个事件来说,它的经验信息熵为:
image.png

条件熵
image.png

其中,P(A_i)表示 A事件的第i种值对应的概率;H(D_k|A_i)为已知A_i的情况下,D事件为k值的条件熵,其对应的计算公式为P(D_k|A_i)log_2P(D_k|A_i)|D_i|表示A_i的频数,|D_i|/|D|表示A_i在所有样本中的频率;|D_ik|表示A_i下D事件为k值的频数,|D_ik|/|D_i|表示所有A_i中,D事件为k值的频率。
Gain_A(D)=H(D)−H(D|A):
对于已知的事件A来说,事件D的信息增益就是D的信息熵与A事件下D的条件熵之差,事件A对事件D的影响越大,条件熵H(D|A)就会越小(在事件A的影响下,事件D被划分得越“纯净”),体现在信息增益上就是差值越大,进而说明事件D的信息熵下降得越多。
所以,在根节点或中间节点的变量选择过程中,就是挑选出各自变量下因变量的信息增益最大的。
image.png

决策树中的ID3算法使用信息增益指标实现根节点或中间节点的字段选择,但是该指标存在一个非常明显的缺点,即信息增益会偏向于取值较多的字段。
为了克服信息增益指标的缺点,提出了信息增益率的概念,它的思想很简单,就是在信息增益的基础上进行相应的惩罚。信息增益率的公式可以表示为:
image.png

其中,H_A为事件A的信息熵。事件A的取值越多, Gain_A(D)可能越大,但同时H_A也会越大,这样以商的形式就实现了Gain_A(D)的惩罚。
image.png

image.png

从上面的计算结果可知,Age变量的信息增益率仍然是最大的,所以在根节点处仍然选择Age变量进行判断和分支。

基尼指数

决策树中的C4.5算法使用信息增益率指标实现根节点或中间节点的字段选择,但该算法与ID3算法一致,都只能针对离散型因变量进行分类,对于连续型的因变量就显得束手无策了。
为了能够让决策树预测连续型的因变量,Breiman等人在1984年提出了CART算法,该算法也称为分类回归树,它所使用的字段选择指标是基尼指数。

image.png

image.png

假设表中的Edu表示客户的受教育水平,Credit为客户在第三方的信用记录,Loan为因变量,表示银行是否对其发放贷款。根据基尼指数的公式,可以计算Loan变量的基尼指数值:
image.png

条件基尼指数
image.png

其中,P(A_i)表示 A变量在某个二元划分下第i组的概率,其对应的经验概率为|D_i|/|D|,即A变量中第i组的样本量与总样本量的商;Gini(D_k|A_i)表示在已知分组A_i的情况下,变量D取第k种值的条件基尼指数,其中|D_ik|/|D_i|表示分组A_i内变量D取第k种值的频率。
image.png

基尼指数增益

与信息增益类似,还需要考虑自变量对因变量的影响程度,即因变量的基尼指数下降速度的快慢,下降得越快,自变量对因变量的影响就越强。下降速度的快慢可用下方式子衡量:


image.png

决策树模型的Python函数

DecisionTreeClassifier(criterion='gini', splitter='best', 
                                    max_depth=None,min_samples_split=2, 
                                    min_samples_leaf=1,
                                    min_weight_fraction_leaf=0.0,max_features=None,            
                                    random_state=None, max_leaf_nodes=None,                                
                                    min_impurity_decrease=0.0, min_impurity_split=None, 
                                    class_weight=None, presort=False)

criterion:用于指定选择节点字段的评价指标,对于分类决策树,默认为'gini',表示采用基尼指数选择节点的最佳分割字段;对于回归决策树,默认为'mse',表示使用均方误差选择节点的最佳分割字段
splitter:用于指定节点中的分割点选择方法,默认为'best',表示从所有的分割点中选择最佳分割点;如果指定为'random',则表示随机选择分割点
max_depth:用于指定决策树的最大深度,默认为None,表示树的生长过程中对深度不做任何限制
min_samples_split:用于指定根节点或中间节点能够继续分割的最小样本量, 默认为2
min_samples_leaf:用于指定叶节点的最小样本量,默认为1
min_weight_fraction_leaf:用于指定叶节点最小的样本权重,默认为None,表示不考虑叶节点的样本权值
max_features:用于指定决策树包含的最多分割字段数,默认为None,表示分割时使用所有的字段,与指定'auto'效果一致;如果为具体的整数,则考虑使用对应的分割字段数;如果为0~1的浮点数,则考虑对应百分比的字段个数;如果为'sqrt',则表示最多考虑√P个字段;如果为'log2',则表示最多使用log_2P个字段
random_state:用于指定随机数生成器的种子,默认为None,表示使用默认的随机数生成器
max_leaf_nodes:用于指定最大的叶节点个数,默认为None,表示对叶节点个数不做任何限制
min_impurity_decrease:用于指定节点是否继续分割的最小不纯度值,默认为0
min_impurity_split:同参数min_impurity_decrease含义一致,该参数已在0.21版本剔除
class_weight:用于指定因变量中类别之间的权重,默认为None,表示每个类别的权重都相等;如果为balanced,则表示类别权重与原始样本中类别的比例成反比;还可以通过字典传递类别之间的权重差异,其形式为{class_label:weight}
presort:bool类型参数,是否对数据进行预排序,默认为False。如果数据集的样本量比较小,设置为True可以提高模型的执行速度;如果数据集的样本量比较大,则不易设置为True

02 决策树的剪枝技术

误差降低剪枝法

image.png
  • 将决策树的某个非叶子节点作为剪枝的候选对象(如图中的x_3处节点),如果将其子孙节点删除(对应的两个叶节点),则x_3处的节点就变成了叶节点。
  • 利用投票原则,将此处叶节点中频数最高的类别用作分类标准(如图中剪枝后该叶节点属于类A)。
  • 利用剪枝后的新树在测试数据集上进行预测,然后对比新树与老树在测试集上的误判样本量,如果新树的误判样本量低于老树的误判样本量,则将x_3处的中间节点替换为叶节点,否则不进行剪枝。
  • 重复前面的三步,直到新的决策树能够最大限度地提高测试数据集上的预测准确率。

悲观剪枝法

image.png

其中,e^′(T)表示剪枝后中间节点T被换成叶节点的误判率;e^′(T_t)表示中间节点T剪枝前其对应的所有叶节点的误判率;E(T)为中间节点T处的误判个数;E(t_i)为节点T下的所有叶节点误判个数;L表示中间节点T对应的所有叶节点个数;N表示中间节点T的样本个数;N_i表示各叶节点中的样本个数,其实∑_i^L N_{i=1}=N
image.png

剪枝标准

对比剪枝前后叶节点误判率的标准就是,如果剪枝后叶节点的误判率期望在剪枝前叶节点误判率期望的一个标准差内,则认为剪枝是合理的,否则不能剪枝。

在决策树图中,假设以T_2节点为例,剪枝前对应了3个叶节点,误判个数分别为3,2,0;如果将其所有叶节点都剪掉,T_2便成为了T_1的叶节点,误判样本数为7。根据计算公式,可以得到:


image.png

代价复杂度剪枝法

从字面理解,该剪枝方法涉及两则信息,一则是代价,是指将中间节点替换为叶节点后误判率会上升;另一则是复杂度,是指剪枝后叶节点的个数减少,进而使模型的复杂度下降。为了平衡上升的误判率与下降的复杂度,需要加入一个系数a,故可以将代价复杂度剪枝法的目标函数写成:

image.png

其中,C(T)=∑_{i=1}^L N_i×H(i);i表示节点T下第i个叶节点;N_i为第i个叶节点的样本量;H(i)为第i个叶节点的信息熵;|N_leaf|为节点T对应的所有叶节点个数;a就是调节参数。问题是参数a该如何计算呢?
节点T剪枝前的目标函数值为:
image.png

节点T剪枝后的目标函数值为:
image.png

C_α(T)_before=C_α(T)_after,得到:
image.png

image.png

剪枝过程
(1)对于一棵充分生长的树,不妨含有4个非叶子节点和5个叶子节点,根据计算a值的公式,可以得到所有非叶子节点对应的a值。
(2)挑选出最小的a值,不妨为α_3,然后对T_3进行剪枝,使其成为叶子节点,便得到一棵新树。
(3)接下来重新计算剩余非叶子节点所对应的a值。
(4)不断重复(2)和(3),直到决策树被剪枝成根节点,最终得到N棵新树。
(5)将测试数据集运用到N棵新树中,再从中挑选出误判率最低的树作为最佳的决策树。

03 随机森林的思想解读

思想解读

image.png
  • 利用Bootstrap抽样法,从原始数据集中生成k个数据集,并且每个数据集都含有N个观测和P个自变量。
  • 针对每一个数据集,构造一棵CART决策树,在构建子树的过程中,并没有将所有自变量用作节点字段的选择,而是随机选择p个字段。
  • 让每一棵决策树尽可能地充分生长,使得树中的每个节点尽可能“纯净”,即随机森林中的每一棵子树都不需要剪枝。
  • 针对k棵CART树的随机森林,对分类问题利用投票法,将最高得票的类别用于最终的判断结果;对回归问题利用均值法,将其用作预测样本的最终结果。

随机森林的Python函数

RandomForestClassifier(n_estimators=10, criterion='gini', max_depth=None, 
                                       min_samples_split=2, min_samples_leaf=1, 
                                    min_weight_fraction_leaf=0.0, max_features='auto', 
                    max_leaf_nodes=None, min_impurity_decrease=0.0, 
                    min_impurity_split=None, bootstrap=True, 
                    oob_score=False, n_jobs=1, random_state=None, 
                    verbose=0, warm_start=False, class_weight=None)

n_estimators:用于指定随机森林所包含的决策树个数
criterion:用于指定每棵决策树节点的分割字段所使用的度量标准,用于分类的随机森林,默认的criterion值为'gini';用于回归的随机森林,默认的criterion值为'mse'
max_depth:用于指定每棵决策树的最大深度,默认不限制树的生长深度
min_samples_split:用于指定每棵决策树根节点或中间节点能够继续分割的最小样本量, 默认为2
min_samples_leaf:用于指定每棵决策树叶节点的最小样本量,默认为1
min_weight_fraction_leaf:用于指定每棵决策树叶节点最小的样本权重,默认为None,表示不考虑叶节点的样本权值
max_features:用于指定每棵决策树包含的最多分割字段数,默认为None,表示分割时使用所有的字段
max_leaf_nodes:用于指定每棵决策树最大的叶节点个数,默认为None,表示对叶节点个数不做任何限制
min_impurity_decrease:用于指定每棵决策树的节点是否继续分割的最小不纯度值,默认为0
bootstrap:bool类型参数,是否对原始数据集进行bootstrap抽样,用于子树的构建,默认为True
oob_score:bool类型参数,是否使用包外样本计算泛化误差,默认为False,包外样本是指每次bootstrap抽样时没有被抽中的样本
n_jobs:用于指定计算随机森林算法的CPU个数,默认为1
random_state:用于指定随机数生成器的种子,默认为None,表示使用默认的随机数生成器
verbose:用于指定随机森林计算过程中是否输出日志信息,默认为0,表示不输出
warm_start:bool类型参数,是否基于上一次的训练结果进行本次的运算,默认为False
class_weight:用于指定因变量中类别之间的权重,默认为None,表示每个类别的权重都相等

04 决策树与随机森林的应用实战

Titanic幸存分类--决策树

# 导入第三方模块
import pandas as pd
# 读入数据
Titanic = pd.read_csv('./Titanic.csv')
Titanic.head()

# 删除无意义的变量,并检查剩余自字是否含有缺失值
Titanic.drop(['PassengerId','Name','Ticket','Cabin'], axis = 1, inplace = True)
Titanic.isnull().sum(axis = 0)

# 对Sex分组,用各组乘客的平均年龄填充各组中的缺失年龄
fillna_Titanic = []
for i in Titanic.Sex.unique():
    update = Titanic.loc[Titanic.Sex == i,].fillna(value = {'Age': Titanic.Age[Titanic.Sex == i].mean()}, inplace = False)
    fillna_Titanic.append(update)
Titanic = pd.concat(fillna_Titanic)
# 使用Embarked变量的众数填充缺失值
Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=True)
Titanic.head()

# 将数值型的Pclass转换为类别型,否则无法对其哑变量处理
Titanic.Pclass = Titanic.Pclass.astype('category')
# 哑变量处理
dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']])
# 水平合并Titanic数据集和哑变量的数据集
Titanic = pd.concat([Titanic,dummy], axis = 1)
# 删除原始的Sex、Embarked和Pclass变量
Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1)
Titanic.head()

读入数据清洗结果:

In [2]: # 导入第三方模块
   ...: import pandas as pd
   ...: # 读入数据
   ...: Titanic = pd.read_csv('./Titanic.csv')
   ...: Titanic.head()
Out[2]:
   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns]

In [3]: # 删除无意义的变量,并检查剩余自字是否含有缺失值
   ...: Titanic.drop(['PassengerId','Name','Ticket','Cabin'], axis = 1, inplace
   ...: = True)
   ...: Titanic.isnull().sum(axis = 0)
   ...:
Out[3]:
Survived      0
Pclass        0
Sex           0
Age         177
SibSp         0
Parch         0
Fare          0
Embarked      2
dtype: int64

In [4]: # 对Sex分组,用各组乘客的平均年龄填充各组中的缺失年龄
   ...: fillna_Titanic = []
   ...: for i in Titanic.Sex.unique():
   ...:     update = Titanic.loc[Titanic.Sex == i,].fillna(value = {'Age': Titan
   ...: ic.Age[Titanic.Sex == i].mean()}, inplace = False)
   ...:     fillna_Titanic.append(update)
   ...: Titanic = pd.concat(fillna_Titanic)
   ...: # 使用Embarked变量的众数填充缺失值
   ...: Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=
   ...: True)
   ...: Titanic.head()
Out[4]:
   Survived  Pclass   Sex        Age  SibSp  Parch     Fare Embarked
0         0       3  male  22.000000      1      0   7.2500        S
4         0       3  male  35.000000      0      0   8.0500        S
5         0       3  male  30.726645      0      0   8.4583        Q
6         0       1  male  54.000000      0      0  51.8625        S
7         0       3  male   2.000000      3      1  21.0750        S

In [5]: # 将数值型的Pclass转换为类别型,否则无法对其哑变量处理
   ...: Titanic.Pclass = Titanic.Pclass.astype('category')
   ...: # 哑变量处理
   ...: dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']])
   ...: # 水平合并Titanic数据集和哑变量的数据集
   ...: Titanic = pd.concat([Titanic,dummy], axis = 1)
   ...: # 删除原始的Sex、Embarked和Pclass变量
   ...: Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1)
   ...: Titanic.head()
Out[5]:
   Survived        Age  SibSp  Parch  ...  Embarked_S  Pclass_1  Pclass_2  Pclass_3
0         0  22.000000      1      0  ...           1         0         0         1
4         0  35.000000      0      0  ...           1         0         0         1
5         0  30.726645      0      0  ...           0         0         0         1
6         0  54.000000      0      0  ...           1         1         0         0
7         0   2.000000      3      1  ...           1         0         0         1

[5 rows x 13 columns]
# 导入第三方包
from sklearn import model_selection
# 取出所有自变量名称
predictors = Titanic.columns[1:]
# 将数据集拆分为训练集和测试集,且测试集的比例为25%
X_train, X_test, y_train, y_test = model_selection.train_test_split(Titanic[predictors], Titanic.Survived, 
  test_size = 0.25, random_state = 1234)
  
# 导入第三方模块
from sklearn.model_selection import GridSearchCV
from sklearn import tree
# 预设各参数的不同选项值
max_depth = [2,3,4,5,6]
min_samples_split = [2,4,6,8]
min_samples_leaf = [2,4,8,10,12]
# 将各参数值以字典形式组织起来
parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split, 'min_samples_leaf':min_samples_leaf}
# 网格搜索法,测试不同的参数值
grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), param_grid = parameters, cv=10)
# 模型拟合
grid_dtcateg.fit(X_train, y_train)
# 返回最佳组合的参数值
grid_dtcateg.best_params_

# 导入第三方模块
from sklearn import metrics
# 构建分类决策树
CART_Class = tree.DecisionTreeClassifier(max_depth=3, min_samples_leaf = 4, min_samples_split=2)
# 模型拟合
decision_tree = CART_Class.fit(X_train, y_train)
# 模型在测试集上的预测
pred = CART_Class.predict(X_test)
# 模型的准确率
print('模型在测试集的预测准确率:\n',metrics.accuracy_score(y_test, pred))

在ipython中的结果:

In [6]: # 导入第三方包
   ...: from sklearn import model_selection
   ...: # 取出所有自变量名称
   ...: predictors = Titanic.columns[1:]
   ...: # 将数据集拆分为训练集和测试集,且测试集的比例为25%
   ...: X_train, X_test, y_train, y_test = model_selection.train_test_split(Tita
   ...: nic[predictors], Titanic.Survived,
   ...:   test_size = 0.25, random_state = 1234)

In [7]: # 导入第三方模块
   ...: from sklearn.model_selection import GridSearchCV
   ...: from sklearn import tree
   ...: # 预设各参数的不同选项值
   ...: max_depth = [2,3,4,5,6]
   ...: min_samples_split = [2,4,6,8]
   ...: min_samples_leaf = [2,4,8,10,12]
   ...: # 将各参数值以字典形式组织起来
   ...: parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_spl
   ...: it, 'min_samples_leaf':min_samples_leaf}
   ...: # 网格搜索法,测试不同的参数值
   ...: grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), p
   ...: aram_grid = parameters, cv=10)
   ...: # 模型拟合
   ...: grid_dtcateg.fit(X_train, y_train)
   ...: # 返回最佳组合的参数值
   ...: grid_dtcateg.best_params_
Out[7]: {'max_depth': 6, 'min_samples_leaf': 8, 'min_samples_split': 4}

In [8]: # 导入第三方模块
   ...: from sklearn import metrics
   ...: # 构建分类决策树
   ...: CART_Class = tree.DecisionTreeClassifier(max_depth=3, min_samples_leaf =
   ...:  4, min_samples_split=2)
   ...: # 模型拟合
   ...: decision_tree = CART_Class.fit(X_train, y_train)
   ...: # 模型在测试集上的预测
   ...: pred = CART_Class.predict(X_test)
   ...: # 模型的准确率
   ...: print('模型在测试集的预测准确率:\n',metrics.accuracy_score(y_test, pred
   ...: ))
模型在测试集的预测准确率:
 0.8295964125560538

绘图:

# 导入第三方包
import matplotlib.pyplot as plt
y_score = CART_Class.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)

# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()  
Figure_1.png

Titanic幸存分类--随机森林

需要在电脑中安装Graphviz,在下面的链接中下载适合自己电脑的版本
https://graphviz.gitlab.io/download/
mac下的Graphviz安装及使用参考:https://blog.csdn.net/qq_36847641/article/details/78224910
windows下Graphviz安装及入门教程:https://www.cnblogs.com/onemorepoint/p/8310996.html

Titanic幸存分类--决策树

# 需要在电脑中安装Graphviz,在下面的链接中下载适合自己电脑的版本
# https://graphviz.gitlab.io/download/
# 然后将解压文件中的bin设置到环境变量中
# 导入第三方模块
from sklearn.tree import export_graphviz
from IPython.display import Image
import pydotplus
from io import StringIO
# 绘制决策树
dot_data = StringIO()
export_graphviz(
    decision_tree,
    out_file=dot_data,  
    feature_names=predictors,
    class_names=['Unsurvived','Survived'],  
    # filled=True,
    rounded=True,  
    special_characters=True
)
# 决策树展现
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png()) 
image.png
# 导入第三方包
from sklearn import ensemble
# 构建随机森林
RF_class = ensemble.RandomForestClassifier(n_estimators=200, random_state=1234)
# 随机森林的拟合
RF_class.fit(X_train, y_train)
# 模型在测试集上的预测
RFclass_pred = RF_class.predict(X_test)
# 模型的准确率
print('模型在测试集的预测准确率:\n',metrics.accuracy_score(y_test, RFclass_pred))


# 计算绘图数据
y_score = RF_class.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
roc_auc = metrics.auc(fpr,tpr)
# 绘图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1)
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()
Figure_1.png

构建随机森林

# 变量的重要性程度值
importance = RF_class.feature_importances_
# 构建含序列用于绘图
Impt_Series = pd.Series(importance, index = X_train.columns)
# 对序列排序绘图
Impt_Series.sort_values(ascending = True).plot(kind='barh')
plt.show()
image.png
# 读入数据
NHANES = pd.read_excel('./NHANES.xlsx')
NHANES.head()
print(NHANES.shape)

# 取出自变量名称
predictors = NHANES.columns[:-1]
# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = model_selection.train_test_split(NHANES[predictors], NHANES.CKD_epi_eGFR, 
                                                                    test_size = 0.25, random_state = 1234)
                                                                    
# 预设各参数的不同选项值
max_depth = [18,19,20,21,22]
min_samples_split = [2,4,6,8]
min_samples_leaf = [2,4,8]
parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split, 'min_samples_leaf':min_samples_leaf}
# 网格搜索法,测试不同的参数值
grid_dtreg = GridSearchCV(estimator = tree.DecisionTreeRegressor(), param_grid = parameters, cv=10)
# 模型拟合
grid_dtreg.fit(X_train, y_train)
# 返回最佳组合的参数值
grid_dtreg.best_params_


# 构建用于回归的决策树
CART_Reg = tree.DecisionTreeRegressor(max_depth = 20, min_samples_leaf = 2, min_samples_split = 4)
# 回归树拟合
CART_Reg.fit(X_train, y_train)
# 模型在测试集上的预测
pred = CART_Reg.predict(X_test)
# 计算衡量模型好坏的MSE值
metrics.mean_squared_error(y_test, pred)


# 构建用于回归的随机森林
RF = ensemble.RandomForestRegressor(n_estimators=200, random_state=1234)
# 随机森林拟合
RF.fit(X_train, y_train)
# 模型在测试集上的预测
RF_pred = RF.predict(X_test)
# 计算模型的MSE值
metrics.mean_squared_error(y_test, RF_pred)

# 构建变量重要性的序列
importance = pd.Series(RF.feature_importances_, index = X_train.columns)
# 排序并绘图
importance.sort_values().plot(kind='barh')
plt.show()
image.png

你可能感兴趣的:(2020-05-19 第十章 决策树与随机森林(python))