python 之 決策樹分類算法


發現幫助新手入門機器學習的一篇好文,首先感謝博主!:用Python開始機器學習(2:決策樹分類算法)

 

J. Ross Quinlan在1975提出將信息熵的概念引入決策樹的構建,這就是鼎鼎大名的ID3算法。后續的C4.5, C5.0, CART等都是該方法的改進。

熵就是“無序,混亂”的程度。剛接觸這個概念可能會有些迷惑。想快速了解如何用信息熵增益划分屬性,可以參考這位兄弟的文章:http://blog.csdn.net/alvine008/article/details/37760639

數據集中信息熵的計算:

        H(x) = E[I(xi)] = E[ log(2,1/p(xi)) ] = -∑p(xi)log(2,p(xi)) (i=1,2,..n)

以博主例子為例,直接上代碼:

   1. 數據集: 

 more fat.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. 讀入數據集

#!/usr/bin/env python
# coding=utf-8

import numpy as np
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

def loadDataSet():
    data =[]
    label= []
    with open('./data/fat.txt') as file:
        for line in file:
            tokens = line.strip().split(' ')
            data.append([float(tk) for tk in tokens[:-1]])
            label.append(tokens[-1])
    x = np.array(data)
    label = np.array(label)
    y = np.zeros(label.shape)
    y[label=='fat']=1
    return x,y

3. 使用sklearn 中的現成庫進行分類,簡單而優雅

def decisionTreeClf():
    x,y = loadDataSet()
    
    # 拆分數據集和訓練集
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2)
    
    # 使用信息熵作為划分標准
    clf = tree.DecisionTreeClassifier(criterion='entropy')
    print(clf)
    clf.fit(x_train,y_train)
    
    # 將決策樹寫入文件
    with open("tree.dot","w") as f:
        f = tree.export_graphviz(clf,out_file=f)
    
    # 打印特征在分類起到的作用性
    print(clf.feature_importances_)

    # 打印測試結果
    answer = clf.predict(x_train)
    print(x_train)
    print(answer)
    print(y_train)
    print(np.mean(answer==y_train))

    # 准確率與召回率
    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']))

 

結果顯示:

>>> bayesDt.decisionTreeClf()
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            max_features=None, max_leaf_nodes=None, min_samples_leaf=1,
            min_samples_split=2, min_weight_fraction_leaf=0.0,
            random_state=None, splitter='best')
[ 0.2488562  0.7511438]
[[  1.9  70. ]
 [  1.5  60. ]
 [  1.5  50. ]
 [  1.7  60. ]
 [  1.9  80. ]
 [  1.6  40. ]
 [  1.8  60. ]
 [  1.8  90. ]]
[ 0.  1.  0.  0.  1.  0.  0.  1.]
[ 0.  1.  0.  0.  1.  0.  0.  1.]
1.0
             precision    recall  f1-score   support

       thin       0.83      1.00      0.91         5
        fat       1.00      0.80      0.89         5

avg / total       0.92      0.90      0.90        10

>>> 

 

這里有3點需要說明,這在以后的機器學習中都會用到。

1、拆分訓練數據與測試數據

這樣做是為了方便做交叉檢驗。交叉檢驗是為了充分測試分類器的穩定性。代碼中的0.2表示隨機取20%的數據作為測試用。其余80%用於訓練決策樹。

也就是說10個樣本中隨機取8個訓練。本文數據集小,多運行幾次,可以看到由於取的訓練數據隨機,每次構建的決策樹都不一樣。

2、特征的不同影響因子。

樣本的不同特征對分類的影響權重差異會很大。分類結束后看看每個樣本對分類的影響度也是很重要的。

在本例中,身高的權重為0.25,體重為0.75,可以看到重量的重要性遠遠高於身高。對於胖瘦的判定而言,這也是相當符合邏輯的。

3、准確率與召回率

這2個值是評判分類准確率的一個重要標准。比如代碼的最后將所有10個樣本輸入分類器進行測試的結果:

測試結果:array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.])
真實結果:array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])

分為thin的准確率為0.83。是因為分類器分出了6個thin,其中正確的有5個,因此分為thin的准確率為5/6=0.83。

分為thin的召回率為1.00。是因為數據集中共有5個thin,而分類器把他們都分對了(雖然把一個fat分成了thin!),召回率5/5=1。

 

分為fat的准確率為1.00,召回率為0.80。是因為數據集中共有5個fat,而分類器只分出了4個(把一個fat分成了thin!),召回率4/5=0.80。

很多時候,尤其是數據分類難度較大的情況,准確率與召回率往往是矛盾的。你可能需要根據你的需要找到最佳的一個平衡點。

比如本例中,你的目標是盡可能保證找出來的胖子是真胖子(准確率),還是保證盡可能找到更多的胖子(召回率)。

 


免責聲明!

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



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