ID 3決定ツリーのアルゴリズム原理とpython実現
14728 ワード
1.引用
意思決定ツリーは本質的に訓練データセットの訓練から分類ルールのセットであり、訓練データに完全に基づいて、得られたルールがフィッティングされやすく、これも意思決定ツリーの欠点であるが、意思決定ツリーの剪定によって、意思決定ツリーの汎化能力を高めることができる.これにより、決定ツリーの作成は、特徴選択、決定ツリーの生成、および決定ツリーの剪断の3つの部分を含むことができる.決定ツリーの応用には、分類、回帰、およびフィーチャー選択が含まれます.決定ツリーの最も古典的なアルゴリズムはID 3、C 4を含む.5及びCARTアルゴリズム、ID 3及びC 4.5アルゴリズムは似ている、C 4.5特徴選択時に選択される情報基準は情報利得比であり、ID 3は情報利得である.情報利得は、より多くの可能な値を有する特徴を選択することに偏っている(例えば、ある特徴が5つの可能な値を有し、その情報利得は2つの特徴値を有する情報利得よりも大きい).
2.主な内容情報論に基づく特徴選択(python情報利得の計算を実現) 決定ツリーの生成 ID 3アルゴリズムのpython実装.
3.情報論に基づく特徴選択
注意:エントロピーはランダム変数の不確実性を表し、エントロピー値が大きいほどランダム変数に含まれる情報が少なくなり、変数の不確実性が大きくなります.1)シャノンが1つのデータを定義する情報は、次式(ここでは2をベースとした対数)で計算することができる.
l(xi)=−log2p(xi)
2)エントロピーは1つのデータセット情報の期待を表し、式を押して計算することができる:(この式は理解できないが、想像することができて、変数の期待する式を求めて、p(xi)は変数xiと情報l(xi)の確率で、確率は変数(情報)を乗じて変数(情報)の期待である)
H=−∑ni=1p(xi)log2p(xi)
3)特徴AのデータセットDに対する情報利得は:
g(D,A)=H(D)−H(D|A)=−∑Kk=1|Ck||D|log2|Ck||D|−∑ni=1|Di||D|∑Kk=1|Dik||Di|log2|Dik||Di|
上式では、訓練データセットをDとし、そのサンプル容量を|D|とし、すなわちサンプル個数とし、KクラスCk,k=1,2,…,K,|Ck|はCkのサンプル個数であり,特徴Aの取値に基づいてDをn個のサブセットD 1,D 2,...,Dn,|Di|はDiのサンプル数,Dik=Di⋂Ck,|Dik|はDikのサンプル数である.次の表と図に示します.
feature1(A)
feature1
feature3
labels
a1
b1
c1
y
a1
b2
c2
n
a1
b1
c2
n
a1
b1
c2
n
a2
b1
c1
y
a2
b2
c2
y
a2
b1
c1
n
4)python実装
4.決定ツリー生成
決定ツリーには、次のフローチャートが表示されます.
5.ID 3アルゴリズムpython実装コード
実行結果:
参考文献:統計学習方法、李航machine learning in action中国語版
意思決定ツリーは本質的に訓練データセットの訓練から分類ルールのセットであり、訓練データに完全に基づいて、得られたルールがフィッティングされやすく、これも意思決定ツリーの欠点であるが、意思決定ツリーの剪定によって、意思決定ツリーの汎化能力を高めることができる.これにより、決定ツリーの作成は、特徴選択、決定ツリーの生成、および決定ツリーの剪断の3つの部分を含むことができる.決定ツリーの応用には、分類、回帰、およびフィーチャー選択が含まれます.決定ツリーの最も古典的なアルゴリズムはID 3、C 4を含む.5及びCARTアルゴリズム、ID 3及びC 4.5アルゴリズムは似ている、C 4.5特徴選択時に選択される情報基準は情報利得比であり、ID 3は情報利得である.情報利得は、より多くの可能な値を有する特徴を選択することに偏っている(例えば、ある特徴が5つの可能な値を有し、その情報利得は2つの特徴値を有する情報利得よりも大きい).
2.主な内容
3.情報論に基づく特徴選択
注意:エントロピーはランダム変数の不確実性を表し、エントロピー値が大きいほどランダム変数に含まれる情報が少なくなり、変数の不確実性が大きくなります.1)シャノンが1つのデータを定義する情報は、次式(ここでは2をベースとした対数)で計算することができる.
l(xi)=−log2p(xi)
2)エントロピーは1つのデータセット情報の期待を表し、式を押して計算することができる:(この式は理解できないが、想像することができて、変数の期待する式を求めて、p(xi)は変数xiと情報l(xi)の確率で、確率は変数(情報)を乗じて変数(情報)の期待である)
H=−∑ni=1p(xi)log2p(xi)
3)特徴AのデータセットDに対する情報利得は:
g(D,A)=H(D)−H(D|A)=−∑Kk=1|Ck||D|log2|Ck||D|−∑ni=1|Di||D|∑Kk=1|Dik||Di|log2|Dik||Di|
上式では、訓練データセットをDとし、そのサンプル容量を|D|とし、すなわちサンプル個数とし、KクラスCk,k=1,2,…,K,|Ck|はCkのサンプル個数であり,特徴Aの取値に基づいてDをn個のサブセットD 1,D 2,...,Dn,|Di|はDiのサンプル数,Dik=Di⋂Ck,|Dik|はDikのサンプル数である.次の表と図に示します.
feature1(A)
feature1
feature3
labels
a1
b1
c1
y
a1
b2
c2
n
a1
b1
c2
n
a1
b1
c2
n
a2
b1
c1
y
a2
b2
c2
y
a2
b1
c1
n
4)python実装
def calcShannonEnt(dataset):#
numSamples = len(dataset)
labelCounts = {}
for allFeatureVector in dataset:
currentLabel = allFeatureVector[-1]
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
entropy = 0.0
for key in labelCounts:
property = float(labelCounts[key])/numSamples
entropy -= property * log(property,2)
return entropy
def BestFeatToGetSubdataset(dataset):
# :
numFeature = len(dataset[0]) - 1
baseEntropy = calcShannonEnt(dataset)
bestInfoGain = 0.0; bestFeature = -1
for i in range(numFeature):#i
# i
feat_i_values = [example[i] for example in dataset]
uniqueValues = set(feat_i_values)
feat_i_entropy = 0.0
for value in uniqueValues:
subDataset = getSubDataset(dataset,i,value)
# pi,
prob_i = len(subDataset)/float(len(dataset))
feat_i_entropy += prob_i * calcShannonEnt(subDataset)
infoGain_i = baseEntropy - feat_i_entropy
if (infoGain_i > bestInfoGain):
bestInfoGain = infoGain_i
bestFeature = i
return bestFeature
4.決定ツリー生成
決定ツリーには、次のフローチャートが表示されます.
5.ID 3アルゴリズムpython実装コード
# -*- coding: utf-8 -*-
from math import log
import operator
import pickle
''' : 、 ( , ) : 、 ( ) :float ( ) '''
def calcShannonEnt(dataset):
numSamples = len(dataset)
labelCounts = {}
for allFeatureVector in dataset:
currentLabel = allFeatureVector[-1]
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
entropy = 0.0
for key in labelCounts:
property = float(labelCounts[key])/numSamples
entropy -= property * log(property,2)
return entropy
''' : : : 、 '''
def creatDataSet():
dataset = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,0,'no']]
labels = ['no surfacing','flippers']
return dataset,labels
''' : 、 、 ( ,( 、0,1 )) : ( ) : '''
def getSubDataset(dataset,colIndex,value):
subDataset = [] #
for rowVector in dataset:
if rowVector[colIndex] == value:
# colIndex
subRowVector = rowVector[:colIndex]
subRowVector.extend(rowVector[colIndex+1:])
#
subDataset.append(subRowVector)
return subDataset
''' : : , ( ) : '''
def BestFeatToGetSubdataset(dataset):
# :
numFeature = len(dataset[0]) - 1
baseEntropy = calcShannonEnt(dataset)
bestInfoGain = 0.0; bestFeature = -1
for i in range(numFeature):#i
# i
feat_i_values = [example[i] for example in dataset]
uniqueValues = set(feat_i_values)
feat_i_entropy = 0.0
for value in uniqueValues:
subDataset = getSubDataset(dataset,i,value)
# pi
prob_i = len(subDataset)/float(len(dataset))
feat_i_entropy += prob_i * calcShannonEnt(subDataset)
infoGain_i = baseEntropy - feat_i_entropy
if (infoGain_i > bestInfoGain):
bestInfoGain = infoGain_i
bestFeature = i
return bestFeature
''' : : : '''
def mostClass(ClassList):
classCount = {}
for class_i in ClassList:
if class_i not in classCount.keys():
classCount[class_i] = 0
classCount[class_i] += 1
sortedClassCount = sorted(classCount.iteritems(),
key=operator.itemgetter(1),reverse = True)
return sortedClassCount[0][0]
''' : , : ( ) : ( ) '''
def creatTree(dataset,labels):
classList = [example[-1] for example in dataset]
# dataset , ,
if classList.count(classList[0]) == len(classList):
return classList[0]
# , ,
if len(dataset[0]) == 1:
return mostClass(classList)
#
bestFeat = BestFeatToGetSubdataset(dataset)
#
bestFeatLabel = labels[bestFeat]
#
myTree = {bestFeatLabel:{}}
del (labels[bestFeat])
#
bestFeatValues = [example[bestFeat] for example in dataset]
uniqueBestFeatValues = set(bestFeatValues)
for value in uniqueBestFeatValues:
# value
subDataset = getSubDataset(dataset,bestFeat,value)
subLabels = labels[:]
#
myTree[bestFeatLabel][value] = creatTree(subDataset,subLabels)
return myTree
''' : : : '''
def classify(inputTree,featlabels,testFeatValue):
firstStr = inputTree.keys()[0]
secondDict = inputTree[firstStr]
featIndex = featlabels.index(firstStr)
for firstStr_value in secondDict.keys():
if testFeatValue[featIndex] == firstStr_value:
if type(secondDict[firstStr_value]).__name__ == 'dict':
classLabel = classify(secondDict[firstStr_value],featlabels,testFeatValue)
else: classLabel = secondDict[firstStr_value]
return classLabel
''' : , : : '''
def storeTree(trainTree,filename):
fw = open(filename,'w')
pickle.dump(trainTree,fw)
fw.close()
def grabTree(filename):
fr = open(filename)
return pickle.load(fr)
if __name__ == '__main__':
dataset,labels = creatDataSet()
storelabels = labels[:]# label
trainTree = creatTree(dataset,labels)
classlabel = classify(trainTree,storelabels,[0,1])
print classlabel
実行結果:
In [1]:runfile('E:/python/ml/dtrees/trees.py', wdir='E:/python/ml/dtrees')
no
In [2]:
参考文献:統計学習方法、李航machine learning in action中国語版