決策樹算法(三)——計算香農熵


寫在前面的話

如果您有任何地方看不懂的,那一定是我寫的不好,請您告訴我,我會爭取寫的更加簡單易懂!

如果您有任何地方看着不爽,請您盡情的噴,使勁的噴,不要命的噴,您的槽點就是幫助我要進步的地方!

計算給定數據的信息熵

在決策樹算法中最重要的目的我們已經在前幾章說過了,就是根據信息論的方法找到最合適的特征來划分數據集。在這里,我們首先要計算所有類別的所有可能值的香農熵,根據香農熵來我們按照取最大信息增益(information gain)的方法划分我們的數據集。


我們的數據集如下表所示:
這里寫圖片描述

根據這張表,我們使用python來構建我們的數據集。

#!/usr/bin/env python # coding=utf-8 # author: chicho # running: python trees.py # filename : trees.py def createDataSet(): dataSet = [[1,1,'yes'], [1,1,'yes'], [1,0,'no'], [0,1,'no'], [0,1,'no']] # 我們定義了一個list來表示我們的數據集,這里的數據對應的是上表中的數據 labels = ['no surfacing','flippers'] return dataSet, labels

其中第一列的1表示的是不需要浮出水面就可以生存的,0則表示相反。 第二列同樣是1表示有腳蹼,0表示的是沒有。

在構建完數據集之后我們需要計算數據集的香農熵。
根據香農熵的定義可以知道:

這里寫圖片描述

根據這個公式我們來編寫相應的代碼。(注意:我們是計算每個類別的香農熵,也就是魚類還是非魚類的香農熵。在這我們的數據集當中我們用’yes’表示是魚類,用‘no’表示非魚類)

# 代碼功能:計算香農熵 from math import log #我們要用到對數函數,所以我們需要引入math模塊中定義好的log函數(對數函數) def calcShannonEnt(dataSet):#傳入數據集 # 在這里dataSet是一個鏈表形式的的數據集 countDataSet = len(dataSet) # 我們計算出這個數據集中的數據個數,在這里我們的值是5個數據集 labelCounts={} # 構建字典,用鍵值對的關系我們表示出 我們數據集中的類別還有對應的關系 for featVec in dataSet: 通過for循環,我們每次取出一個數據集,如featVec=[1,1,'yes'] currentLabel=featVec[-1] # 取出最后一列 也就是類別的那一類,比如說‘yes’或者是‘no’ if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 print labelCounts # 最后得到的結果是 {'yes': 2, 'no': 3} shannonEnt = 0.0 # 計算香農熵, 根據公式 for key in labelCounts: prob = float(labelCounts[key])/countDataSet shannonEnt -= prob * log(prob,2) return shannonEnt

在python中我們使用 a=[]來定義一格list,我們使用a={}來定義一個字典。
例如:
website = {1:”google”,”second”:”baidu”,3:”facebook”,”twitter”:4}

>>>#用d.keys()的方法得到dict的所有鍵,結果是list >>> website.keys() [1, 'second', 3, 'twitter']

 

注意是d.keys()

>>>#用d.values()的方法得到dict的所有值,如果里面沒有嵌套別的dict,結果是list >>> website.values() ['google', 'baidu', 'facebook', 4] >>>#用items()的方法得到了一組一組的鍵值對, >>>#結果是list,只不過list里面的元素是元組 >>> website.items() [(1, 'google'), ('second', 'baidu'), (3, 'facebook'), ('twitter', 4)]

接下來我們來測試一下,通過 reload來測試

>>> import trees >>> reload(trees) <module 'trees' from 'trees.pyc'> >>> myDat,labels = trees.createDataSet() >>> myDat [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] >>> labels ['no surfacing', 'flippers'] >>> trees.calcShannonEnt(myDat) {'yes': 2, 'no': 3} 0.9709505944546686 >>> 

這里寫圖片描述

我們貼出實驗的完整代碼:

#!/usr/bin/env python # coding=utf-8 # author: chicho # running: python trees.py # filename : trees.py from math import log def createDataSet(): dataSet = [[1,1,'yes'], [1,1,'yes'], [1,0,'no'], [0,1,'no'], [0,1,'no']] labels = ['no surfacing','flippers'] return dataSet, labels def calcShannonEnt(dataSet): countDataSet = len(dataSet) labelCounts={} for featVec in dataSet: currentLabel=featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 print labelCounts shannonEnt = 0.0 for key in labelCounts: prob = float(labelCounts[key])/countDataSet shannonEnt -= prob * log(prob,2) return shannonEnt 

我們再把計算的過程總結一下,方便大家理解:

1.計算數據集中實例的總是,也就是樣本的總數。我們把這個值保存成一格單獨的變量以便之后方便使用,提高代碼的效率
2.創建字典,用於保存類別信息。在整個數據集當中有多少個類別,每個類別的個數是多少
3. 在我們創建的數據字典中,它的鍵是我們數據集中最后一列的值。如果當前鍵不存在則把這個鍵加入到字典當中,依次統計出現類別的次數
4. 最后使用所有類標簽對應的次數來計算它們的概論
5.計算香農熵


香農熵越高,則說明混合的數據越多,我們可以在數據集當中添加更多的分類,來觀察一下熵是怎么變化的。

>>> myDat[0][-1]='maybe' >>> myDat [[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] >>> trees.calcShannonEnt(myDat) {'maybe': 1, 'yes': 1, 'no': 3} 1.3709505944546687 >>> 

對比一下可以發現熵增加了:
這里寫圖片描述

這里寫圖片描述

得到熵之后我們就可以按照獲取最大信息增益的方法划分數據集。


免責聲明!

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



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