原理
決策樹(shù)既可以解決分類(lèi)問(wèn)題,天然地可以解決多分類(lèi)問(wèn)題,也可以解決回歸問(wèn)題
如圖,當(dāng)我們建立好一棵樹(shù)之后,對(duì)于未知的數(shù)據(jù),我們就可以通過(guò)這樣的3次判斷來(lái)確定其分類(lèi)。

那么最重要的問(wèn)題是:我們要如何進(jìn)行節(jié)點(diǎn)的選擇呢?
我們來(lái)看這樣一個(gè)判斷過(guò)程:

對(duì)于每一個(gè)節(jié)點(diǎn),我們需要選擇哪一個(gè)維度,以及這個(gè)維度的劃分的分界點(diǎn)?
信息熵
我們引入信息熵的概率,你可能在信息論中學(xué)過(guò)這個(gè)知識(shí),
我們來(lái)簡(jiǎn)單認(rèn)識(shí)一下,其實(shí)和高中化學(xué)中的熵殊途同歸
信息熵代表隨機(jī)變量不確定度的度量,越小則表示數(shù)據(jù)不確定性越低
而我們做分類(lèi)問(wèn)題實(shí)際上就是確定他的分類(lèi),所以我們需要通過(guò)一次次判斷來(lái)降低其信息熵

我們可以很容易的得出,若某一概率為1,則H為0,至于其他的概率為0的項(xiàng),通過(guò)微積分中最小項(xiàng)的知識(shí),我們?nèi)菀椎贸銎浣Y(jié)果為0,所以H為0達(dá)到最小
我們來(lái)看看二分類(lèi)中信息熵的函數(shù):


這時(shí)候我們可以稍作思考,原來(lái)我們面臨的問(wèn)題是:“每個(gè)節(jié)點(diǎn)如何選擇維度?維度上哪個(gè)值進(jìn)行劃分?”現(xiàn)在問(wèn)題變成了:“我們可以通過(guò)劃分后信息熵能夠最大的降低判斷選擇的節(jié)點(diǎn)對(duì)不對(duì),恰不恰當(dāng)”
所以我們可以在每一個(gè)節(jié)點(diǎn)上一個(gè)個(gè)情況的試,最后選擇使得信息熵有效降低的那一組值。
代碼實(shí)現(xiàn)
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris= datasets.load_iris()
x=iris.data[:,2:]#保留后兩個(gè)特征
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]:#相等時(shí)是區(qū)分不開(kāi)的
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
```
我們進(jìn)行第一次判斷
```
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)
```
我們來(lái)看這時(shí)候左邊的熵和右邊的熵

可見(jiàn)左邊已經(jīng)劃分完畢了,我們對(duì)右邊繼續(xù)劃分
```
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)
```

可見(jiàn)右邊信息熵也一定程度的下降,實(shí)際上我們可以一直換分下去,直至信息熵足夠低
我們使用sklearn中的決策樹(shù)進(jìn)行查看
```
from sklearn.tree import DecisionTreeClassifier
dt_clf=DecisionTreeClassifier(max_depth=2,criterion="entropy")#entropy是信息熵方式
dt_clf.fit(x,y)
dt_clf.score(x,y)
```

#####基尼系數(shù)
除了前面提到的信息熵,我們還可以采用基尼系數(shù)作為判據(jù)


對(duì)于相應(yīng)實(shí)現(xiàn),我們只需要將entropy函數(shù)改成基尼系數(shù)相應(yīng)的函數(shù)就可以了
需要注意的是,sklearn中默認(rèn)使用基尼系數(shù)而不是信息熵
#####CART
CART:根據(jù)某一個(gè)維度d和某一個(gè)閾值v進(jìn)行劃分
也就是我們前面構(gòu)建的方式,同時(shí)sklearn也是使用這種方式實(shí)現(xiàn)決策樹(shù)的
還有ID3,C4.5,C5.0等方式
現(xiàn)在我們來(lái)看看sklearn中決策樹(shù)模型的一些參數(shù)
max_depth決策樹(shù)深度
min_samples_split拆分需要的最少的數(shù)據(jù),少于這個(gè)值便不再拆分了,防止過(guò)擬合
min_samples_leaf對(duì)于一個(gè)結(jié)點(diǎn)最少需要的數(shù)據(jù),也就是最后分類(lèi)停下來(lái)的條件
max_leaf_nodes最對(duì)有的結(jié)點(diǎn)數(shù)
###決策樹(shù)解決回歸問(wèn)題
sklearn中有相應(yīng)的函數(shù)如下:
```
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)
#實(shí)際上這里size默認(rèn)是0.2
from sklearn.tree import DecisionTreeRegressor
dt_reg=DecisionTreeRegressor()
dt_reg.fit(x_train,y_train)
dt_reg.score(x_test,y_test)
```
###總結(jié)
本文僅是作為決策樹(shù)知識(shí)的入門(mén),了解了基本的原理之后還有不少需要補(bǔ)充的知識(shí),后續(xù)還會(huì)再補(bǔ)上!