Udacity機器學習入門筆記——決策樹

監督學習算法第三種——決策樹decision trees

    決策樹可以通過核技巧把簡單的線性決策面轉換爲非線性決策面

    百度百科:決策樹是一個預測模型;他代表的是對象屬性與對象值之間的一種映射關係。樹中每個節點表示某個對象,而每個分叉路徑則代表的某個可能的屬性值,而每個葉結點則對應從根節點到該葉節點所經歷的路徑所表示的對象的值

    通過座標數據進行多次分割,找出分界線,繪製決策樹。在機器學習中,決策樹學習算法就是根據數據,使用計算機算法自動找出決策邊界。

-----------

決策樹的python代碼(sklearn)

鏈接:http://scikit-learn.org/stable/modules/tree.html
>>> from sklearn import tree
>>> X = [[0, 0], [1, 1]]
>>> Y = [0, 1]
>>> clf = tree.DecisionTreeClassifier()
>>> clf = clf.fit(X, Y)
代碼練習:class_vis.py與prep_terrain_data.py代碼與樸素貝葉斯代碼相同

studentMain.py

#!/usr/bin/python

""" lecture and example code for decision tree unit """

import sys
from class_vis import prettyPicture, output_image
from prep_terrain_data import makeTerrainData

import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
from classifyDT import classify

features_train, labels_train, features_test, labels_test = makeTerrainData()

### the classify() function in classifyDT is where the magic
### happens--fill in this function in the file 'classifyDT.py'!
clf = classify(features_train, labels_train)


#### grader code, do not modify below this line

prettyPicture(clf, features_test, labels_test)
output_image("test.png", "png", open("test.png", "rb").read())
classifyDT.py
def classify(features_train, labels_train):
	### your code goes here--should return a trained decision tree classifer
	from sklearn import tree
	clf = tree.DecisionTreeClassifier()
	clf = clf.fit(features_train,labels_train)
	return clf

狹長區域爲過擬合


class_vis.py與prep_terrain_data代碼不變

決策樹準確性代碼:0.908

import sys
from class_vis import prettyPicture
from prep_terrain_data import makeTerrainData

import numpy as np
import pylab as pl

features_train, labels_train, features_test, labels_test = makeTerrainData()

#################################################################################

########################## DECISION TREE #################################


#### your code goes here
from sklearn import tree
clf=tree.DecisionTreeClassifier()
clf = clf.fit(features_train,labels_train)

pre = clf.predict(features_test)

from sklearn.metrics import accuracy_score
acc = accuracy_score(labels_test,pre)
### be sure to compute the accuracy on the test set
    
def submitAccuracies():
  return {"acc":round(acc,3)}

決策樹參數

http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html

min_samples_split可分割的樣本數量下限,默認值爲2

對於決策樹最下層的每一個節點,是否還要繼續分割,min_samples_split決定了能夠繼續進行分割的最少分割樣本

     min_samples_split=50時,準確率91.2%,效果圖:                   min_samples_split=2時,準確率90.8%,效果圖:          

熵(entropy)和雜質

熵作用:主要控制決策樹在何處分割數據

熵定義:它是一系列樣本中的不純度的測量值(measure of impurity in a bunch of examples)

建立決策樹的過程就是找到變量劃分點從而產生儘可能的單一的子集,實際上決策樹做決策的過程,就是對這個過程的遞歸重複

例子:當某個路段有限速的時候,不論坡度如何,這裏(YES)都會是紅叉,箭頭所指爲單一子集


熵公式

Pi是第i類中的樣本佔總樣本數的比例

熵與數據單一性呈負相關關係(0~1)

所有樣本屬於同一類,熵爲0;樣本均勻分佈在所有類中,熵爲1.0

子:四個數據點,每個數據點有三個特徵:坡度、顛簸程度、是否超過限速,以及車的行駛速度

計算其熵值爲1.0

