1. 決策樹分類算法原理
1.1 概述
(資料圖)
決策樹(decision tree)——是一種被廣泛使用的分類算法。
相比貝葉斯算法,決策樹的優(yōu)勢在于構(gòu)造過程不需要任何領(lǐng)域知識或參數(shù)設(shè)置
在實(shí)際應(yīng)用中,對于探測式的知識發(fā)現(xiàn),決策樹更加適用
1.2 算法思想
通俗來說,決策樹分類的思想類似于找對象?,F(xiàn)想象一個(gè)女孩的母親要給這個(gè)女孩介紹男朋友,于是有了下面的對話:
女兒:多大年紀(jì)了?
母親:26。
女兒:長的帥不帥?
母親:挺帥的。
女兒:收入高不?
母親:不算很高,中等情況。
女兒:是公務(wù)員不?
母親:是,在稅務(wù)局上班呢。
女兒:那好,我去見見。
這個(gè)女孩的決策過程就是典型的分類樹決策。
實(shí)質(zhì):通過年齡、長相、收入和是否公務(wù)員對將男人分為兩個(gè)類別:見和不見
假設(shè)這個(gè)女孩對男人的要求是:30歲以下、長相中等以上并且是高收入者或中等以上收入的公務(wù)員,那么這個(gè)可以用下圖表示女孩的決策邏輯
上圖完整表達(dá)了這個(gè)女孩決定是否見一個(gè)約會對象的策略,其中:
綠色節(jié)點(diǎn)表示判斷條件
橙色節(jié)點(diǎn)表示決策結(jié)果
箭頭表示在一個(gè)判斷條件在不同情況下的決策路徑
圖中紅色箭頭表示了上面例子中女孩的決策過程。
這幅圖基本可以算是一顆決策樹,說它“基本可以算”是因?yàn)閳D中的判定條件沒有量化,如收入高中低等等,還不能算是嚴(yán)格意義上的決策樹,如果將所有條件量化,則就變成真正的決策樹了。
決策樹分類算法的關(guān)鍵就是根據(jù)“先驗(yàn)數(shù)據(jù)”構(gòu)造一棵最佳的決策樹,用以預(yù)測未知數(shù)據(jù)的類別
決策樹:是一個(gè)樹結(jié)構(gòu)(可以是二叉樹或非二叉樹)。其每個(gè)非葉節(jié)點(diǎn)表示一個(gè)特征屬性上的測試,每個(gè)分支代表這個(gè)特征屬性在某個(gè)值域上的輸出,而每個(gè)葉節(jié)點(diǎn)存放一個(gè)類別。使用決策樹進(jìn)行決策的過程就是從根節(jié)點(diǎn)開始,測試待分類項(xiàng)中相應(yīng)的特征屬性,并按照其值選擇輸出分支,直到到達(dá)葉子節(jié)點(diǎn),將葉子節(jié)點(diǎn)存放的類別作為決策結(jié)果。
1.3 決策樹構(gòu)造
1.3.1 決策樹構(gòu)造樣例
假如有以下判斷蘋果好壞的數(shù)據(jù)樣本:
樣本 紅 大 好蘋果 0 1 1 1 1 1 0 1 2 0 1 0 3 0 0 0 |
樣本中有2個(gè)屬性,A0表示是否紅蘋果。A1表示是否大蘋果。假如要根據(jù)這個(gè)數(shù)據(jù)樣本構(gòu)建一棵自動判斷蘋果好壞的決策樹。
由于本例中的數(shù)據(jù)只有2個(gè)屬性,因此,我們可以窮舉所有可能構(gòu)造出來的決策樹,就2棵,如下圖所示:
顯然左邊先使用A0(紅色)做劃分依據(jù)的決策樹要優(yōu)于右邊用A1(大小)做劃分依據(jù)的決策樹。
當(dāng)然這是直覺的認(rèn)知。而直覺顯然不適合轉(zhuǎn)化成程序的實(shí)現(xiàn),所以需要有一種定量的考察來評價(jià)這兩棵樹的性能好壞。
決策樹的評價(jià)所用的定量考察方法為計(jì)算每種劃分情況的信息熵增益:
如果經(jīng)過某個(gè)選定的屬性進(jìn)行數(shù)據(jù)劃分后的信息熵下降最多,則這個(gè)劃分屬性是最優(yōu)選擇
1.3.2 屬性劃分選擇(即構(gòu)造決策樹)的依據(jù)
熵:信息論的奠基人香農(nóng)定義的用來信息量的單位。簡單來說,熵就是“無序,混亂”的程度。
通過計(jì)算來理解:
1、原始樣本數(shù)據(jù)的熵:
樣例總數(shù):4
好蘋果:2
壞蘋果:2
熵:-(1/2 * log(1/2) +1/2 * log(1/2)) = 1
信息熵為1表示當(dāng)前處于最混亂,最無序的狀態(tài)。
2、兩顆決策樹的劃分結(jié)果熵增益計(jì)算
l樹1先選A0作劃分,各子節(jié)點(diǎn)信息熵計(jì)算如下:
0,1葉子節(jié)點(diǎn)有2個(gè)正例,0個(gè)負(fù)例。信息熵為:e1 = -(2/2 * log(2/2) + 0/2 * log(0/2)) = 0。
2,3葉子節(jié)點(diǎn)有0個(gè)正例,2個(gè)負(fù)例。信息熵為:e2 = -(0/2 * log(0/2) + 2/2 * log(2/2)) = 0。
因此選擇A0劃分后的信息熵為每個(gè)子節(jié)點(diǎn)的信息熵所 zhan bi zhong 的加權(quán)和:
選擇A0做劃分的信息熵增益G(S, A0)=S - E = 1 - 0 = 1.
事實(shí)上,決策樹葉子節(jié)點(diǎn)表示已經(jīng)都屬于相同類別,因此信息熵一定為0。
l樹2先選A1作劃分,各子節(jié)點(diǎn)信息熵計(jì)算如下:
0,2子節(jié)點(diǎn)有1個(gè)正例,1個(gè)負(fù)例。信息熵為:e1 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1。
1,3子節(jié)點(diǎn)有1個(gè)正例,1個(gè)負(fù)例。信息熵為:e2 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1。
因此選擇A1劃分后的信息熵為每個(gè)子節(jié)點(diǎn)的信息熵所zhan bi zhong的加權(quán)和:
也就是說分了跟沒分一樣!
選擇A1做劃分的信息熵增益G(S, A1)=S - E = 1 - 1 = 0.
因此,每次劃分之前,我們只需要計(jì)算出信息熵增益最大的那種劃分即可。
1.4 算法要點(diǎn)
1.4.1、指導(dǎo)思想
經(jīng)過決策屬性的劃分后,數(shù)據(jù)的無序度越來越低,也就是信息熵越來越小
1.4.2算法實(shí)現(xiàn)
梳理出數(shù)據(jù)中的屬性
比較按照某特定屬性劃分后的數(shù)據(jù)的信息熵增益,選擇信息熵增益最大的那個(gè)屬性作為第一劃分依據(jù),然后繼續(xù)選擇第二屬性,以此類推
2. 決策樹分類算法Python實(shí)戰(zhàn)
2.1 案例需求
我們的任務(wù)就是訓(xùn)練一個(gè)決策樹分類器,輸入身高和體重,分類器能給出這個(gè)人是胖子還是瘦子。
所用的訓(xùn)練數(shù)據(jù)如下,這個(gè)數(shù)據(jù)一共有10個(gè)樣本,每個(gè)樣本有2個(gè)屬性,分別為身高和體重,第三列為類別標(biāo)簽,表示“胖”或“瘦”。該數(shù)據(jù)保存在1.txt中。
1.5 50 thin 1.5 60 fat 1.6 40 thin 1.6 60 fat 1.7 60 thin 1.7 80 fat 1.8 60 thin 1.8 90 fat 1.9 70 thin 1.9 80 fat |
2.2 模型分析
決策樹對于“是非”的二值邏輯的分枝相當(dāng)自然。而在本數(shù)據(jù)集中,身高與體重是連續(xù)值怎么辦呢?
雖然麻煩一點(diǎn),不過這也不是問題,只需要找到將這些連續(xù)值劃分為不同區(qū)間的中間點(diǎn),就轉(zhuǎn)換成了二值邏輯問題。
本例決策樹的任務(wù)是找到身高、體重中的一些臨界值,按照大于或者小于這些臨界值的邏輯將其樣本兩兩分類,自頂向下構(gòu)建決策樹。
2.3 python實(shí)現(xiàn)
使用python的機(jī)器學(xué)習(xí)庫,實(shí)現(xiàn)起來相當(dāng)簡單和優(yōu)雅
?# -*- coding: utf-8 -*- import numpy as np import scipy as sp from sklearn import tree from sklearn.metrics import precision_recall_curve from sklearn.metrics import classification_report from sklearn.cross_validation import train_test_split """ 數(shù)據(jù)讀入 """ data = [] labels = [] with open("d:\\python\\ml\\data\\1.txt") as ifile: for line in ifile: tokens = line.strip().split(" ") data.append([float(tk) for tk in tokens[:-1]]) labels.append(tokens[-1]) x = np.array(data) labels = np.array(labels) y = np.zeros(labels.shape) """ 標(biāo)簽轉(zhuǎn)換為0/1 """ y[labels=="fat"]=1 """ 拆分訓(xùn)練數(shù)據(jù)與測試數(shù)據(jù) """ x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2) """ 使用信息熵作為劃分標(biāo)準(zhǔn),對決策樹進(jìn)行訓(xùn)練 """ clf = tree.DecisionTreeClassifier(criterion="entropy") print(clf) clf.fit(x_train, y_train) """ 把決策樹結(jié)構(gòu)寫入文件 """ with open("tree.dot", "w") as f: f = tree.export_graphviz(clf, out_file=f) """ 系數(shù)反映每個(gè)特征的影響力。越大表示該特征在分類中起到的作用越大 """ print(clf.feature_importances_) """測試結(jié)果的打印""" answer = clf.predict(x_train) print(x_train) print(answer) print(y_train) print(np.mean( answer == y_train)) """準(zhǔn)確率與召回率""" precision, recall, thresholds = precision_recall_curve(y_train, clf.predict(x_train)) answer = clf.predict_proba(x)[:,1] print(classification_report(y, answer, target_names = ["thin", "fat"]))? |
這時(shí)候會輸出
[ 0.2488562 0.7511438] array([[ 1.6, 60. ], [ 1.7, 60. ], [ 1.9, 80. ], [ 1.5, 50. ], [ 1.6, 40. ], [ 1.7, 80. ], [ 1.8, 90. ], [ 1.5, 60. ]]) array([ 1., 0., 1.?, 0., 0., 1., 1., 1.]) array([ 1., 0., 1., 0., 0., 1., 1., 1.]) 1.0 precision recall f1-score support thin 0.83 1.00 0.91 5 fat 1.000.80 0.89 5 avg / total 1.00 1.00 1.00 8 array([ 0., 1., 0., 1., 0., 1., 0., 1.,0., 0.]) array([ 0., 1., 0., 1., 0., 1., 0., 1.,0., 1.]) 可以看到,對訓(xùn)練過的數(shù)據(jù)做測試,準(zhǔn)確率是100%。但是最后將所有數(shù)據(jù)進(jìn)行測試,會出現(xiàn)1個(gè)測試樣本分類錯誤。 說明本例的決策樹對訓(xùn)練集的規(guī)則吸收的很好,但是預(yù)測性稍微差點(diǎn)。? |
2.4 決策樹的保存
一棵決策樹的學(xué)習(xí)訓(xùn)練是非常耗費(fèi)運(yùn)算時(shí)間的,因此,決策樹訓(xùn)練出來后,可進(jìn)行保存,以便在預(yù)測新數(shù)據(jù)時(shí)只需要直接加載訓(xùn)練好的決策樹即可
本案例的代碼中已經(jīng)決策樹的結(jié)構(gòu)寫入了tree.dot中。打開該文件,很容易畫出決策樹,還可以看到?jīng)Q策樹的更多分類信息。
本例的tree.dot如下所示:
?digraph Tree { 0 [label="X[1]<= 55.0000\nentropy = 0.954434002925\nsamples = 8", shape="box"] ; 1 [label="entropy = 0.0000\nsamples = 2\nvalue = [ 2. 0.]", shape="box"] ; 0 -> 1 ; 2 [label="X[1]<= 70.0000\nentropy = 0.650022421648\nsamples = 6", shape="box"] ; 0 -> 2 ; 3 [label="X[0]<= 1.6500\nentropy = 0.918295834054\nsamples = 3", shape="box"] ; 2 -> 3 ; 4 [label="entropy = 0.0000\nsamples = 2\nvalue = [ 0. 2.]", shape="box"] ; 3 -> 4 ; 5 [label="entropy = 0.0000\nsamples = 1\nvalue = [ 1. 0.]", shape="box"] ; 3 -> 5 ; 6 [label="entropy = 0.0000\nsamples = 3\nvalue = [ 0. 3.]", shape="box"] ; 2 -> 6 ; }? |
根據(jù)這個(gè)信息,決策樹應(yīng)該長的如下這個(gè)樣子:
標(biāo)簽: 機(jī)器學(xué)習(xí) 二值邏輯 基本可以