python机器学习——决策树算法

背景与原理:

决策树算法是在各种已知情况发生概率的基础上通过构成决策树来求某一事件发生概率的算法,由于这个过程画成图解之后很像一棵树形结构,因此我们把这个算法称为决策树。

而在机器学习中,决策树是一种预测模型,代表对象属性和对象值之间的一种映射,一棵决策树的每个内部节点会处理数据的某个维度对应的变量,根据这个变量的取值向下进行分支,直到走到叶节点,每个叶节点代表输入对应的一个最终输出。

决策树生成算法有很多种,比如ID3,C4.5和C5.0等,这里使用ID3实现方法。

决策树直观上很好理解,比如已知小明在晴天有空的时候去跑步的概率是90%,那么现在如果想预测小明是否会去跑步,那么我们首先观察是否是晴天,这就产生了“是晴天”和“不是晴天”两个分支,而对于“是晴天”的分支我们再观察小明是否有空,这就产生了“有空”和“没空”两个分支,最后在“有空”这个分支我们已经找到了叶节点,发现小明去跑步的概率为90%,那我们就作出预测小明会去跑步。而对于其余的分支我们需要更多信息才能做出预测。

而对于决策树而言,最重要的是要选择每个节点处理哪个属性。在上述例子中可能没有体现,我们先观察是否是晴天和先观察是否有空对整个决策过程没有影响,但是如果我们再加入一个条件“小明在没空的时候一定不会去跑步(都没空了跑什么步)”,那此时如果我们先观察是否是晴天,我们仍然需要在每个分支里都观察小明是否有空,而如果我们先观察小明是否有空,那么在小明没空的时候,我们不需要观察是否是晴天就可以作出预测:小明不会去跑步!也就是说对于“有空”这个分支,我们才需要继续向下分支,而对于“没空”这个分支,我们直接到达了叶节点——“不去跑步”!

上述分析实际上体现了“熵”的思想:严格地:对于一个有$n$个取值$x_{1},...,x_{n}$的随机变量$X$,那么定义其熵值为$H(X)=-\sum_{i=1}^{n}P(X=x_{i})\log_{b}P(X=x_{i})$,这里的$b$通常取$2,e,10$

我们说“信息”是用来消除“不确定性”的东西,而熵则是用来度量不确定性的量(比如如果一个随机变量只有一个取值,那么这个随机变量也就不再随机了,不确定性为0,其熵值也是0)。因此我们可以认为一个信息的出现如果造成的熵减越大,那么这个信息的信息量越大。

所以对一个样本集$T$,其原始的熵为$H(T)$,而当我们已知一个特征$X$的信息时,假设$X$有$n$个取值$x_{1},...,x_{n}$,我们定义条件熵$H(T|X)=\sum_{i=1}^{n}P(X=x_{i})H(T|X=x_{i})$,其中$H(T|X=x_{i})$是计算$T$在$X=x_{i}$下概率分布的熵,比如虽然原始的$T$可能有100种取值,但是当我们已知$X=x_{i}$时,$T$只会有一种取值,这样的话$H(T|X=x_{i})=0$

这样我们就可以非常自然地定义信息增益$IG(T,X)=H(T)-H(T|X)$,表示当我们引入条件$X$后消除了多少不确定性,而我们在每个节点上要选取的特征就是在当前能选取的特征中消除的不确定性最多的特征,即使$IG(T,X)$最大的$X$

代码实现:

 

import numpy as np
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
import graphviz

data=load_iris()
X=data.data
Y=data.target

X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=0.25)

clf=DecisionTreeClassifier(criterion="entropy")
clf=clf.fit(X_train,Y_train)

dot_data = tree.export_graphviz(clf,feature_names= ['f1','f2','f3','f4'],class_names=["class1","class2","class2"],filled=True,rounded=True,out_file=None)
graph = graphviz.Source(dot_data)
score_=clf.score(X_test, Y_test)
print(score_)
graph

这是对于鸢尾花数据集用决策树分类的效果,这里的决策树直接调了sklearn里的包,同时引用了graphviz包来做可视化(这个包的使用很复杂,建议在jupyter里运行上述代码,不然可视化不太容易),而score是用来衡量分类效果的,这里的score得分还不错。

小结与优化:

决策树算法的一个问题在于可能出现过拟合——如果有一个特征的取值多到了可以直接根据这个特征分支出所有的类,那么上面的算法会很高兴地建立这样的决策树,但是这样的决策树的泛化效果就会变得很差,因此在上述训练过程中,可以加入参数random_state和splitter来控制决策树的随机模式,通过合理选择模式降低对训练集的拟合,从而一定程度上提高模型的泛化性能,同样在原理层面可以把特征选取原则由信息增益变为信息增益率,通过增加一定的惩罚项减轻过拟合的问题等。

另一个问题是对于特征维度多、数据数量大的数据集决策树训练的效率不高,可以通过迭代增益、探索确定的分裂原则等手段进行优化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章