標籤:ase 大小 line append 指標 cond str create images
決策樹---ID3演算法
決策樹:
以天氣資料庫的訓練資料為例。
Outlook |
Temperature |
Humidity |
Windy |
PlayGolf? |
sunny |
85 |
85 |
FALSE |
no |
sunny |
80 |
90 |
TRUE |
no |
overcast |
83 |
86 |
FALSE |
yes |
rainy |
70 |
96 |
FALSE |
yes |
rainy |
68 |
80 |
FALSE |
yes |
rainy |
65 |
70 |
TRUE |
no |
overcast |
64 |
65 |
TRUE |
yes |
sunny |
72 |
95 |
FALSE |
no |
sunny |
69 |
70 |
FALSE |
yes |
rainy |
75 |
80 |
FALSE |
yes |
sunny |
75 |
70 |
TRUE |
yes |
overcast |
72 |
90 |
TRUE |
yes |
overcast |
81 |
75 |
FALSE |
yes |
rainy |
71 |
91 |
TRUE |
no |
這個例子是根據報告天氣條件的記錄來決定是否外出打高爾夫球。
作為分類器,決策樹是一棵有向無環樹。
由根節點、分葉節點、內部節點、分割屬性、分割判斷規則構成
產生階段:決策樹的構建和決策樹的修剪。
根據分割方法的不同:有基於資訊理論(Information Theory)的方法和基於最小GINI指數(lowest GINI index)的方法。對應前者的常見方法有ID3、C4.5,後者的有CART。
ID3 演算法
ID3的基本概念是:
1) 決策樹中的每一個非葉子節點對應著一個特徵屬性,樹枝代表這個屬性的值。一個分葉節點代表從樹根到分葉節點之間的路徑所對應的記錄所屬的類別屬性值。這就是決策樹的定義。
2) 在決策樹中,每一個非葉子節點都將與屬性中具有最大資訊量的特徵屬性相關聯。
3) 熵通常是用於測量一個非葉子節點的資訊量大小的名詞。
熵
熱力學中表徵物質狀態的參量之一,用符號S表示,其物理意義是體系混亂程度的度量。熱力學第二定律(second law of thermodynamics),熱力學基本定律之一,又稱“熵增定律”,表明在自然過程中,一個孤立系統的總混亂度(即“熵”)不會減小。
在資訊理論中,變數的不確定性越大,熵也就越大,把它搞清楚所需要的資訊量也就越大。資訊熵是資訊理論中用於度量資訊量的一個概念。一個系統越是有序,資訊熵就越低;反之,一個系統越是混亂,資訊熵就越高。所以,資訊熵也可以說是系統有序化程度的一個度量。
資訊增益的計算
定義1:若存在個相同機率的訊息,則每個訊息的機率是,一個訊息傳遞的資訊量為。若有16個事件,則,需要4個位元來代表一個訊息。
定義2:若給定機率分布,則由該分布傳遞的資訊量稱為的熵,即
例:若是,則是1;若是,則是0.92;若
是,則是0(注意機率分布越均勻,其資訊量越大)
定義3:若一個記錄的集合根據類別屬性的值被分為相互獨立的類,則識別的一個元素所屬哪個類別所需要的資訊量是,其中是的機率分布,即
仍以天氣資料庫的資料為例。我們統計了14天的氣象資料(指標包括outlook,temperature,humidity,windy),並已知這些天氣是否打球(play)。如果給出新一天的氣象指標資料,判斷一下會不會去打球。在沒有給定任何天氣資訊時,根據曆史資料,我們知道一天中打球的機率是9/14,不打的機率是5/14。此時的熵為:
定義4:若我們根據某一特徵屬性將分成集合,則確定中的一個元素類的資訊量可通過確定的加權平均值來得到,即的加權平均值為:
Outlook |
temperature |
humidity |
windy |
play |
|
yes |
no |
|
|
|
yes |
no |
yes |
no |
sunny |
2 |
3 |
False |
6 |
2 |
9 |
5 |
overcast |
4 |
0 |
True |
3 |
3 |
|
|
rainy |
3 |
2 |
|
|
|
|
|
針對屬性Outlook,我們來計算
定義5:將資訊增益定義為:
即增益的定義是兩個資訊量之間的差值,其中一個資訊量是需確定的一個元素的資訊量,另一個資訊量是在已得到的屬性的值後確定的一個元素的資訊量,即資訊增益與屬性相關。
針對屬性Outlook的增益值:
若用屬性windy替換outlook,可以得到,。即outlook比windy取得的資訊量大。
ID3演算法的Python實現
import math import operatordef calcShannonEnt(dataset): numEntries = len(dataset) labelCounts = {} for featVec in dataset: currentLabel = featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] +=1 shannonEnt = 0.0 for key in labelCounts: prob = float(labelCounts[key])/numEntries shannonEnt -= prob*math.log(prob, 2) return shannonEnt def CreateDataSet(): dataset = [[1, 1, ‘yes‘ ], [1, 1, ‘yes‘ ], [1, 0, ‘no‘], [0, 1, ‘no‘], [0, 1, ‘no‘]] labels = [‘no surfacing‘, ‘flippers‘] return dataset, labelsdef splitDataSet(dataSet, axis, value): retDataSet = [] for featVec in dataSet: if featVec[axis] == value: reducedFeatVec = featVec[:axis] reducedFeatVec.extend(featVec[axis+1:]) retDataSet.append(reducedFeatVec) return retDataSetdef chooseBestFeatureToSplit(dataSet): numberFeatures = len(dataSet[0])-1 baseEntropy = calcShannonEnt(dataSet) bestInfoGain = 0.0; bestFeature = -1; for i in range(numberFeatures): featList = [example[i] for example in dataSet] uniqueVals = set(featList) newEntropy =0.0 for value in uniqueVals: subDataSet = splitDataSet(dataSet, i, value) prob = len(subDataSet)/float(len(dataSet)) newEntropy += prob * calcShannonEnt(subDataSet) infoGain = baseEntropy - newEntropy if(infoGain > bestInfoGain): bestInfoGain = infoGain bestFeature = i return bestFeaturedef majorityCnt(classList): classCount ={} for vote in classList: if vote not in classCount.keys(): classCount[vote]=0 classCount[vote]=1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] def createTree(dataSet, labels): classList = [example[-1] for example in dataSet] if classList.count(classList[0])==len(classList): return classList[0] if len(dataSet[0])==1: return majorityCnt(classList) bestFeat = chooseBestFeatureToSplit(dataSet) bestFeatLabel = labels[bestFeat] myTree = {bestFeatLabel:{}} del(labels[bestFeat]) featValues = [example[bestFeat] for example in dataSet] uniqueVals = set(featValues) for value in uniqueVals: subLabels = labels[:] myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels) return myTree myDat,labels = CreateDataSet()createTree(myDat,labels)
運行結果如下:
決策樹---ID3演算法(介紹及Python實現)