决策树(DTS)是一种非参数监督学习用于方法分类和回归。我们的目标是创建一个预测通过学习从数据推断出功能简单的决策规则的目标变量的值的模型。
决策树的一些优点是:
决策树的缺点包括:
已知训练向量 x i ∈ R n , i = 1 , … , 1 x_{i} \in R^{n}, i=1, \dots, 1 xi∈Rn,i=1,…,1和标签向量 y ∈ R l y \in R^{l} y∈Rl ,决策树迭代式地把空间分为拥有相同标签数据的集合。
设 Q Q Q表示在节点 m m m的数据。每一个候补的分割 θ = ( j , t m ) \theta=\left(j, t_{m}\right) θ=(j,tm),它包含了一个特征 j j j 和阀值 t m t_m tm,把数据划分为为两个子集 Q left ( θ ) Q_{\text {left}}(\theta) Qleft(θ)和 Q right ( θ ) Q_{\text {right}}(\theta) Qright(θ)
Q left ( θ ) = ( x , y ) ∣ x j < = t m Q right ( θ ) = Q \ Q left ( θ ) \begin{array}{l}{Q_{\text {left}}(\theta)=(x, y) | x_{j}<=t_{m}} \\ {Q_{\text {right}}(\theta)=Q \backslash Q_{\text {left}}(\theta)}\end{array} Qleft(θ)=(x,y)∣xj<=tmQright(θ)=Q\Qleft(θ)
节点 m m m杂质度有函数 H ( ) H() H()计算,公式的选择有任务的类型决定(分类和回归)
G ( Q , θ ) = n l e f t N m H ( Q l e f t ( θ ) ) + n r i g h t N m H ( Q r i g h t ( θ ) ) G(Q, \theta)=\frac{n_{l e f t}}{N_{m}} H\left(Q_{l e f t}(\theta)\right)+\frac{n_{r i g h t}}{N_{m}} H\left(Q_{r i g h t}(\theta)\right) G(Q,θ)=NmnleftH(Qleft(θ))+NmnrightH(Qright(θ))
选择合适的分割,最小化杂质度
θ ∗ = argmin θ G ( Q , θ ) \theta^{*}=\operatorname{argmin}_{\theta} G(Q, \theta) θ∗=argminθG(Q,θ)
递归去获得子集 Q left ( θ ∗ ) Q_{\text {left}}(\theta^*) Qleft(θ∗)和 Q right ( θ ∗ ) Q_{\text {right}}(\theta^*) Qright(θ∗)直到到达最大的深度,或者 N m < m i n samples N_{m}<\mathrm{min}_{\text {samples}} Nm<minsamples或者 N m = 1 N_{m}=1 Nm=1
假设一个分类结果输出 0 , 1 , … , K − 1 0,1, \ldots, \mathrm{K}-1 0,1,…,K−1,节点 m m m,由一个带有 N m N_{m} Nm个观测值的 R m R_{m} Rm区域表示,并且
p m k = 1 / N m ∑ x i ∈ R m I ( y i = k ) p_{m k}=1 / N_{m} \sum_{x_{i} \in R_{m}} I\left(y_{i}=k\right) pmk=1/Nmxi∈Rm∑I(yi=k)
p m k p_{m k} pmk表示属于类别 k k k的样本在节点 m m m中的比例
一般杂质度的计算方式是Gini
H ( X m ) = ∑ k p m k ( 1 − p m k ) H\left(X_{m}\right)=\sum_{k} p_{m k}\left(1-p_{m k}\right) H(Xm)=k∑pmk(1−pmk)
熵:
H ( X m ) = − ∑ k p m k log ( p m k ) H\left(X_{m}\right)=-\sum_{k} p_{m k} \log \left(p_{m k}\right) H(Xm)=−k∑pmklog(pmk)
和错误分类:
H ( X m ) = 1 − max ( p m k ) H\left(X_{m}\right)=1-\max \left(p_{m k}\right) H(Xm)=1−max(pmk)
如果目标是一个连续的值,则节点 m m m,表示拥有 N m N_m Nm个观察的区域 R m R_m Rm,最优化分割位置的通用标准是均方误差(使用平均值最小化的L2误差)和平均绝对误差(使用中值最小化的L1误差)
均方误差:
y ‾ m = 1 N m ∑ i ∈ N m y i H ( X m ) = 1 N m ∑ i ∈ N m ( y i − y ‾ m ) 2 \begin{array}{c}{\overline{y}_{m}=\frac{1}{N_{m}} \sum_{i \in N_{m}} y_{i}} \\ {H\left(X_{m}\right)=\frac{1}{N_{m}} \sum_{i \in N_{m}}\left(y_{i}-\overline{y}_{m}\right)^{2}}\end{array} ym=Nm1∑i∈NmyiH(Xm)=Nm1∑i∈Nm(yi−ym)2
平均绝对误差:
y ‾ m = 1 N m ∑ i ∈ N m y i H ( X m ) = 1 N m ∑ i ∈ N m ∣ y i − y ‾ m ∣ \begin{array}{c}{\overline{y}_{m}=\frac{1}{N_{m}} \sum_{i \in N_{m}} y_{i}} \\ {H\left(X_{m}\right)=\frac{1}{N_{m}} \sum_{i \in N_{m}}\left|y_{i}-\overline{y}_{m}\right|}\end{array} ym=Nm1∑i∈NmyiH(Xm)=Nm1∑i∈Nm∣yi−ym∣
其中 X m X_{m} Xm表示节点 m m m中的训练数据
DecisionTreeClassifier是一个能够对数据集进行多类分类的一个工具类。
输入1:数列X,装训练数据,[n_samples, n_features]
输入2:数列Y,装训练标签,[n_samples]
>>> from sklearn import tree
>>> X = [[0, 0], [1, 1]]
>>> Y = [0, 1]
>>> clf = tree.DecisionTreeClassifier()
>>> clf = clf.fit(X, Y)
拟合后,进行预测
>>> clf.predict([[2., 2.]])
array([1])
还可以预测每类的概率
>>> clf.predict_proba([[2., 2.]])
array([[0., 1.]])
DecisionTreeClassifier 能够二进制的(其中标记物是[-1,1])分类和多类(其中标记物是[0,…,K-1])的分类。
使用Iris数据集构建决策树
>>> from sklearn.datasets import load_iris
>>> from sklearn import tree
>>> iris = load_iris()
>>> clf = tree.DecisionTreeClassifier()
>>> clf = clf.fit(iris.data, iris.target)
经过训练后,我们可以使用export_graphviz 导出Graphviz格式的决策树。
graphviz 安装,在conda环境中:
conda install python-graphviz
python环境下安装
pypi with pip install graphviz
例子,图输出到iris.pdf
>>> import graphviz
>>> dot_data = tree.export_graphviz(clf, out_file=None)
>>> graph = graphviz.Source(dot_data)
>>> graph.render("iris")
决策树也可以使用 DecisionTreeRegressor适用于回归问题
输入与分类方法类似,只是标签可以是float,而分类是integer
>>> from sklearn import tree
>>> X = [[0, 0], [2, 2]]
>>> y = [0.5, 2.5]
>>> clf = tree.DecisionTreeRegressor()
>>> clf = clf.fit(X, y)
>>> clf.predict([[1, 1]])
array([0.5])
多输出问题就是说需要预测多个输出,标签 Y Y Y是2D数列,[n_samples, n_outputs]。
当在输出端之间没有相关性,一个非常简单的方法来解决这类问题是建立n个独立的模型,即,一个用于每个输出,然后使用这些模型来独立地预测n个输出端中的每一个。然而,很有可能它是相同的输入相关,更好的方式是建立能够同时预测所有n个输出端的一个单一的模式。首先,训练时间短,因为只有一个单一估计模型。其次,将所得估计的泛化精度通常会增加。
对于决策树,这种策略可以很容易地被用来支持多输出的问题。这需要以下变化:
### your code goes here ###
from sklearn import tree
clf = tree.DecisionTreeClassifier(min_samples_split=40)
t0 = time()
#print len(features_train[0])
clf.fit(features_train,labels_train)
print "training time:", round(time()-t0,3),"s"
t0 = time()
pred =clf.predict(features_test)
print "predict time:", round(time()-t0,3),"s"
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(labels_test,pred)
print accuracy
https://scikit-learn.org/stable/modules/tree.html