目录
1、决策树是什么
决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。
决策树算法的本质是一种图结构,我们只需要问一系列问题就可以对数据进行分类了。
2.决策树有什么优点
1.是一个白盒模型,结果很容易能够被解释。如果在模型中可以观察到给定的情况,则可以通过布尔逻辑轻松解释条件。相反,在黑盒模型中(例如,在人工神经网络中),结果可能更难以解释。
2.能够同时处理数字和分类数据,既可以做回归又可以做分类。其他技术通常专门用于分析仅具有一种变量类型的数据集。
3.使用树的成本(比如说,在预测数据的时候)是用于训练树的数据点的数量的对数,相比于其他算法,这是一个很低的成本。
3.决策树的缺点
1. 决策树学习者可能创建过于复杂的树,这些树不能很好地推广数据。这称为过度拟合。修剪,设置叶节点所需的最小样本数或设置树的最大深度等机制是避免此问题所必需的,而这些参数的整合和调整对初学者来说会比较晦涩
2.决策树的学习是基于贪婪算法,它靠优化局部最优(每个节点的最优)来试图达到整体的最优,但这种做法不能保证返回全局最优决策树。这个问题也可以由集成算法来解决,在随机森林中,特征和样本会在分枝过程中被随机采样。
3. 如果标签中的某些类占主导地位,决策树学习者会创建偏向主导类的树。因此,建议在拟合决策树之前平衡数据集。
4.决策树使用的训练集的数值,不能存在空值,如果存在空值,需要补全;此外,决策树不能处理文字信息,需要将文字信息全部转化为数字类型。
3.1决策树常用的预处理数据的方法
例如我们这次选取的是泰坦尼克号数据集作为训练样本
如上可知,总共存在五类数据
1.Embarked列,存在S,C,Q三类数据,利用各自的下标【0,1,2】分别表示s,c,q
#将三分类变量转换为数值型变量
labels = data["Embarked"].unique().tolist()
data["Embarked"] = data["Embarked"].apply(lambda x: labels.index(x))
2.删除缺失值过多的列,和观察判断来说和预测的y没有关系的列
#删除缺失值过多的列,和观察判断来说和预测的y没有关系的列
data.drop(["Cabin","Name","Ticket"],inplace=True,axis=1)
3.填补相关缺失列
#处理缺失值,对缺失值较多的列进行填补,例如年龄列,可使用年龄的平均值进行填补
data["Age"] = data["Age"].fillna(data["Age"].mean())
4.有一些特征只确实一两个值,可以采取直接删除记录的方法
data = data.dropna()
5.将二分类变量转换为数值型变量,例如性别列
#astype能够将一个pandas对象转换为某种类型,和apply(int(x))不同,astype可以将文本类转换为数字,用这个方式可以很便捷地将二分类特征转换为0~1
data["Sex"] = (data["Sex"]== "male").astype("int")
#查看处理后的数据集
data.head()
4.决策树重要参数
4.1criterion
为了要将表格转化为一棵树,决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。
Criterion这个参数正是用来决定不纯度的计算方法的。
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)
4.2 random_state & splitter
若不给定random_state的值,则会
4.3剪枝参数
在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。这样的决策树往往会过拟合,这就是说,它会在训练集上表现很好,在测试集上却表现糟糕。我们收集的样本数据不可能和整体的状况完全一致,因此当一棵决策树对训练数据有了过于优秀的解释性,它找出的规则必然包含了训练样本中的噪声,并使它对未知数据的拟合程度不足。
为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。sklearn为我们提供了不同的剪枝策略:
max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉这是用得最广泛的剪枝参数,在高维度低样本量时非常有效。决策树多生长一层,对样本量的需求会增加一倍,所以限制树深度能够有效地限制过拟合。在集成算法中也非常实用。实际使用时,建议从=3开始尝试,看看拟合的效果再决定是否增加设定深度。
min_samples_leaf & min_samples_splitmin_samples_leaf
限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择。min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。
5.决策树的使用
1.导库
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier #实例化样本时使用
from sklearn.model_selection import GridSearchCV #画树图用
from sklearn.model_selection import cross_val_score #计算测试样本的拟合状况
from sklearn.model_selection import train_test_split #导入训练集和测试集
2.导入样本库
data = pd.read_csv(r"C:\Users\jz\Desktop\sklearn学习_jb51\【机器学习】菜菜的sklearn课堂(1-12全课)\01 决策树课件数据源码\data.csv",index_col = 0)
带着r,可以使用C:\xxx\xxx\这种格式,如果不加r,则需要使用C://xxx//xxx//这格式
3.使用上面提供的方法,进行数据集的预处理修正。
4.对数据集进行切片,分为x和y数据集
5.训练样本,并修正索引
Xtrain,Xtest,Ytrain,Ytest=train_test_split(x,y,test_size=0.3)
修正x轴索引坐标:
Xtrain.index=range(Xtrain.shape[0])
for i in [Xtrain,Xtest,Ytrain,Ytest]:
i.index=range(i.shape[0])
6.训练测试
clf = DecisionTreeClassifier(random_state=25) #实例化
clf = clf.fit(Xtrain, Ytrain) #用训练集数据训练模型
score_ = clf.score(Xtest, Ytest) #导入测试集,从接口中调用需要的信息
score_ #查看测试集拟合情况
7.如果测试情况不好,可以使用交叉验证来测试一下
#因为只有0.76,拟合效果并不好,因此使用交叉验证来试一下看是否有所改变
clf = DecisionTreeClassifier(random_state=25)
clf = clf.fit(Xtrain, Ytrain)
score = cross_val_score(clf,x,y,cv=5).mean() #使用交叉验证
score
#cv表示跑的次数,不写默认是5
画图进一步查看交叉验证的情况
tr=[]
te=[]
for i in range(10):
clf = DecisionTreeClassifier(random_state=25
,max_depth=i+1
)
clf = clf.fit(Xtrain, Ytrain)
score_tr=clf.score(Xtrain,Ytrain)
score_te=cross_val_score(clf,x,y,cv=10).mean()
tr.append(score_tr)
te.append(score_te)
print(max(te))
plt.plot(range(1,11),tr,color="red",label="train")
plt.plot(range(1,11),te,color="green",label="test")
plt.xticks(range(1,11))#生成x轴,范围1到11
plt.legend()#显示图例
plt.show()
8.使用网格搜索进一步探索最佳的参数,进行调参
#使用网格搜索同时调整多个参数,但也有缺点,一定会将所有参数都同时取一个最优值
gini_thresholds = np.linspace(0,0.5,20)
parameters = {'splitter':('best','random')
,'criterion':("gini","entropy")
,"max_depth":[*range(2,4)]
,'min_samples_leaf':[*range(1,50,5)]
,'min_impurity_decrease':[*np.linspace(0,0.5,20)]
}
clf = DecisionTreeClassifier(random_state=25)
GS = GridSearchCV(clf, parameters, cv=10)#网格搜索
GS.fit(Xtrain,Ytrain)
查看最佳组合
GS.best_params_
查看最好的结果
GS.best_score_
9.绘制树状图
feature_name=['Pclass','性别','Age','SibSp','Parch','Fare','Embarked']
import graphviz
from sklearn.model_selection import train_test_split
dot_data = tree.export_graphviz(clf
,out_file = None
,feature_names= feature_name
,class_names=["幸存者","死亡者"]
,filled=True
,rounded=True
)
graph = graphviz.Source(dot_data)
graph
查看每项class对结果的影响
[*zip(feature_name,clf.feature_importances_)]
完结,撒花!!!