決策樹 (一)
阿新 • • 發佈:2018-12-06
# -*- coding: utf-8 -*- """ 熵定義為資訊的期望值。 熵:表示隨機變數的不確定性。 條件熵:在一個條件下,隨機變數的不確定性。 資訊增益:熵 - 條件熵 在一個條件下,資訊不確定性減少的程度! 如果選擇一個特徵後,資訊增益最大(資訊不確定性減少的程度最大),那麼我們就選取這個特徵。 """ from math import log """ 函式說明:建立測試集 Parameter: 無 Returns: dataSet 資料集 Labels 分類屬性 """ def createDataSet(): dataSet = [[0, 0, 0, 0, 'no'], [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'], [0, 1, 1, 0, 'yes'], [0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'], [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'], [1, 0, 1, 2, 'yes'], [1, 0, 1, 2, 'yes'], [2, 0, 1, 2, 'yes'], [2, 0, 1, 1, 'yes'], [2, 1, 0, 1, 'yes'], [2, 1, 0, 2, 'yes'], [2, 0, 0, 0, 'no']] Labels = ['不放貸', '放貸'] return dataSet, Labels """ 函式說明:計算給定資料集的經驗熵(夏農熵) Parameters: dataSet 資料集 Returns: shannonEnt 經驗熵 """ def calcShannonEnt(dataSet): #返回資料集的行數 numEntirs = 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]) / numEntirs # shannonEnt -= prob * log(prob, 2) return shannonEnt """ 函式說明:按照給定特徵劃分資料集 Parameters: dataSet 待劃分的資料集 axis 劃分資料集的特徵 value 需要返回的特徵值 Returns: retDataSet 返回的資料集列表 """ def 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 retDataSet """ 函式說明:選擇最優特徵 Paramaters: dataSet Returns: beatFeature 資訊增益最優的特徵的索引值 """ def chooseBestFeatureToSplit(dataSet): #特徵數量 numFeatures = len(dataSet[0]) - 1 #計算資料集的夏農熵 baseEntropy = calcShannonEnt(dataSet) #資訊增益 bestInfoGain = 0.0 #最優特徵的索引值 bestFeature = -1 for i in range(numFeatures): #獲取dataSet的第i個所有特徵 #將dataSet中的資料先按行依次放入example中, #然後取得example中的example[i]元素,放入列表featList中 #相當於取所有行的第一個值 #之所以這樣取,是因為dataSet是個列表,而不是矩陣,矩陣取第一列有方法 featList = [ example[i] for example in dataSet] #建立集合set,元素不可重複 uniqueVals = set(featList) #經驗條件熵 newEntropy = 0.0 #計算資訊增益 for value in uniqueVals: #subDataSet是劃分後的子集 subDataSet = splitDataSet(dataSet, i, value) #計運算元集的概率 prob = len(subDataSet) / float(len(dataSet)) #計算經驗條件熵 newEntropy += prob * calcShannonEnt(subDataSet) #資訊增益 infoGain = baseEntropy - newEntropy #列印每個特徵的資訊增益 print("第%d個特徵的增益為:%.3f" % (i, infoGain)) if (infoGain > bestInfoGain): bestInfoGain = infoGain bestFeature = i return bestFeature if __name__ == '__main__': dataSet, features = createDataSet() print("最優特徵索引值:" + str(chooseBestFeatureToSplit(dataSet)))