一.
1.1決策樹模型結構
分類決策樹模型一種描述對實例進行分類的樹形結構。決策樹由結點和有向邊組成。結點有兩種類型:內部結點和葉結點。內部結點表示一個特徵或屬性,葉結點表示一個類。
1.2決策樹遞歸思想
決策樹學習的算法通常是一個遞歸地選擇最優特徵,並根據該特徵對訓練數據進行分割,使得對各個子數據集有一個最好的分類的過程。這一過程對應着特徵空間的劃分,也對應着決策樹的構建。開始,構建根節點,將所有訓練數據都放在根結點。選擇一個最優特徵,按照這一特徵將訓練數據集分割成子集,使得各個子集有一個在當前條件下最好的分類。如果這些子集已經能夠被基本正確分類,那麼構建葉結點,並將這些子集分到所對應葉結點中去;如果還有子集不能夠被基本正確分類,那麼就對這些子集選擇新的最優特徵,繼續對其進行分割,構建相應的結點。如此遞歸地進行下去,直至所有訓練數據子集被基本正確分類,或者沒有合適的特徵爲止。最後每個子集都被分到葉結點上,即都有了明確的類。這就生成了一棵決策樹。
二.
2.2信息增益
特徵A對訓練數據集D的信息增益g(D, A),定義爲集合D的經驗熵H(D)與特徵A給定條件下D的經驗條件熵H(D|A)之差,即
一般地,熵H(Y)與條件熵H(Y|X)之差稱爲互信息。決定決策樹學習中的信息增益等價於訓練數據集中類與特徵的互信息。
而決策樹就是利用信息增益準則來選擇特徵
2.2信息增益率
信息增益值的大小是相對於訓練數據集而言的,並沒有絕對意義。在分類問題困難時,也就是說在訓練數據集的經驗熵大的時候,信息增益值會偏大。反之,信息增益值會偏小。使用信息增益比可以對這一問題進行校正。這是特徵選擇的另一準則。
信息增益比:特徵A對訓練數據集D的信息增益比定義爲其信息增益g(D, A)與訓練數據集D的經驗熵H(D)之比:
三.
3.1 ID3算法
ID3算法的核心是在決策樹各個結點上應用信息增益準則選擇特徵,遞歸地構建決策樹。具體方法是:從根節點(root node)開始,對結點計算所有可能的特徵的信息增益,選擇信息增益最大的特徵作爲結點的特徵,由該特徵的不同取值建立子結點;再對子結點遞歸地調用以上方法,構建決策樹;直到所有特徵的信息增益均很小或者沒有特徵可以選擇爲止。最後得到一個決策樹。ID3相當於用極大似然法進行概率模型的選擇
優點:
簡單
缺點:
1)ID3算法採用信息增益來選擇最優劃分特徵,然而人們發現,信息增益傾向與取值較多的特徵,對於這種具有明顯傾向性的屬性,往往容易導致結果誤差;
2)ID3算法沒有考慮連續值,對與連續值的特徵無法進行劃分;
3)ID3算法無法處理有缺失值的數據;
4)ID3算法沒有考慮過擬合的問題,而在決策樹中,過擬合是很容易發生的;
5)ID3算法採用貪心算法,每次劃分都是考慮局部最優化,而局部最優化並不是全局最優化,當然這一缺點也是決策樹的缺點,獲得最優決策樹本身就是一個NP難題,所以只能採用局部最優;
3.2 C4.5算法
C4.5算法的提出旨在解決ID3算法的缺點 ,是對ID3算法的改進。
1)採用信息增益比來替代信息增益作爲尋找最優劃分特徵,信息增益比的定義是信息增益和特徵熵的比值,對於特徵熵,特徵的取值越多,特徵熵就傾向於越大;
2)對於連續值的問題,將連續值離散化,在這裏只作二類劃分,即將連續值劃分到兩個區間,劃分點取兩個臨近值的均值,因此對於m個連續值總共有m-1各劃分點,對於每個劃分點,依次算它們的信息增益,選取信息增益最大的點作爲離散劃分點;
3)對於缺失值的問題,我們需要解決兩個問題,第一是在有缺失值的情況下如何選擇劃分的屬性,也就是如何得到一個合適的信息增益比;第二是選定了劃分屬性,對於在該屬性的缺失特徵的樣本該如何處理。
4)對於過擬合的問題,採用了後剪枝算法和交叉驗證對決策樹進行剪枝處理,這個在CART算法中一起介紹。
還存在的不足:
1)C4.5的剪枝算法不夠優秀;
2)C4.5和ID3一樣,都是生成的多叉樹,然而在計算機中二叉樹模型會比多叉樹的運算效率高,採用二叉樹也許效果會更好;
3)在計算信息熵時會涉及到大量的對數運算,如果是連續值還需要進行排序,尋找最優離散劃分點,這些都會增大模型的運算;
4)C4.5算法只能處理分類問題,不能處理迴歸問題,限制了其應用範圍。
四
4.1劃分數據集
def split_data_set(dataSet, axis, value):
"""
:param dataSet: 數據集
:param axis: 劃分數據集特徵的列號0,1,或者列名
:param value: 返回特徵的值
:return:
"""
re_data_set = []
for feat_vector in dataSet:
if feat_vector[axis] == value:
reduceFeatVec =feat_vector[:axis]
reduceFeatVec.extend(feat_vector[axis+1 :])
re_data_set .append(reduceFeatVec)
4.1選擇最好的數據集劃分方式
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1
# 計算整個數據集的原始香農熵
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0; bestFeature = -1
# 遍歷數據集中的所有特徵
for i in range(numFeatures):
# 將數據集中所有第i個特徵值或者所有可能存在的值寫入這個新list中
featList = [example[i] for example in dataSet]
# 使用set數據類型得到互不相同的元素值
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 bestFeature
4.3創建樹的代碼
def createTree(dataSet,labels):
'''
:param dataSet: 數據集
:param labels: 標籤列表
:return: 決策樹信息,字典類型
'''
# 創建列表包含數據集的所有類標籤
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