1. 程式人生 > >機器學習(三)決策樹演算法ID3的實現

機器學習(三)決策樹演算法ID3的實現

    上一篇機器學習的部落格我詳細說了機器學習中決策樹演算法的原理,這篇部落格我就以一個小例子來說明機器學習中決策樹演算法的實現。用Python實現機器學習中的決策樹演算法需要用到機器學習的庫,sklearn,我的部落格有詳細講解怎麼安裝機器學習中用到的sklearn庫,如果我們安裝的可以照著這篇部落格去安裝----Python2.7中安裝sklearn

        補充和總結一下上一篇部落格決策樹中的演算法:

        ID3(Iterative Dichotomiser 3)是由羅斯奎因蘭(Ros Quinlan)於1986年開發的。該演算法建立一個多路樹,找到每個節點(即以貪婪的方式)分類特徵,這將產生分類目標的最大資訊增益。樹生長到最大尺寸,然後通常應用修剪步驟,以提高樹的概括性來看待資料的能力。
       C4.5是ID3的後繼者,並且通過動態定義將連續屬性值分割成離散的一組間隔的離散屬性(基於數值變數)來去除特徵必須是分類的限制。C4.5將訓練好的樹(即ID3演算法的輸出)轉換成if-then規則的集合。然後評估每個規則的這些準確性以確定應用它們的順序。如果規則的準確性沒有改善,則通過刪除規則的前提條件來完成修剪。
       C5.0是Quinlan根據專有許可證釋出的最新版本。它使用更少的記憶體,並建立比C4.5更小的規則集,同時更準確。
        CART(分類和迴歸樹)與C4.5非常相似,但它不同之處在於它支援數值目標變數(迴歸),並且不計算規則集。CART使用在每個節點產生最大資訊增益的特徵和閾值構造二叉樹。

       決策樹的優點:
            簡單的理解和解釋。樹木視覺化。
            需要很少的資料準備。其他技術通常需要資料歸一化,需要建立虛擬變數,並刪除空值。但請注意,此模組不支援缺少值。
            使用樹的成本(即,預測資料)在用於訓練樹的資料點的數量上是對數的。
            能夠處理數字和分類資料。其他技術通常專門用於分析只有一種變數型別的資料集。見演算法,以獲取更多資訊。
            能夠處理多輸出問題。
            使用白盒子模型。如果給定的情況在模型中可以觀察到,那麼條件的解釋很容易用布林邏輯來解釋。相比之下,在黑箱模型(例如,在人工神經網路中)中,結果可能更難以解釋。
            可以使用統計

測試驗證模型。這使得可以考慮模型的可靠性。
            即使其假設被資料生成的真實模型有些違反,表現良好。
     決策樹的缺點:
            決策樹學習者可以建立不能很好地推廣資料的過於複雜的樹。這被稱為過擬合。修剪(目前不支援)的機制,設定葉節點所需的最小樣本數或設定樹的最大深度是避免此問題的必要條件。
          決策樹可能不穩定,因為資料的小變化可能會導致完全不同的樹被生成。通過使用合奏中的決策樹來減輕這個問題。
          學習最佳決策樹的問題被認為是在最優性的幾個方面的NP完全,甚至對於簡單的概念。因此,實際的決策樹學習演算法基於啟發式演算法,例如在每個節點進行區域性最優決策的貪心演算法。這樣的演算法不能保證返回全域性最優決策樹。這可以通過在綜合學習者中訓練多個樹來緩解,其中特徵和樣本隨機抽樣取代。
          有一些難以學習的概念,因為決策樹不能很容易地表達它們,例如XOR,奇偶校驗或複用器問題。
          如果某些類占主導地位,決策樹學習者會創造有偏見的樹木。因此,建議在擬合決策樹之前平衡資料集。

      例子:關於人們買電腦,試著用決策樹去分析,哪類人群符合什麼條件可以買電腦。


上面的圖片詳細記錄了14個人買電腦他們的年齡、收入、是否為學生、信用等級、以及結果是否買了電腦(Class Label)。

        根據ID3演算法原理用虛擬碼語言簡述是否買電腦與否的決策樹演算法核心:

        1:首先根據Class:buy_computer中的YES  OR  NO計算資訊熵。

        2:然後根據屬性age、income、student、credit_rating中的一個去算出各個屬性與Class:Buy_Computer的YES  OR  NO去算出期望

        3:然後根據各個屬性算出的期望值去與資訊熵相減,絕對值大的作為根節點,畫出第一層分叉樹。

        4:根據劃分出來的決策樹,再在每個分支中繼續重複上面的一二三的步驟。直到決策樹的純度達到自己的要求停止。詳細的演算法在上一篇部落格中講過了,這裡只是再重複一邊。

python程式碼實現上面的ID3演算法:

  1. # -*- coding: utf-8 -*-
  2. from sklearn.feature_extraction import DictVectorizer   
  3. import csv  
  4. from sklearn import tree  
  5. from sklearn import preprocessing  
  6. from sklearn.externals.six import StringIO  
  7. # Read in the csv file and put features into list of dict and list of class label
  8. allElectronicsData = open(r'F:\progrem\luna\DeepLearningBasicsMachineLearned\DecisionTree\AllElectronics.csv''rb')  
  9. reader = csv.reader(allElectronicsData)  
  10. headers = reader.next()  
  11. print(headers)  
  12. featureList = []  
  13. labelList = []  
  14. for row in reader:  
  15.     labelList.append(row[len(row)-1])  
  16.     rowDict = {}  
  17.     for i in range(1, len(row)-1):  
  18.         rowDict[headers[i]] = row[i]  
  19.     featureList.append(rowDict)  
  20. print(featureList)  
  21. # Vetorize features
  22. vec = DictVectorizer()  
  23. dummyX = vec.fit_transform(featureList) .toarray()  
  24. print("dummyX: " + str(dummyX))  
  25. print(vec.get_feature_names())  
  26. print("labelList: " + str(labelList))  
  27. # vectorize class labels
  28. lb = preprocessing.LabelBinarizer()  
  29. dummyY = lb.fit_transform(labelList)  
  30. print("dummyY: " + str(dummyY))  
  31. # Using decision tree for classification
  32. # clf = tree.DecisionTreeClassifier()
  33. clf = tree.DecisionTreeClassifier(criterion='entropy')  
  34. clf = clf.fit(dummyX, dummyY)  
  35. print("clf: " + str(clf))  
  36. # Visualize model
  37. with open("allElectronicInformationGainOri.dot"'w') as f:  
  38.     f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)  
  39. #new data
  40. newRowX = [11,  0,  1,  0,  1,  0,  1,  1,  0]  
  41. print("newRowX: " + str(newRowX))  
  42. predictedY = clf.predict(newRowX)  
  43. print("predictedY: " + str(predictedY))  

輸出結果: