決策樹(Decision Tree)是一種簡單但是廣泛使用的分類器。通過訓練數據構建決策樹,可以高效的對未知的數據進行分類。決策數有兩大優點:1)決策樹模型可以讀性好,具有描述性,有助於人工分析;2)效率高,決策樹只需要一次構建,反覆使用,每一次預測的最大計算次數不超過決策樹的深度。
訓練數據如下表:
根據訓練數據集的數據,構造決策樹
比如新發現一種動物,通過決策樹就可以判斷它是否是魚類
但是在本例中決策樹的劃分也不止上圖的一種,還有另一種
我們通過表能看出第二種分類也能正確分類
但是計算機最終只生成一種決策樹,那麼如何選擇呢?在這裏就要使用信息熵來決定使用哪種方案
下面代碼給出了選擇哪個特徵(不浮出水面是否可以生存、是否有腳蹼)能最好的劃分數據集
# coding:utf-8
from math import log
import operator
##創建訓練數據集
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):
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 * log(prob,2) #log base 2
return shannonEnt
##分割數據集 axis即爲在每一行中第axis個元素作爲特徵值劃分並選出值與value相等的那一行,但要除去第axis個元素
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis] #輸出的數據中要剔除該行第axis個元素
reducedFeatVec.extend(featVec[axis+1:])#輸出的數據中要剔除該行第axis個元素
retDataSet.append(reducedFeatVec)
return retDataSet
##選擇最好的數據集劃分方式
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1 #每一行的最後一個元素作爲該行的標籤
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0; bestFeature = -1
for i in range(numFeatures): #遍歷每一個特徵
featList = [example[i] for example in dataSet]#取出特徵值數組,即取出數據集每行的第i列組成一個數組
uniqueVals = set(featList) #使用set數據類型來去除重複項
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 bestFeature #返回能最好劃分數據集的特徵, 如dataSet = [[1, 1, 'yes'], [1, 1, 'yes'],[1, 0, 'no'], [0, 1, 'no'],[0, 1, 'no']] 一行中的第一個元素或第二個元素
dataSet, labels=createDataSet()
print chooseBestFeatureToSplit(dataSet)
計算出的結果爲 0,說明選擇不浮出水面是否可以生存該特徵