原理
决策树既可以解决分类问题,天然地可以解决多分类问题,也可以解决回归问题
如图,当我们建立好一棵树之后,对于未知的数据,我们就可以通过这样的3次判断来确定其分类。
示意图
那么最重要的问题是:我们要如何进行节点的选择呢?
我们来看这样一个判断过程:
示例
对于每一个节点,我们需要选择哪一个维度,以及这个维度的划分的分界点?
信息熵
我们引入信息熵的概率,你可能在信息论中学过这个知识,
我们来简单认识一下,其实和高中化学中的熵殊途同归
信息熵代表随机变量不确定度的度量,越小则表示数据不确定性越低
而我们做分类问题实际上就是确定他的分类,所以我们需要通过一次次判断来降低其信息熵
信息熵计算公式
我们可以很容易的得出,若某一概率为1,则H为0,至于其他的概率为0的项,通过微积分中最小项的知识,我们容易得出其结果为0,所以H为0达到最小
我们来看看二分类中信息熵的函数:
二分类中信息熵函数 二分类中信息熵函数曲线
这时候我们可以稍作思考,原来我们面临的问题是:“每个节点如何选择维度?维度上哪个值进行划分?”现在问题变成了:“我们可以通过划分后信息熵能够最大的降低判断选择的节点对不对,恰不恰当”
所以我们可以在每一个节点上一个个情况的试,最后选择使得信息熵有效降低的那一组值。
代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris= datasets.load_iris()
x=iris.data[:,2:]#保留后两个特征
y=iris.target
def split(x,y,d,value):#d为维度,value为划分值
index_a=(x[:,d]<=value)
index_b=(x[:,d]>value)
return x[index_a],x[index_b],y[index_a],y[index_b]
from collections import Counter
from math import log
def entropy(y):
counter=Counter(y)
res=0.0
for num in counter.values():
p=num/len(y)
res+=-p*log(p)
return res
def try_split(x,y):
best_intropy=float('inf')
best_d,best_v=-1,-1
for d in range(x.shape[1]):#遍历每一列
sort_index=np.argsort(x[:,d])#第d列排序
for i in range(1,len(x)):
if x[sort_index[i-1],d]!=x[sort_index[i],d]:#相等时是区分不开的
v=(x[sort_index[i-1],d]+x[sort_index[i],d])/2#作为备选value值
x_l,x_r,y_l,y_r=split(x,y,d,v)
e=entropy(y_l)+entropy(y_r)
if e<best_intropy:
best_intropy,best_d,best_v=e,d,v
return best_intropy,best_d,best_v
```
我们进行第一次判断
```
best_entropy,best_d,best_v= try_split(x,y)
x1_l,x1_r,y1_l,y1_r= split(x,y,best_d,best_v)
```
我们来看这时候左边的熵和右边的熵
![信息熵1](https://img.haomeiwen.com/i19479038/a7dc68398b05b47a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可见左边已经划分完毕了,我们对右边继续划分
```
best_entropy2,best_d2,best_v2=try_split(x1_r,y1_r)
x2_l,x2_r,y2_l,y2_r= split(x1_r,y1_r,best_d2,best_v2)
```
![信息熵2](https://img.haomeiwen.com/i19479038/7dc340e392139609.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可见右边信息熵也一定程度的下降,实际上我们可以一直换分下去,直至信息熵足够低
我们使用sklearn中的决策树进行查看
```
from sklearn.tree import DecisionTreeClassifier
dt_clf=DecisionTreeClassifier(max_depth=2,criterion="entropy")#entropy是信息熵方式
dt_clf.fit(x,y)
dt_clf.score(x,y)
```
![sklearn的结果](https://img.haomeiwen.com/i19479038/ab94532720e64f04.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#####基尼系数
除了前面提到的信息熵,我们还可以采用基尼系数作为判据
![基尼系数公式](https://img.haomeiwen.com/i19479038/06e936391552d232.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![二分类中的基尼系数函数](https://img.haomeiwen.com/i19479038/6d55da7d010e8666.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
对于相应实现,我们只需要将entropy函数改成基尼系数相应的函数就可以了
需要注意的是,sklearn中默认使用基尼系数而不是信息熵
#####CART
CART:根据某一个维度d和某一个阈值v进行划分
也就是我们前面构建的方式,同时sklearn也是使用这种方式实现决策树的
还有ID3,C4.5,C5.0等方式
现在我们来看看sklearn中决策树模型的一些参数
max_depth决策树深度
min_samples_split拆分需要的最少的数据,少于这个值便不再拆分了,防止过拟合
min_samples_leaf对于一个结点最少需要的数据,也就是最后分类停下来的条件
max_leaf_nodes最对有的结点数
###决策树解决回归问题
sklearn中有相应的函数如下:
```
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
boston= datasets.load_boston()
x=boston.data
y=boston.target
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=666)
#实际上这里size默认是0.2
from sklearn.tree import DecisionTreeRegressor
dt_reg=DecisionTreeRegressor()
dt_reg.fit(x_train,y_train)
dt_reg.score(x_test,y_test)
```
###总结
本文仅是作为决策树知识的入门,了解了基本的原理之后还有不少需要补充的知识,后续还会再补上!
网友评论