決策樹演算法目前最流行的有id3, c4.5, cart三種,其中c4.5是由id3改進而來,用資訊增益比代替id3中的資訊增益,id3演算法不能直接處理連續型資料,事先要把資料轉換成離散型才可以操作,c4.5演算法可以處理非離散型資料,而且可以處理不完整資料。cart演算法使用基尼指數用於特徵選擇,並在樹構造過程中進行剪枝。在構造決策樹的時候,那些掛著幾個元素的節點,不考慮最好,不然容易導致overfitting。
決策樹(id3)基本原理可以概括為:通過計算資訊增益劃分屬性集,選擇增益最大的屬性作為決策樹當前節點,依次往下,構建整個決策樹。
假如隨機變數x = ,每乙個變數取到的概率是p=,熵的計算通過下面公式:
熵計算完成後,通過將各個屬性劃分出來,計算各屬性特徵的資訊增益來確定決策樹的節點。資訊增益計算公式如下:
其中s為全部樣本集合,a為屬性,value(a)是屬性a的值域,v是屬性a的乙個取值,sv是s中屬性a值為v的樣本集合,|sv|是樣本數量。
以下為id3演算法的python實現,構造決策樹並測試。
#!/bin/python
#coding=utf-8
from math import log
import operator
def creatdataset():
"""構造資料集
"""dataset = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no su***cing', 'flippers']
return dataset, labels
def clacshannonent(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)
return shannonent
def splitdataset(dataset, axis, value):
"""按照給定特徵劃分資料集
dataset是資料集,axis是資料集特徵中的某乙個(待劃分出去),value是待劃分的那個特徵的值,
retdataset是劃分之後去掉axis=value特徵之後的資料集
"""retdataset =
for featvec in dataset:
if featvec[axis] == value:
reducedfeatvec = featvec[: axis]
reducedfeatvec.extend(featvec[axis + 1 : ])
return retdataset
def choosebestfeaturetosplit(dataset):
"""選擇最好的資料集劃分方式
"""numfeatures = len(dataset[0]) - 1
#原資料集的熵
baseentropy = clacshannonent(dataset)
#print baseentropy
bestinfogain = 0.0
bestfeature = -1
for i in range(numfeatures):
featlist = [example[i] for example in dataset]
uniquevals = set(featlist)
newentropy = 0.0
for value in uniquevals:
subdataset = splitdataset(dataset, i, value)
prob = len(subdataset) / float(len(dataset))
newentropy += prob * clacshannonent(subdataset)
infogain = baseentropy - newentropy
#print infogain
#print i
if (infogain > bestinfogain):
bestinfogain = infogain
bestfeature = i
#print i
return bestfeature
def majoritycnt(classlist):
classcount = {}
for vote in classlist:
if vote not in classcount.keys():
classcount[vote] = 0
classcount[vote] += 1
sortedclasscount = sorted(classcount.iteritems(), key=operator.itemgetter(1), reverse=true)
return sortedclasscount
def creattree(dataset, labels):
"""構造決策樹
"""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 = }
#得到列表包含的所有屬性值
del(labels[bestfeat])
featvalues = [example[bestfeat] for example in dataset]
uniquevals = set(featvalues)
for value in uniquevals:
sublables = labels[:]
mytree[bestfeatlabel][value] = creattree(splitdataset(dataset, bestfeat, value), sublables)
return mytree
def classify(inputtree, featlabels, testvec):
"""分類測試函式,inputtree為構造的決策樹,featlabels為測試資料的label,testvec為測試資料,結果返回分類結果標籤
"""firststr = inputtree.keys()[0]
seconddict = inputtree[firststr]
featindex = featlabels.index(firststr)
for key in seconddict.keys():
if testvec[featindex] == key:
if type(seconddict[key]).__name__ == 'dict':
classlabel = classify(seconddict[key], featlabels, testvec)
else:
classlabel = seconddict[key]
return classlabel
機器學習實戰之決策樹
1.熵 entropy h s 用來測量乙個資料集s的不確定程度。h s x x p x log2 p x s 待計算熵的資料集,在id3演算法的每次迭代中會改變 x s中類別的集合 p x 屬於類別x的元素站集合s中總元素的比例 h s 0 集合s 被完全分到乙個類中。在id3中,對每乙個屬性熵,...
機器學習實戰之決策樹
在 機器學習實戰 決策樹這一章的時候,有些地方的 有點看不太懂,看了幾篇部落格,還是未解。最後仔細看書,發現自己不懂資料集的組織方式。希望大家看的時候也注意一下。在決策樹函式呼叫的資料要滿足如下要求 1 資料必須是由列表元素組成的列表,所有的列表元素都要具有相同的資料長度 2 資料 也就是資料集中的...
機器學習實戰之決策樹
1 演算法概述 1.1 結構分析 決策樹是一種依託決策而建立起來的樹,其中,每乙個內部節點表示乙個屬性上的測試,每乙個分支代表乙個測試的結果輸出,每乙個葉子代表一種類別。如上圖所示就是乙個決策樹,首先分析所給資料集是否為同一類別,如果是,那就不用劃分了,如果不是,就尋找劃分資料集最好的特徵進行劃分 ...