赞
踩
决策树算法实现分类问题可以被理解为不断地进行条件语句判断,最终实现分类,如下图:
进行判断的分支很像树的枝干,被分出来的类别像是枝干上的叶子,所以将这个图称为决策树。所以,用决策树算法解决问题的第一步就是画出决策树。
在画决策树之前,要先了解决策树的结构是怎样的。
在分类阶段时,从根开始,按照决策树的分类属性逐层往下划分,直到叶节点,获得分类结果。
画出决策树的第一步即决定哪一个特征适合当作根节点。在这里,我们引入一些概念。
在化学中,熵用来衡量一种物质内部的混乱程度,即这种物质的纯度。
在概率论中,设有一事件
X
X
X,则它的熵
H
(
X
)
H(X)
H(X)可以衡量事件
X
X
X发生的不确定性。
熵的公式为:
H
(
X
)
=
−
∑
i
=
1
n
P
(
X
)
l
o
g
2
(
P
(
X
)
)
H(X)=-\sum_{i=1}^{n}P(X)log_{2}(P(X))
H(X)=−i=1∑nP(X)log2(P(X))
举例来说,假设这里有两组数据,A组数据为:1,2,3,4,5,4,6,1,7,8;B组数据为:1,2,1,1,1,1,1,1,1,1。那么我们可以很清楚地判断出A组数据的不纯度比较高,也就是熵值比较高。
那么,怎么用熵的公式来证明的确是A组数据的熵值较高呢?
首先,我们可以求出在A中随机挑出各个数字的概率,那么在A组数据中,挑出各个数据的概率不是0.1就是0.2,而在B组数据中,选到1的概率达到了0.9。将这些概率代到熵的公式中去以后,由于对数函数的性质,概率越小,得到的对数值的绝对值越大,所以A组数据中得到的对数值都比较大,而B组数据中由于有0.9的存在,使得熵远远小于A组的熵。
总而言之,当一组数据中的纯度越高,熵值就越小。
G
i
n
i
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
1
−
∑
k
=
1
K
p
k
2
Gini(p)=\sum_{k=1}^{K}p_{k}(1-p_{k})=1-\sum_{k=1}^{K}p_{k}^2
Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2
从式子可以看出,当概率越小时,得到的Gini系数越大,这和熵值的定义是一样的。
构造数的基本想法是随着树深度的增加,节点的熵迅速地降低。熵降低的速度越快越好,这样我们有望得到一颗高度最矮的决策树。
下图为14组历史数据,记录了14天中小明是否出去打球的情况,以及当天的天气(outlook),温度(temperature),湿度(humidity)和是否刮风(windy)。
首先,在没有给定任何天气信息时,根据历史数据,我们只知道新的一天打球的概率是9/14,不打球的概率是5/14。那么,此时的熵为:
接着,我们可以计算出分别以以上四个特征(天气,温度,湿度和是否刮风)为根节点时的最初的熵与经过分支之后的熵的变化值:
对于基于天气的划分,
在上面的例子中,我们用信息增益gain来确定下一个节点是什么特征,我们一般称这种方法为ID3。
但是这种方法有个缺点,就是当历史数据中有一些特征中存在的属性较多,但每个属性对应的样本个数很少时,ID3很难画出真正的决策树。
比如在历史数据中增加一列特征ID,表示第几天,那么ID这个特征中包含的属性有1,2,……,14,每个属性都只包含一个样本,那么如果要将ID作为根节点来划分的话,根据上例的分析可以得出信息熵已经归零,即它的信息增益一定是最大的。
所以,我们可以使用C4.5方法,用信息增益率为标准划分节点:
信
息
增
益
率
=
g
a
i
n
H
信息增益率=\frac{gain}{H}
信息增益率=Hgain
因为属性很多,所以熵值一定很大,那么其信息增益率就会减小,就不会被选作根节点了。
除了用ID3和C4.5之外,CART方法用Gini系数作为标准也很常用。
CART是英文Classification And Regression Tree的简写,又称为分类回归树。从它的名字我们就可以看出,它是一个很强大的算法,既可以用于分类还可以用于回归。
CART算法使用二元切分法来处理连续型变量。而使用二元切分法则易于对树构建过程进行调整以处理连续型特征。具体的处理方法是:如果特征值大于给定值就走左子树,否则就走右子树。
CART算法有两步:
总结来说:
评价函数:
C
(
T
)
=
∑
t
∈
l
e
a
f
N
t
×
H
(
t
)
C(T)=\sum_{t\in leaf}N_t\times H(t)
C(T)=t∈leaf∑Nt×H(t)
其中,
N
t
N_t
Nt是指第
t
t
t个叶节点上的样本个数,
H
(
t
)
H(t)
H(t)是指第
t
t
t个叶节点的熵(或Gini系数)。评价函数越小,说明得到的决策树越好。
如果不剪枝,最后形成的决策树很有可能一个叶节点对应一个样本,这对训练集来说准确率达到了百分之百,但在测试集中效果很差,即过拟合现象。
预剪枝和后剪枝都可以防止过拟合现象。
在预剪枝中,可以规定一个深度限制为3,则决策树中划分出三层节点后就会停止;或者规定一个节点中的样本数少于50个时停止。
在后剪枝中,评价函数被改变为如上图所示,
α
\alpha
α越大,对叶节点数的要求越严格。
我们使用决策树来对wine dataset中的酒进行分类。
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import graphviz
import matplotlib.pyplot as plt
# 读取数据
wine = load_wine()
print(wine.data.shape)
print(wine.target)
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
print(Xtrain.shape)
print(Xtest.shape)
print(Ytrain.shape)
print(Ytest.shape)
# 建立模型
clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=30, splitter="random",
max_depth=3, min_samples_leaf=10, min_samples_split=10 )
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度
print(score)
函数介绍之tree.DecisionTreeClassifier:
输入:
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
dot_data = tree.export_graphviz(clf,
feature_names= feature_name,
class_names=["琴酒","雪莉","贝尔摩德"],
filled=True,
rounded=True)
graph = graphviz.Source(dot_data)
graph
[*zip(feature_name,clf.feature_importances_)]
score_train = clf.score(Xtrain,Ytrain)
score_test = clf.score(Xtest,Ytest)
print(score_train)
print(score_test)
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i+1, criterion="entropy", random_state=30,splitter="random")
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()
from sklearn.tree import DecisionTreeRegressor from sklearn import linear_model # 用线性回归做对比 ex0 = pd.read_table('ex0.txt',header=None) ex0.describe() plt.scatter(ex0.iloc[:,1].values,ex0.iloc[:,-1].values) #用来训练的数据 x = (ex0.iloc[:, 1].values).reshape(-1,1) # 将行数组转换为列数组 y = (ex0.iloc[:,-1].values).reshape(-1,1) # 预测 X_test = np.arange(0, 1, 0.01)[:, np.newaxis] # 另一种方法将行数组转换为列数组 print(X_test.shape) y_1 = model1.predict(X_test) y_2 = model2.predict(X_test) y_3 = model3.predict(X_test) # 可视化结果 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=1", linewidth=2) plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=3", linewidth=2) plt.plot(X_test, y_3, color='red', label='liner regression', linewidth=2) plt.xlabel("data") plt.ylabel("target") plt.title("Decision Tree Regression") plt.legend() plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。