day-7 sklearn庫實現ID3決策樹算法


 

  本文介紹如何利用決策樹/判定樹(decision tree)中決策樹歸納算法(ID3)解決機器學習中的回歸問題。文中介紹基於有監督的學習方式,如何利用年齡、收入、身份、收入、信用等級等特征值來判定用戶是否購買電腦的行為,最后利用python和sklearn庫實現了該應用。

  1、  決策樹歸納算法(ID3)實例介紹

  2、  如何利用python實現決策樹歸納算法(ID3)

1、決策樹歸納算法(ID3)實例介紹

  首先介紹下算法基本概念,判定樹是一個類似於流程圖的樹結構:其中,每個內部結點表示在一個屬性上的測試,每個分支代表一個屬性輸出,而每個樹葉結點代表類或類分布。樹的最頂層是根結點。

  決策樹的優點: 直觀,便於理解,小規模數據集有效    

  決策樹的缺點:處理連續變量不好,類別較多時,錯誤增加的比較快,可規模性一般

  以如下測試數據為例:

   

  我們有一組已知訓練集數據,顯示用戶購買電腦行為與各個特征值的關系,我們可以繪制出如下決策樹圖像(繪制方法后面介紹) 

  

  此時,輸入一個新的測試數據,就能根據該決策樹很容易判定出用戶是否購買電腦的行為。

  有兩個關鍵點需要考慮:1、如何決定分支終止;2如何決定各個節點的位置,例如根節點如何確定。

         1、如何決定分支終止

         如果某個節點所有標簽均為同一類,我們將不再繼續繪制分支,直接標記結果。或者分支過深,可以基於少數服從多數的算法,終止該分支直接繪制結果。

   

         例如,通過年齡划分,所有middle_aged對象,對應的標簽都為yes,盡管還有其它特征值,例如收入、身份、信用等級等,但由於標簽所有都為一類,所以該分支直接標注結果為yes,不再往下細分。

  2、如何決定各個節點的位置,例如根節點如何確定。

  在說明這個問題之前,我們先討論一個熵的概,信息和抽象,如何度量?1948年,香農提出了 “信息熵(entropy)”的概念,一條信息的信息量大小和它的不確定性有直接的關系,要搞清楚一件非常非常不確定的事情,或者是我們一無所知的事情,需要了解大量信息==>信息量的度量就等於不確定性的多少

  例子:猜世界杯冠軍,假如一無所知,猜多少次?每個隊奪冠的幾率不是相等的,也就說明該信息熵較大。

  當前樣本集合 D 中第 k 類樣本所占的比例為 pk ,則 D 的信息熵定義為

  

  離散屬性 a 有 V 個可能的取值 {a1,a2,…,aV};樣本集合中,屬性 a 上取值為 av 的樣本集合,記為 Dv。用屬性 a 對樣本集 D 進行划分所獲得的“信息增益”,表示得知屬性 a 的信息而使得樣本集合不確定度減少的程,公式如下:

  

 

  ID3算法首先計算各個特征向量的信息增益量,取最大的作為決策樹的根,利用上面公式,以計算age年齡的信息增益量為例:

   

  於是,我們選取age年齡作為決策樹的根節點,依次畫出最后的決策樹,最后的算法如下:

    •   樹以代表訓練樣本的單個結點開始(步驟1)。
    •   如果樣本都在同一個類,則該結點成為樹葉,並用該類標號(步驟2 和3)。
    •   否則,算法使用稱為信息增益的基於熵的度量作為啟發信息,選擇能夠最好地將樣本分類的屬性(步驟6)。該屬性成為該結點的“測試”或“判定”屬性(步驟7)。在算法的該版本中,
    •   所有的屬性都是分類的,即離散值。連續屬性必須離散化。
    •   對測試屬性的每個已知的值,創建一個分枝,並據此划分樣本(步驟8-10)。
    •   算法使用同樣的過程,遞歸地形成每個划分上的樣本判定樹。一旦一個屬性出現在一個結點上,就不必該結點的任何后代上考慮它(步驟13)。
    •   遞歸划分步驟僅當下列條件之一成立停止:
    •   (a) 給定結點的所有樣本屬於同一類(步驟2 和3)。
    •   (b) 沒有剩余屬性可以用來進一步划分樣本(步驟4)。在此情況下,使用多數表決(步驟5)。
    •   這涉及將給定的結點轉換成樹葉,並用樣本中的多數所在的類標記它。替換地,可以存放結
    • 點樣本的類分布。
    •   (c) 分枝
    •   test_attribute = a i 沒有樣本(步驟11)。在這種情況下,以 samples 中的多數類
    •   創建一個樹葉(步驟12)

 

  除了ID3算法,還有一些其它算法可以用來繪制決策樹,此處暫不討論,例如:C4.5:  Quinlan,Classification and Regression Trees (CART): (L. Breiman, J. Friedman, R. Olshen, C. Stone)。共同點:都是貪心算法,自上而下(Top-down approach)。區別:屬性選擇度量方法不同: C4.5 (gain ratio), CART(gini index), ID3 (Information Gain)

