【实践篇】决策树参数选择和 GridSearchCV
注:本节,小鱼将继续使用连载上一篇文章 【实践篇】决策树的可视化展示 使用的加利福尼亚房屋价值预测的数据集,关于数据集的介绍这里不再赘述。
Sklearn 为我们提供了 DecisionTreeRegressor 来构建决策树回归模型:
from sklearn.model_selection import train_test_split
data_train, data_test, target_train, target_test = train_test_split(
housing.data,
housing.target,
test_size=0.2,
random_state=0
)
dtr = DecisionTreeRegressor(random_state=0)
dtr.fit(data_train,target_train)
dtr.score(data_test,target_test)
使用决策树默认的参数,在测试集得到评分为:
0.5924304824636766
模型的评分还是很低的,不足 0.6 。接下来,我们使用 Sklearn 提供的随机森林回归模型 RandomForestRegressor ,同样使用默认的参数训练和评估模型:
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor(random_state=0)
rfr.fit(data_train,target_train)
rfr.score(data_test,target_test)
RandomForestRegressor:我们可以暂时理解为很多棵决策树,一棵决策树不行,那我多一些树,结果就会越可靠。
随机森林在测试集得到的评分:
0.7979950876327253
这就是随机森林的威力,在没进行任何调参的情况下,评分就提高了 20 个百分点。RandomForestRegressor 默认为我们训练了 100 棵决策树。
接下来,小鱼将使用 RandomForestRegressor 模型介绍决策树回归模型的参数以及如何调参的问题。
决策树参数
-
criterion: 衡量标准,也就是我们前面介绍的衡量切分质量的标准,如熵、gini系数;对于回归任务,默认为方差
squared_error。
-
max_features: 在寻找最佳切分特征时,考虑的特征数量,默认考虑全部特征。当特征小于 50 的时候一般使用所有的特征。
-
max_depth: 预剪枝策略的一种,限制树的深度,如果不加以限制,将节点将不断展开,直到所有叶子节点都是纯页,或者叶子节点样本数少于 min_samples_split 停止分裂。在数据少或者特征少的时候可以不管这个值,如果模型样本量多,特征也多的情况下,可以限制一下。
-
min_samples_split : 预剪枝策略的一种,限制叶子节点的样本个数。如果某节点的样本数少于 min_samples_split 则不会继续再尝试选择最优特征来进行划分;如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
-
min_samples_leaf : 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝,如果样本量不大,不需要管这个值,大些如10W可是尝试下5
-
min_weight_fraction_leaf: 这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。默认是 0,不考虑权重问题。一般来说,如果较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
-
max_leaf_nodes: 通过限制最大叶子节点数,可以防止过拟合,默认是
None,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制。具体的值可以通过交叉验证得到。 -
n_estimators:要建立树的个数。
现在,决策树有哪些参数,我们已经清楚了,那这么多参数,如何选出最优的参数值组合呢?
小鱼在介绍逻辑回归模型的时候,为了找到最优的正则化惩罚力度参数,使用了 model_selection 模块中的 KFold 进行了 5 折的交叉验证,将交叉验证的结果作为当前正则化惩罚力度的模型评估结果。
那现在,我们有这么多特征,将各个特征的候选参数值进行组合,将会组合出非常多的参数~不过,这些过程并不需要我们手动完成,GridSearchCV 帮我们轻松搞定~
GridSearchCV
时间关系,小鱼这里只选择了 min_samples_split 和 n_estimators 两个参数,来展示 GridSearchCV 的用法:
from sklearn.model_selection import GridSearchCV
tree_param_grid = {
"min_samples_split": [3,6,9],
"n_estimators": [10,50,100]
}
grid = GridSearchCV(
RandomForestRegressor(),
param_grid=tree_param_grid,
cv=5
)
grid.fit(data_train, target_train)
GridSearchCV 的参数非常简单,传入构建的模型;param_grid 为模型的参数和参数取值组成的字典;cv=5 表示做 5 折的交叉验证。
训练结果:
GridSearchCV(cv=5, estimator=RandomForestRegressor(),
param_grid={'min_samples_split': [3, 6, 9],
'n_estimators': [10, 50, 100]})
由于 min_samples_split 和 n_estimators 都有 3 个待选值,因此组合之后共有 9 组值,这 9 组值构建的随机森林模型,将分别进行 5 折的交叉验证。
获取结果最好的一组值:
>> grid.best_params_
{'min_samples_split': 6, 'n_estimators': 100}
最好的这组值,验证集得分是多少呢?
>> grid.best_score_
0.8004570387240992
使用最佳参数建模,并以测试集进行模型评估:
>> rfr = RandomForestRegressor(min_samples_split=6, n_estimators=100, random_state=0)
>> rfr.fit(data_train, target_train)
>> rfr.score(data_test, target_test)
0.7977553401920536
还可以打印决策树构造时,评估出的特征重要性(重要的特征,切分能力越强):
>> pd.Series(rfr.feature_importances_, index=housing.feature_names).sort_values(ascending=False)
MedInc 0.539850
AveOccup 0.135402
Latitude 0.083998
Longitude 0.082741
HouseAge 0.054384
AveRooms 0.045247
Population 0.030297
AveBedrms 0.028082
dtype: float64