信息增益:父節點的熵-子節點的熵的加權平均(分割父節點後生成的子節點)


    決策樹算法會最大程度地提高信息增益,通過這種方法選擇進行劃分的特徵,如果特徵可以取多個不同值,該方法幫助它找出在何處進行劃分,它會嘗試最大程度提高信息增益。(爲了得到數據單一性最佳的劃分分支)

    用信息增益確定對哪個變量進行劃分,首先利用信息增益對坡度進行計算

    父節點包含四個樣本,按照坡度劃分得出左ssf,右f(熵爲0,樣本只有一類)


然後計算左熵:


然後根據信息增益公式計算子節點熵的加權平均:entropy=3/4 * 0.9184 + 1/4 * 0 = 0.6888

然後得出基於坡度進行數據劃分時所得到的信息增益=父節點熵1.0-子節點熵0.6888=0.3112

基於顛簸程度進行數據劃分所得到的信息增益:

    右上上圖信息可知,按顛簸程度劃分左右子節點各爲sf

    計算bumpy、smooth的熵

    entropy(bumpy)=-1/2 * ㏒₂½-1/2*㏒₂½ =1

     entropy(smooth)=-1/2 * ㏒₂½-1/2*㏒₂½ =1

    計算子節點熵的加權平均:entropy = 2/4 *1 +2/4 *1 = 1

得信息增益=1-1=0

基於是否限速進行數據劃分所得到的信息增益:1

偏差bias與方差variance

    高偏差機器學習算法實際上會忽略訓練數據,它幾乎沒有能力學習任何數據,這被稱爲偏差。所有對一個有偏差的汽車進行訓練,無論訓練通過何種方式進行,它的操作都不會有任何區別;

    另一個極端情況,汽車對數據高度敏感,它只能復現曾經見過的東西,那樣就會是一個方差極高的算法,但是對於之前未見過的情況,它的反應非常差,因爲沒有適當的偏差讓它泛化新的東西。

    通過調整參數讓偏差與方差平衡,使算法具有一定泛化能力,但仍然對訓練數據開放,能根據數據調整模型。

決策樹優缺點

    易於使用,易於理解

    容易過擬合,尤其對於具有包含大量特徵的數據時,複雜的決策樹可能會過擬合數據,通過仔細調整參數,避免過擬合(對於節點上只有單個數據點的決策樹,幾乎肯定是過擬合)



dt_author_id

#!/usr/bin/python

""" 
    This is the code to accompany the Lesson 3 (decision tree) mini-project.

    Use a Decision Tree to identify emails from the Enron corpus by author:    
    Sara has label 0
    Chris has label 1
"""
    
import sys
from time import time
sys.path.append("../tools/")
from email_preprocess import preprocess

### features_train and features_test are the features for the training
### and testing datasets, respectively
### labels_train and labels_test are the corresponding item labels
features_train, features_test, labels_train, labels_test = preprocess()

#########################################################
### your code goes here ###
from sklearn import tree
clf = tree.DecisionTreeClassifier(min_samples_split=40)
clf = clf.fit(features_train,labels_train)
acc = clf.score(features_test,labels_test)
print acc
print len(features_train[0])
#########################################################

    準確率0.9789

    從你的數據中找出特徵的數量,數據是以 numpy 數組的形式排列的,其中數組的行數代表數據點的數量,列數代表特徵的數量;爲了碼提取這個數值,可以寫一行這樣的代碼len(features_train[0]):3785

    加入 tools/email_preprocess.py,會看到這樣的代碼:selector =SelectPercentile(f_classif, percentile=1),將 percentile 從 10 改爲 1。

    l 現在的特徵數量是多少呢?379

    l 你認爲 SelectPercentile 起到什麼作用?其他所有的都不變的情況下,賦予 percentile 的值較大是否得到一棵更加複雜的或者簡化的決策樹?選擇排名排在前n%的變量,賦予 percentile 的值較大會得到一棵更加複雜的樹

    I 注意訓練時間的不同取決於特徵的數量。

    l 當 percentile 等於 1 時,準確度是多少?0.967

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章