决策树是最简单的也是最具解释性和表达性的一种机器学习算法,既可以处理分类问题(ID3,C45,C50),也可以处理回归问题(CART)。
它是根据特征(feature)的值逐步把数据分类,直到所有的叶子节点属于同一个类型结束。注意决策树都是贪婪的。
1. 如何确定哪个特征被优先选择用来分类。
根据某一个特征划分数据集,其划分前后信息熵会有变化。优先选择的特征是让给让信息熵变化最大或者信息熵增益比最大的特征。
不过,从另外一方面来说,也要避免选择日期或者非常特殊的特征来做决策点,因为这些特征不具备任何的泛化能力。
2. 如何避免过拟合。
对于决策树来说,如果树的高度过高,或者某个叶子节点的数据特别少,或者叶子节点非常多(后两者有关联),就有可能是过拟合,在匹配被预测数据的时候就不会有很好的性能。避免决策树学习中的过度拟合问题,通常通过两种方法:
(1)及早停止树增长,比如发现树的高度过高,叶节点过多,或者节点内数据过少。这是sci-kit learn库目前的做法。
(2)通过后剪枝减少决策树的节点的个数。
尽管上面第一种方法可能看起来更直接,但是对过度拟合的树进行后修剪被证明在实践中更成功。这是因为在第一种方法中精确的估计何时停止树增长很困难。后剪枝的算法基本上就是合并同一个根节点下面所有的叶节点成为一个大的节点,而选择哪些节点做合并则需要根据节点内部数据个数。
选取能够得到最大信息增益(information gain)的特征为数据划分归类,直到全部划分结束而不对树的规模进行任何控制。
等树生成之后,执行后剪枝。
信息增益的潜在问题是,比如有一个数据集含有一个特征是日期或者ID,则该特征会得到最大的信息增益,但是显然在验证数据中不会得到任何的结果。C45的信息增益比就是解决这个问题的。
选取能够得到最大信息增益率(information gain ratio)的特征来划分数据,并且像ID3一样执行后剪枝。是ID3的后续版本并扩展了IDC的功能,比如特征数值允许连续,在分类的时候进行离散化。信息增益率:“Gain ratio takes number and size of branches into account when choosing an attribute, and corrects the information gain by taking the intrinsic information of a split into account (i.e. how much info do we need to tell which branch an instance belongs to).”
这是最新的一个版本,是有许可的(proprietary license)。比之C45,减少了内存,使用更少的规则集,并且准确率更高。
CART(Classification and Regression Trees)分类回归树,它使用基尼不纯度(Gini Impurity)来决定划分。Gini Impurity和information gain ratio的理解和区分在这里:http://stats.stackexchange.com/questions/94886/what-is-the-relationship-between-the-gini-score-and-the-log-likelihood-ratio。它和C45基本上是类似的算法,主要区别:1)它的叶节点不是具体的分类,而是是一个函数f(),该函数定义了在该条件下的回归函数。2)CART是二叉树,而不是多叉树。
sci-kit learn提供决策树,是基于优化的CART算法,使用方便简单,但是有两个问题:1)不如C50优化;2)sci-kit learn库并没有实现后剪枝(截至最新版0.16.0),所以防止过拟合的办法都是提前停止生长的方法,可以通过设置参数的方式控制。详情参加:http://scikit-learn.org/stable/modules/tree.html
使用:
from sklearn import tree
clf = tree.DecisionTreeClassifier() or clf = tree.DecisionTreeRegressor
clf = clf.fit(X, Y)
clf.predict([[..]])
clf.predict_proba([[..]])
(其中clf就是最终的分类器,而X是输入数据,Y是label。)
类和函数的原型:
class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, class_weight=None)
输入参数展开说:
结果展开说:
tree_ : Tree 对象(sklearn.tree._tree.Tree),二叉树。根据这个tree_对象,可以还原整个决策树的决策过程。关于tree_的细节,可以参考sklearn的官网,如何把tree可视化,可以参照stackoverflow的问答(参考链接在后面):
from sklearn import tree
from StringIO import StringIO
import pydot (需要首先安装pydot库)
dot_data =StringIO()
tree.export_graphviz(clf,out_file=dot_data)
graph =pydot.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("./iris.pdf")
max_features_ : 参与决策树的特征数。
5. 应用场景和限制
是监督的分类和回归算法。对噪声点的容忍性非常好。性能比较好。贪婪。
详情参阅:http://scikit-learn.org/stable/modules/tree.html
6. 参考
http://scikit-learn.org/stable/modules/tree.html
http://blog.csdn.net/google19890102/article/details/28611225
http://underthehood.blog.51cto.com/2531780/610442
http://blog.csdn.net/cyningsun/article/details/8735169
http://stackoverflow.com/questions/25274673/is-it-possible-to-print-the-decision-tree-in-scikit-learn