決策樹分類
決策樹分類歸類於監督學習,能夠根據特征值一層一層的將數據集進行分類。它的有點在於計算復雜度不高,分類出的結果能夠很直觀的呈現,但是也會出現過度匹配的問題。使用ID3算法的決策樹分類第一步需要挑選出一個特征值,能夠將數據集最好的分類,之后遞歸構成分類樹。使用信息增益,來得到最佳的分類特制。
信息增益
根據某一特征划分數據集之后,信息發生的變化就叫做信息增益,計算出根據哪一個特征值划分之后數據集的信息增益值最大,那個該特制就是當前划分數據集的最好特征。可以用下面的公式計算得到信息增益值:
為同一類別的概率值。例如一個數據集有10條記錄 3條記錄類別屬於A類, 7條記錄類別屬於B類 根據公式就有 信息增益值為 -(0.3*log2(0.3) + 0.7*log2(0.7))。
定義一個函數的計算該值
def calcuShannon(dataset): dataset_row = len(dataset) #得到數據集的行數 labels = {} #聲明一個標簽字典 for featVec in dataset: lable = featVec[-1] #得到每一行最后的標簽歸類 if label not in labels.keys(): labels[lable] = 0 labels[lable] += 1 #得到每一個分類標簽的數量 shannon = 0.0 for key in labels: pro = float(labels[key])/dataset_row Shannon -= pro *log(pro, 2) return shannon #返回 信息增益值
舉一個實際運用的例子,有如下數據集 有四個特征 X1, X2, X3, X4
接下來計算一下以X2特征作為划分的之后信息增益值。
X2的取值有1,0,按1 切割矩陣后得到
計算 S1 = -((2/3) * log2 (2/3) + (1/3)*log2(1/3))
按0切割矩陣后得到
計算 S2 = -(1 * log21 )
總得信息增益值 S = (3/6)*S1 + (3/6)*S2
上面是以X2划分得到的信息增益值 ,循環計算得到 所有特征的該值,最后取出最大的一個,那么該特征就是最佳的分類特征,得到之后的子數據集矩陣,重復這一過程,當所有的特征都划分完畢,或者子集中的數據都屬於同一類,停止划分 比如。
# 某一列 指定的值 划分出 數據矩陣 def splitdataset(dataset, axis, value): redataset = [] for featVec in dataset: if featVec[axis] == value: reduecfeatVec = featVec[:, axis] reduecfeatVec.extend(featVec[axis, :]) redataset.append(reduecfeatVec) return redataset
#傳入數據 輸入最佳的划分特征 def getbestfeature(dataset): numfeature = len(dataset[0]) - 1 #得到特征數量 baseEntropy = caluShannonent(dataset) #計算數據集的基礎信息增益值 bestinfoGain = 0.0 bestfeature = -1 for i in range(numfeature): featlist = [] for data_row in dataset: featlist.extend(data_row[i]) #得到第i列的特征量 uniqueVals = set(featlist) #構造一個list,去除掉重復值 newEntropy = 0.0 for value in uniqueVals: #根據第i列以及取值划分數據集 subdataset = splitdataset(dataset, i, value) #得到子數據集 prob =len(subdataset)/float(len(dataset)) newEntropy += prob *calcuShannon(subdataset) #得到第i的信息增益值 infoGain = baseEntropy - newEntropy if infoGain > bestinfoGain : bestinfoGain = infoGain bestfeature = i return bestfeature #返回最佳划分特征 列號
遞歸生成分分類樹:
#所有特征都划分完成,最后的標簽中若並不是所有都是屬於同一類,調用該函數返回最多哪一類 def majorityCnt(classlist): classcount = {} for vote in classlist: if vote in classlist: classcount[vote] = 0 classcount[vote] += 1 sortedclasscount = sorted(classcount.iteritems(), key = operator.itemgetter(1), reverse= True) return sortedclasscount[0][0] def createTree(dataset, lables): 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 = getbestfeature(dataset)#返回最佳分類特征索引 bestfeatlabel = lables[bestfeat] #返回特征值 del(lables[bestfeat])#刪除該最佳分類特征 classifyTree = {bestfeatlabel: {}} bestfeatColValue = [example[bestfeat] for example in dataset] uniqueValue = set(bestfeatColValue) for value in uniqueValue: sublabels = lables[:] classifyTree = createTree(splitdataset(dataset, bestfeat, value), sublabels)#遞歸調用生成分類樹 return classifyTree