决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规 则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。
重要属性与接口:
一个属性:feature_importances_ 四个接口:fit,score,apply,predict (由模型得到x或y,在fit形成模型后使用)
tree.DecisionTreeClassifier 分类树 tree.DecisionTreeRegressor 回归树 tree.export_graphviz 将生成的决策树导出为DOT格式,画图专用
三种方法使用代码基本一致。

分类树
from sklearn import tree #导入需要的模块
clf = tree.DecisionTreeClassifier() #实例化
clf = clf.fit(X_train,y_train) #用训练集数据训练模型
result = clf.score(X_test,y_test) #导入测试集,从接口中调用需要的信息
重要参数
criteri不填默认基尼系数,填写gini使用基尼系数,填写entropy使用信息增益。
from sklearn import tree
from sklearn.datasets import load_wine # 获得红酒数据
from sklearn.model_selection import train_test_split # 将数据打乱,并分割出来,分为测试机和训练集
import graphviz
wine = load_wine()
# wine.data.shape # 数据行列数
# wine.target # 标签
# --分割训练集和数据集
Xtrain, Xtext, Ytrain, Ytext = train_test_split(wine.data,wine.target,test_size=0.3)
# --建立决策树模型 (标准建立模型)
jcs = tree.DecisionTreeClassifier(criterion='gini')
jcs = jcs.fit(Xtrain,Ytrain)
score = jcs.score(Xtext,Ytext)
# print(score)
# --画出特征树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
dot_data = tree.export_graphviz(jcs
,out_file = None
,feature_names= feature_name # 添加特征名
,class_names=["琴酒","雪莉","贝尔摩德"] # 设置决策名
,filled=True # 是否加颜色
,rounded=True # 边框是否为原型
,fontname="Microsoft YaHei" # 修复中文乱码
)
graphviz.Source(dot_data).view() # 用pycharm显示
jcs.feature_importances_ # 显示特征重要性 可以搭配[*zip(feature_name,jcs.feature_importances_)]使用
# 在模型中可以添加两个参数,使得模型准确度提升上来,即利用集成的方法,也就是多个模型实验,防止过拟合。
# random_state=30,splitter="random";30可修改,找到最合适的值,参数可要可不要,哪个score高就要哪个。
jcs = tree.DecisionTreeClassifier(criterion='entropy',random_state=30, splitter="random")
jcs = jcs.fit(Xtrain,Ytrain)
score = jcs.score(Xtext,Ytext)
剪枝精修,当数据集有多个特征时,能提前预测到,一定要对特征进行一个精修,就需要提前设置参数,以达到释放内存,提高训练分数的效果。
当出现过拟合时,出现训练集分数很高,但是测试集却不好时,可以考虑限制节点。
max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉这是用得最广泛的剪枝参数,在高维度低样本量时非常有效。决策树多生长一层,对样本量的需求会增加一倍,所以限制树深度能够有效地限制过拟合。在集成算法中也非常实用。实际使用时,建议从=3开始尝试,看看拟合的效果再决定是否增加设定深度。
min_samples_leaf & min_samples_split
min_samples_leaf限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生。(针对叶子节点不能超过多少)
一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择。
min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。(针对根节点不能超过多少)
max_features & min_impurity_decrease 一般max_depth使用,用作树的”精修“ max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。和max_depth异曲同工, max_features是用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量 而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型 学习不足。如果希望通过降维的方式防止过拟合,建议使用PCA,ICA或者特征选择模块中的降维算法。 (限制特征选取的个数,可以利用多个特征,通过图表展示的形式来看合适的取特征值数) min_impurity_decrease限制信息增益的大小,信息增益小于设定数值的分枝不会发生。(根减去叶子)
import matplotlib.pyplot as plt
test = []
for i in range(10):
jcs = tree.DecisionTreeClassifier(max_depth=i+1
,criterion="entropy"
,random_state=30
,splitter="random"
)
clf = jcs.fit(Xtrain, Ytrain)
score = jcs.score(Xtest, Ytest)
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
回归树:使用方法差不多。
案例学习:泰坦尼克号
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
# 导入数据
data = pd.read_csv(r'D:\Users\14011\Downloads\SKlearn全部章节数据及代码 (1)\01 决策树数据及代码\Taitanic data\data.csv')
# 删除不用的列
data = data.drop(['Name','Cabin','Ticket'],axis=1)
# 利于均值填充空值
data['Age'] = data['Age'].fillna(data['Age'].mean())
# 删除空值行
data = data.dropna()
# 换数字数据
l = data['Embarked'].unique().tolist()
data['Embarked'] = data['Embarked'].apply(lambda x: l.index(x))
data['Sex'] = (data['Sex'] == 'male').astype('int')
# 提出数据和标签,在进行分组
x = data.loc[:,data.columns != 'Survived']
y = data['Survived']
xtrain,xtest,ytrain,ytest = train_test_split(x,y,test_size=0.3)
# 下标修正
for i in [xtrain,xtest,ytrain,ytest]:
i.index = range(i.shape[0])
# 建立模型
jcs = DecisionTreeClassifier()
jcs = jcs.fit(xtrain,ytrain)
score = jcs.score(xtest,ytest)
# 交叉验证
from sklearn.model_selection import cross_val_score
score = cross_val_score(jcs,x,y,cv=10).mean()
tr = []
te = []
for i in range(10):
jcs = DecisionTreeClassifier(random_state=30
,max_depth=i+1
,criterion='entropy'
)
jcs =jcs.fit(xtrain,ytrain)
score_tr = jcs.score(xtrain,ytrain)
score_te = cross_val_score(jcs,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,label='test')
plt.xticks(range(1,11))
plt.legend()
plt.show()
import numpy as np
# 网格搜索:能够帮助我们同时调整多个参数的技术,枚举技术。
gini_thresholds = np.linspace(0,0.5,20)
# 一串参数和这些参数对应的,我们希望网格搜索来搜索的参数的取值范围。
parameters = {'splitter':('best','random')
,'criterion':("gini","entropy")
,"max_depth":[*range(1,10)]
,'min_samples_leaf':[*range(1,50,5)]
,'min_impurity_decrease':[*np.linspace(0,0.5,20)]
}
jcs = DecisionTreeClassifier(random_state=30)
GS = GridSearchCV(jcs,parameters,cv=10)
GS.fit(xtrain,ytrain)