一、决策树原理
1.熵的概念
化学中可定义为分子的混乱程度,这里可以理解为系统的不确定程度
例如:A{1,2,3,4,5},B{1,1,1,1,1}
对于A集合,每个数字发生的概率均为1/6,Pi较小,-Pi*lnPi较大,熵值较大。
对于B集合,1发生的概率为1,熵值较小。
(x为Pi,y为lnPi)
2.如何构造决策树(例子)
构造树的基本想法是随着树的深度的增加,节点的熵迅速降低。降低的越快越好,这样我们可以得到一颗最矮的决策树。
(若决策树高度过高,意味着有大量分支,每一个叶子节点纯度都很高,对于一个新的数据集上,分类达到百分百的效果,会出现过拟合的问题)
例子:一共有14组和数据,每行数据有4个特征,来决定当天是否去打球。
步骤:
1.决定哪个属性作为根节点,天气,温度,湿度,有风均可作为根节点。首先计算原始数据熵值,然后分别计算4个属性的熵值,分别计算出信息增溢,选择信息增溢最大的属性作为根节点。(划分后的族群内部混乱程度会最小)
熵值的计算过程如下:
2.迭代
预剪枝:在构建决策树的过程中,提前停止
后剪枝:在决策树构建好后,才开始剪枝
3.决策树的构造:
优点:计算复杂程度不高,对中间的缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过拟合问题。(例如:人类可以按照性别分类,你却按照姓名分类)
使用数据类型:数值型和离散型。
二、sklearn库实现
from sklearn import tree
form sklearn.metric import precision_recall_curve
form sklearn.metric import classification_report
form sklearn.cross_valication import train_test_split
#拆分训练数据与测试数据,80%做训练,20%做测试
train_test_split(x,y,test_size=0.2)
#信息熵作
tree.Decision TreeClassifier(criterion='entropy')
#训练结果
clf.fit(x_train,y_train)
#预测结果
clf.predict(x_train)
#计算准确率和召回率
precision_recall_curve(y_train,y_pre)
#计算全量的预测结果
clf.predict_proba(x)[:,1]
#打印每个分类的准召率
classification_report(y,answer,target_names=target_names)
红酒分类案例(建模预测+精准度+画树):
#导入库
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
wine=load_wine()
wine.data
#结果
array([[1.423e+01, 1.710e+00, 2.430e+00, ..., 1.040e+00, 3.920e+00,
1.065e+03],
[1.320e+01, 1.780e+00, 2.140e+00, ..., 1.050e+00, 3.400e+00,
1.050e+03],
[1.316e+01, 2.360e+00, 2.670e+00, ..., 1.030e+00, 3.170e+00,
1.185e+03],
...,
[1.327e+01, 4.280e+00, 2.260e+00, ..., 5.900e-01, 1.560e+00,
8.350e+02],
[1.317e+01, 2.590e+00, 2.370e+00, ..., 6.000e-01, 1.620e+00,
8.400e+02],
[1.413e+01, 4.100e+00, 2.740e+00, ..., 6.100e-01, 1.600e+00,
5.600e+02]])
wine.target
#结果
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2])
#表格显示
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
wine.feature_names
#结果
['alcohol',
'malic_acid',
'ash',
'alcalinity_of_ash',
'magnesium',
'total_phenols',
'flavanoids',
'nonflavanoid_phenols',
'proanthocyanins',
'color_intensity',
'hue',
'od280/od315_of_diluted_wines',
'proline']
wine.target_names
#结果
array(['class_0', 'class_1', 'class_2'], dtype='<U7')
#30%作为训练样本
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)
#实例化+建模+预测结果+精准度
clf=tree.DecisionTreeClassifier(criterion="entropy")
clf=clf.fit(Xtrain,Ytrain)
score=clf.score(Xtest,Ytest)
clf.predict(Xtest)
score
#结果
array([0, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 1, 1, 0, 2, 1,
1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 2, 2, 0, 1,
2, 2, 1, 2, 0, 0, 1, 1, 0, 2])
0.9259259259259259
#画出一棵树
feature_name=['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
import graphviz #需要安装graphviz
dot_data=tree.export_graphviz(clf
,feature_names=featrure_name
,class_names=['琴酒','雪梨','贝尔摩德']
,filled=True
,rounded=True
)
graph=graphviz.Source(dot_data)
graph
#显示特征重要程度
clf.feature_importance_
[*zip(feature_name,clf.feature_importance)]
调参优化
1.random_state & splitter
random_state用来设置分枝中的随机模式的参数,高维度特征中随机性会更加明显。输入任意整数,会长出同一棵树,让模型稳定
splitter也用来控制数中的随即选项,有两种输入值,输入”best",决策树在分枝时虽然随机,但是还会优先选择更重要的特征进行分枝。输入“random”,决策树分枝时会更加随机,树会更深,对训练集的拟合将会降低。
调整这两个参数可以降低过拟合的可能性。
clf=tree.DecisionTreeClassifier(criterion="entropy")改为
clf=tree.DecisionTreeClassifier(criterion="entropy"
, random_state=30
, splitter="random")
2.剪枝参数
为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。
- max_depth
限制树的最大深度,超过设定深度的树枝都会被剪掉。
在高维度低样本量时非常有效。决策树多生长一层,对样本量的需求就会增加一倍,否则分枝就不会发生,所以可以限制树深来限制过拟合。建议从=3开始。 - min_sample_leaf & min_samples_split
min_sample_leaf规定分枝后的子节点必须至少包括min_sample_leaf个训练样本,否则分枝不会发生。设置过小会引起过拟合,设置太大会组织模型学习数据。建议从=5开始。
min_sample_split规定,一个节点必须要包含min_sample_split个训练样本,才会分枝,否则不分枝。
clf=tree.DecisionTreeClassifier(criterion="entropy"
, random_state=30
, splitter="random"
, max_depth=3
, min_sample_leaf=10
, min_sample_split=10
)
- max_feature & min_impurity_decrease
max_feature限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。可用来限制高维度数据的过拟合。但降维方式防止过拟合更建议使用PCA,ICA或者特征选择模块中的降维算法。
min_impurity_decrease限制信息增益的大小,信息增益小于设定数值分支不会发生。
如何确认参数
使用超参数的学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,它用来度量不同参数取值下模型表现的线。
#学习曲线求参数
import matplotlib.pyplot as plt
test = [ ]
for i in range (10):
clf = tree.DecisionTreeClassifier(max_depth=i+1
, criterion="entropy"
, random_state=30
)
clf = clf.fit(Xtrain,Ytrain)
score = clf.score(Xtest,Ytest)
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
结果:
当man_depth=3时,模型达到最优。