2、  如何利用python實現決策樹歸納算法(ID3)

  用Python實現上面實例前,我們需要先安裝一個科學庫Anaconda,anaconda指的是一個開源的Python發行版本,其包含了conda、Python等180多個科學包及其依賴項。

  同時,還需要安裝一個決策樹圖形繪制工具graphviz

  下面是具體的代碼實現

# 導入庫
from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import preprocessing
from sklearn.externals.six import StringIO
import math

# 測試,沒有age時的信息熵
result = -(5/14*math.log2(5/14) + 9/14*math.log2(9/14))
print(result)

#測試,有age時的信息熵
result1 = 5/14*(-3/5*math.log2(3/5) - 2/5*math.log(2/5)) + 4/14*(-4/4*math.log2(4/4)) + 5/14*(-3/5*math.log2(3/5) - 2/5*math.log2(2/5))
print(result1)

# 1 打開測試數據集
allElectronicsData = open(r'D:\test.csv','r')
reader = csv.reader(allElectronicsData)
# 讀取文件頭
headers = next(reader)
#print(headers)

featureList = []
labelList = []

# 2 為每個測試樣例,建立一個特征名和值的字典,然后加入到featureList中
for row in reader:
    labelList.append(row[len(row) -1])
    rowDict = {}
    for i in range(1,len(row) -1):
        rowDict[headers[i]] = row[i]
    featureList.append(rowDict)
print(labelList)
print(featureList)

# 3 把輸入特征集進行轉換,例如
'''
{'age': 'youth', 'income': 'high', 'student': 'no', 'credit_rating': 'fair'}
[ 0.  0.  1.  0.  1.  1.  0.  0.  1.  0.]
'''
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()
#print(type(dummyX))
print(dummyX)
#print(vec.get_feature_names())

# 4 對標簽值進行0,1轉換
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
print(dummyY)

# 5 直接調用庫的決策樹分類器,entropy表示信息熵
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX,dummyY)
#print(clf)

# 6 填入feature_names,還原原有的值,寫入test.dot文件
with open("test.dot",'w') as f:
    f = tree.export_graphviz(clf,feature_names=vec.get_feature_names(),out_file=f)

# 7 此時dumyX為一個n維的向量,取出第一行,修改一下作為一個新的測試數據
# 'age': 'middle_aged', 'income': 'high', 'student': 'no', 'credit_rating': 'fair' 正確結果應該是 買 為1
oneRowX = dummyX[0,:]
print("oneRowX:  ",oneRowX)
newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print(newRowX)

# 8 使用新數據進行測試驗證
predictedY = clf.predict(newRowX.reshape(1, -1))
print(predictedY)

# 使用graphviz工具,通過命令dot -Tpdf test.dot -o output.pdf生成決策樹文檔

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM