本文用通俗易懂的方式来讲解分类树中的回归树,并以“一维回归的图像绘制”和“泰坦尼克号幸存者预测”两个例子来说明该算法原理。
以下是本文大纲:
1 DecisionTreeRegressor
1.1 重要参数,属性及接口 criterion
1.2 交叉验证
2 实例:一维回归的图像绘制
3 实例:泰坦尼克号幸存者的预测
4 决策树的优缺点
5 附录
5.1 分类树参数列表
5.2 分类树属性列表
5.3 分类树接口列表
1 DecisionTreeRegressor
首先,我们来看看在sklearn中,这个库长什么样子吧:
class sklearn.tree.DecisionTreeRegressor (criterion=’mse’, 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, presort=False)
如果你读过本博客的前两篇关于决策树的文章,你会发现
几乎所有参数,属性及接口都和分类树一模一样。需要注意的是,在回归树种,没有标签分布是否均衡的问题,因
此没有class_weight这样的参数。
下面我们介绍一下重要的参数和属性以及接口有哪些
1.1 重要参数,属性及接口 criterion
回归树衡量分枝质量的指标,支持的标准有三种:
1)输入"mse"使用均方误差mean squared error(MSE),父节点和叶子节点之间的均方误差的差额将被用来作为
特征选择的标准,这种方法通过使用叶子节点的均值来最小化L2损失。
2)输入“friedman_mse”使用费尔德曼均方误差,这种指标使用弗里德曼针对潜在分枝中的问题改进后的均方误差。
3)输入"mae"使用绝对平均误差MAE(mean absolute error),这种指标使用叶节点的中值来最小化L1损失
属性中最重要的依然是featureimportances,接口依然是apply, fifit, predict, score最核心。
其中我们要看一下MAE是什么:
解释一下:我们将一个数据集划分成n份,每次取其中一份为测试机,剩下的为训练集,这样每一次划分都计算出一个精确性Ei,最后我们取平均值为最后的模型度量结果。
如果我们自己用代码来实现这个过程可能会很麻烦,但是,sklearn早已为我们封装好了,我们直接用就可以。
下面我们来介绍一下如何来使用sklearn来进行交叉验证:
首先我们导入相关的模块:
from sklearn.datasets import load_boston #我们导入波士顿的放假数据from sklearn.model_selection import cross_val_score #导入交叉验证模块from sklearn.tree import DecisionTreeRegressor #导入回归树模块
然后我们进行交叉验证:
regressor = DecisionTreeRegressor(random_state=0)#实例化cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error") #交叉验证cross_val_score的用法,这里将数据集分为十个部分。
解释一下:我们可以得到每次交叉验证得到的分数。
第一个参数是实例化后的模型。第二个参数是完整的数据集。第三个参数是完整数据集的标签。第四个参数表示交叉验证的次数,一般是5.第五个参数是指明交叉验证的分数指标。
2 实例:一维回归的图像绘制
接下来我们到二维平面上来观察决策树是怎样拟合一条曲线的。
我们用回归树来拟合正弦曲线,并添加一些噪声来 观察回归树的表现。
首先导入使用的包:
import numpy as npfrom sklearn.tree import DecisionTreeRegressorimport matplotlib.pyplot as plt
然后我们开始造一个数据集:
rng = np.random.RandomState(1) #随机数种子X = np.sort(5 * rng.rand(80,1), axis=0) #生成0~5之间随机的x取值,数据为80行1列(二维的),因为训练时候不允许有一维特征。sort是排序。y = np.sin(X).ravel()#生成正弦曲线。ravel函数是将数据降成一维的。y[::5] += 3 * (0.5 - rng.rand(16))#在正弦曲线上加噪声,每5个步长取一个数 ,共16个数,结果噪声就在3*(-0.5,0.5)=(-1.5,1.5)之间。
这四行代码已经做了比较详细的注释,若不清楚,请百度一下每个函数的作用,做做实验就会懂的。
然后我们将造好的数据画出来看看:
plt.figure()plt.scatter(X,y,s=20,edgecolor="black",c="darkorange",label="data")
解释一下:这些噪音就相当于我们平常做实验的时候所遇到的一些不好的数据
这里我们建立两个模型,目的是为了看不同拟合效果(max_depth不一样)能得到什么结果。
regr_1 = DecisionTreeRegressor(max_depth=2)regr_2 = DecisionTreeRegressor(max_depth=5)regr_1.fit(X, y)regr_2.fit(X, y)
好了,现在模型已经训练好,现在我们得找一个数据来训练一下,看看模型的效果:
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]#这里是生成0~5,步长为0.01的数列,后面[]的功能是增维y_1 = regr_1.predict(X_test)#得到模型1的结果y_2 = regr_2.predict(X_test)#得到模型2的结果
我们将数据图、模型1的结果、模型2的结果画在一张图上:
plt.figure()plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")plt.plot(X_test, y_1, color="cornflowerblue",label="max_depth=2", linewidth=2)plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)plt.xlabel("data")plt.ylabel("target")plt.title("Decision Tree Regression")plt.legend()plt.show()
解释一下:我们可以很清晰的看到,当max_depth为2的时候,效果还算好,当max_depth为5的时候,模型会对数据有更强的拟合,但是结果却不如人意,结果画出来的图很夸张有没有。那就说明受噪声影响比较大。
3 实例:泰坦尼克号幸存者的预测
泰坦尼克号的沉没是世界上最严重的海难事故之一,今天我们通过分类树模型来预测一下哪些人可能成为幸存者。
数据集来着https://www.kaggle.com/c/titanic,数据集会随着代码一起提供给大家,大家可以在下载页面拿到。
首先我们导入所需要的库:
import pandas as pdfrom sklearn import treefrom sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.model_selection import GridSearchCVfrom sklearn.model_selection import cross_val_scoreimport matplotlib.pyplot as plt
然后我们导入数据集,并看看数据集长什么样吧:
data = pd.read_csv(r"D:\学习笔记\毛维杨\data.csv",index_col= 0)data
上面这个函数就能取出数据集中的前n行展示出来,默认为5.
拿到数据集了,首先当然是处理一下,取其精华去其糟粕!
regressor = DecisionTreeRegressor(random_state=0)#实例化cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error") #交叉验证cross_val_score的用法,这里将数据集分为十个部分。0
是不是更“漂亮”了!
下面开始建模:
regressor = DecisionTreeRegressor(random_state=0)#实例化cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error") #交叉验证cross_val_score的用法,这里将数据集分为十个部分。1
分完训练集和测试集后,我们的训练集和测试集的索引会变乱,所以我们要对其进行修正。
下面我们来进行建模:
regressor = DecisionTreeRegressor(random_state=0)#实例化cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error") #交叉验证cross_val_score的用法,这里将数据集分为十个部分。2
本文首先以max_depth为例来构建学习曲线,我们以max_depth取值为横轴,以得分score为纵轴画图,图中包含训练集和测试集两条曲线。
可以看到,当max_depth越来越大的时候,模型的过拟合程度越来约严重,其中最好的点是在3附近,通过实验可以知道,最大的得分是0.81778,这个分数依然不是那么理想。
那么我们要找出最合适的剪枝方案(也就是每个参数设置成什么最好),难道要我们像max_depth一样一个一个去画图观察?那样工作量巨大!
当然不是!
因为在剪纸这一步有很多可以调节的参数,如何寻找到一个最优的参数组合就成了一个问题,网格搜索方法(GridSearchCV)就解决了这个问题。
GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化的结果和参数。但是这个方法适合于小数据集,一旦数据的量级上去了,很难得出结果。
这个时候就是需要动脑筋了。数据量比较大的时候可以使用一个快速调优的方法——坐标下降。它其实是一种贪心算法:拿当前对模型影响最大的参数调优,直到最优化;
再拿下一个影响最大的参数调优,如此下去,直到所有的参数调整完毕。
这个方法的缺点就是可能会调到局部最优而不是全局最优,但是省时间省力,巨大的优势面前,还是试一试吧,后续可以再拿bagging再优化。
本文利用该方法对模型进行处理,其中cv值设为10,即做10次交叉验证:
regressor = DecisionTreeRegressor(random_state=0)#实例化cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error") #交叉验证cross_val_score的用法,这里将数据集分为十个部分。3
至此,关于决策树的全部内容整理完毕,接下来开始新的算法整理。
本文参考教程:菜菜的sk-learn课程
如有写的不合适,亦或是不精确的地方,望读者多包涵
如果大家对上述内容有任何不理解的地方,可以留言,和毛同学共同讨论,一起进步!