의사 결정 트리 --ID3

참고 URL : HTTPS : //www.cnblogs.com/further-further-further/p/9429257.html

ID3 알고리즘

최적의 의사 결정 트리

- - 코딩 : UTF-8 - -

"" "
목 8월에 생성 17시 9분 34초 2018이
의사 결정 트리 ID3 구현
@author : weixw
" ""
수학 가져 오기 로그에서
가져 오기 연산자

원시 데이터

DEF createDataSet ()
와 DataSet = [1, 1, 1,1, '예'],
[1, 1, 0,0, '예'],
[1, 0, 1,1, '아니오'],
[0, 1, 0,1, '예'],
[0, 1, 1,0, '예'],
[1, 1, 1, 1, '예'],
[1, 1, 0, 0 , '아니요'],
[1, 0, 1, 1, "아니오"],
[0, 1, 0, 1, "아니오"],
[0, 1, 1, 0, '아니오']
라벨 = 없음 [ '아니오 피싱', '오리발', '사람', '일']
데이터 세트 레이블을 반환

과반수 투표

열 결과의 수까지 동일한 값

DEF majorityCnt (classList)
classCounts = {}
classList의 값 :
만약 (값하지 classCounts.keys에서 ())
classCounts [값 = 0
classCounts [값] + = 1
sortedClassCount = 정렬 (classCounts.iteritems () 키 = operator.itemgetter (1) 역방향 = TRUE)
반환 sortedClassCount [0] [0]

데이터 파티션

와 DataSet : 원래 데이터 세트

축 : 지정된 열 인덱스 분할

값 : 지정된 열의 값

splitDataSet DEF (와 DataSet A, 축 값) :
retDataSet = []
와 DataSet A의 featDataVal 님
featDataVal [축] == 값 IF :
# 1 열의 소정 값 아래 두 줄을 제거가 재치
reducedFeatVal = featDataVal [: 축]
reducedFeatVal.extend (featDataVal [축 + 1.])
retDataSet.append (reducedFeatVal)
retDataSet를 반환

섀넌 엔트로피 계산

DEF calcShannonEnt (와 DataSet)
아이템의 총 수 # 데이터 세트
NumEntries를 = LEN (와 DataSet A)
# 태그 카운트 객체 초기화
labelCounts = {}
와 DataSet A의 featDataVal를 들어
# 데이터 취득마다 마지막 한 태그 값 설정
있는 currentLabel = featDataVal를 [- 1]
#이 태그는 태그 저장 오브젝트가 아닌 경우, 초기화 및 계산
IF) (안 labelCounts.keys에있는 currentLabel을 :
labelCounts [있는 currentLabel] = 0
labelCounts를 [있는 currentLabel] + = 1
# 엔트로피 초기화
shannonEnt = 0.0
# 순회 라벨 개체 확률의 결정은, 상기 엔트로피를 계산한다
) (labelCounts.keys 키를 들면 :
[KEY = labelCounts의 소품 / 플로트 (NumEntries를)
shannonEnt - * = 소품 로그 (프로 2)
복귀 shannonEnt

최고의 기능을 열 인덱스를 선택

DEF chooseBestFeatureToSplit (와 DataSet)
기능의 수를 카운트 # 1, 태그 특성 마지막 데이터 세트가 아닌 특징 량
. numFeatures = LEN (데이터 세트 [0]) - 1
# 초기 데이터 섀넌 엔트로피 계산
baseEntropy = calcShannonEnt (와 DataSet)
# 초기화 정보 게인 상기 최적 구획 열 인덱스
bestInfoGain = 0.0
bestFeatureIndex = -1
에 대한 I 범위 (numFeatures)에서 :
각 열에 # 데이터 취득
featList = [실시 예와 DataSet A의 실시 예 [I]
데이터 중복 각 열의 #
= 세트 uniqueVals (featList )
newEntropy = 0.0
uniqueVals의 값을 :
하위 데이터 = splitDataSet (와 DataSet A, I, 값)
# 조건부 확률 계산
PROB = LEN (하위 데이터)를 / 플로트 (LEN (와 DataSet A))
# 조건부 엔트로피 계산
newEntropy + = 확률값을 * calcShannonEnt (하위 데이터 )
# 컴퓨팅 정보 이득
infoGain = baseEntropy - newEntropy
경우 (infoGain> bestInfoGain)
bestInfoGain = infoGain
bestFeatureIndex = 제가
돌아 bestFeatureIndex

의사 결정 트리 만들기

createTree DEF (와 DataSet A, 라벨) :
#의 가져 오기 태그 속성 데이터 집합 마지막 열은 레이블 이름과 다른 라벨
classList = [예 [-1]와 DataSet A의 예를 들어]
# 트리 극단적 종료 조건
# 태그 값은 속성 모두 같은, 반품 레이블을 제 속성치
classList.count은 (classList [0]) == LEN (classList) 경우 :
classList [0] 돌려주는
# 만 기능이다 (a)
IF LEN (와 DataSet A [0]) == 1.
majorityCnt를 반환 ( classList)
# 최적 기능 열 인덱스 얻었다
bestFeatureIndex = chooseBestFeatureToSplit (셋 a)
# 인덱스에 대응하는 최적의 태그 이름 얻기
bestFeatureLabel = 라벨 [bestFeatureIndex]
# 루트 노드 생성
{{} bestFeatureLabel}으로 myTree = 중을
대부분 인덱스 탭에 대응하는 #을 제거 이름, 라벨 정확하게 탐색 레이블을
델 (라벨 [bestFeatureIndex])
# 최적 열을 구하는
bestFeature = [실시 예 [bestFeatureIndex]의 세트에서 예]
uniquesVals = 세트 (bestFeature)
: uniquesVals의 값
#子标签名称集合
subLabels = 라벨 [:]
#递归
으로 myTree [bestFeatureLabel] [VALUE = createTree (splitDataSet (데이터 세트 bestFeatureIndex, 값) subLabels)
창으로 myTree

분류 결과를 얻

inputTree : 의사 결정 트리 사전

featLabels : 태그 목록

testVec : 벡터 시험 예 : 경로의 간단한 예 [1,1] => 예 (값 트렁크 조화, 리프 노드로의 루트에서)

DEF (inputTree, featLabels, testVec를) 분류 :
# 루트 노드의 이름, 목록에 DICT 받기
firstSide = 목록 (inputTree.keys ())
# 이름 String 형 루트
firstStr을 firstSide = [0]
루트를 받기 #을 자식 노드에 해당하는
secondDict = inputTree [firstStr을]
# 얻을 라벨리스트 인덱스에 해당하는 루트 노드의 이름
featIndex = featLabels.index (firstStr을)
규모에 해당하는 인덱스 값에 인수 #
키 = testVec [featIndex]
#이 오기 트렁크 상기 타겟 벡터 후에
valueOfFeat = secondDict하는 열쇠
# 결정 리프 노드 또는 자식 노드이다 콜백 함수 분류의 하위 노드는, 분류 결과가 리프 노드 인
# 1의 경우 유형 (valueOfFeat) .__ 이름 __ == '딕셔너리' 당량 isinstance (valueOfFeat, 딕셔너리) IF :
isinstance (valueOfFeat, 딕셔너리) 경우 :
classLabel = 분류 (valueOfFeat, featLabels, testVec)는
다른 :
classLabel = valueOfFeat
classLabel를 반환

디스크에 저장된 의사 결정 트리 분류기는, 파일 이름은 일반적으로 TXT 형식으로 저장

데프 storeTree (inputTree, 파일 이름) :
수입 피클
FW = 개방 (파일 이름, 'WB +')
pickle.dump (inputTree, FW)
fw.close ()

로드 아웃 도자기 객체는 여기에 파일 이름은 위의 txt 파일의 기능입니다

데프 grabTree (파일 이름) :
수입 피클
FR = 개방 (파일 이름, 'RB')
반환 pickle.load (FR)

의사 결정 트리를 그리기

'' '
년 10 월 14, 2010에 작성

@author : 피터 해링턴
'' '
PLT 등의 수입 matplotlib.pyplot

decisionNode = 딕셔너리 (boxstyle = "톱니"FC = "0.8")
leafnode의 딕셔너리 = (boxstyle = "round4"FC = "0.8")
arrow_args = 딕셔너리 (arrowstyle = ""- ")

나무의 잎 노드를 가져옵니다

(으로 myTree의) getNumLeafs DEF :
numLeafs = 0
목록에 #의 딕셔너리
firstSides는 = 목록 (myTree.keys ())는
firstStr을 firstSides = [0]
으로 myTree의 secondDict은 = [firstStr을]
secondDict.keys ()에서의 키의 경우 :
# 잎 여부를 판정한다 노드 (유형에 의해 결정이, 자식 클래스, 유형 str을 존재하지 않는, 서브 클래스는 다음, DICT 존재하는)
경우 유형 (secondDict [
키]) == name__ .__ 'DICT'dictonaires 참조 경우에 # 테스트 노드는, 그들은 잎 노드 수있는 것은 아닙니다 IF
(secondDict [키]) numLeafs + = getNumLeafs
다른 :
. numLeafs + = 1
반환 numLeafs

나무의 층의 수를 가져옵니다

DEF getTreeDepth (으로 myTree)
MAXDEPTH = 0
# 딕셔너리转化리스트为
firstSides = 목록 (myTree.keys ())
firstStr을 firstSides = [0]
secondDict으로 myTree = [firstStr을]
secondDict.keys ()에서 키 :
만약 타입 (secondDict [
키]) .__ name__ == '딕셔너리'노드가 dictonaires 인 경우가 리프 노드되어 있지 않은 경우 # 시험 보러
thisDepth = 1 + getTreeDepth (secondDict)] 키
다른 :
thisDepth = 1
의 경우 thisDepth> MAXDEPTH : MAXDEPTH = thisDepth
반환 MAXDEPTH

DEF plotNode은 (nodeTxt는 centerPt는 parentPt, nodeType 값은)
createPlot.ax1.annotate는 (nodeTxt, XY = parentPt, xycoords =는 '분획 축'
xytext = centerPt, textcoords = '이 분획 축'
= HA, VA = "센터" "센터"BBOX = nodeType에, arrowprops = arrow_args)

DEF plotMidText (cntrPt, parentPt, txtString)
xMid = (parentPt [0] - cntrPt [0]) / 2.0 + cntrPt [0]
yMid = (parentPt [1] - cntrPt [1]) / 2.0 + cntrPt [1]
createPlot.ax1.text (xMid, yMid, txtString, VA = "중앙"하 = "센터"회전 = 30)

데프 plotTree (으로 myTree, parentPt, nodeTxt) : # 첫 번째 키에 분할 무슨 업적을 설명하는 경우
=의 getNumLeafs (으로 myTree) # numLeafs는이 나무의 x 폭을 결정
깊이 = getTreeDepth (으로 myTree)
firstSides = 목록 (myTree.keys ())
firstStr을 firstSides = [0] #이 있어야이 노드에 대한 텍스트 라벨
cntrPt = (plotTree.xOff + (1.0 + 플로트 (numLeafs)) / 2.0 / plotTree.totalW, plotTree.yOff)
plotMidText (cntrPt, parentPt을 , nodeTxt)
plotNode (firstStr을, cntrPt, parentPt, decisionNode)
secondDict으로 myTree = [firstStr을]
plotTree.yOff plotTree.yOff = - 1.0 / plotTree.totalD
secondDict.keys 키 () 대 :
입력하면 (secondDict [
키]) .__ name__ == 'DICT'노드가 dictonaires 인 경우 # 시험은 잎 노드입니다하지 않을 경우, 볼
plotTree (secondDict] [키, cntrPt는, STR (키)) # 재귀
#은 잎 노드가있다 : 다른 사람이 리프 노드를 인쇄
plotTree.xOff plotTree.xOff = + 1.0 / plotTree.totalW
plotNode ([키] secondDict (plotTree.xOff, plotTree.yOff) cntrPt, leafnode의)
plotMidText ((plotTree.xOff, plotTree.yOff) cntrPt, STR (키))
plotTree.yOff plotTree.yOff = + 1.0 / plotTree.totalD

당신이 dictonary을받을 수 있나요 경우 당신은 나무 알고, 그리고 첫 번째 요소는 다른 DICT 될 것입니다

의사 결정 트리를 그리기

DEF createPlot (inTree)
도 plt.figure = (1, facecolor = '흰색')
fig.clf ()
axprops = 딕셔너리 (xticks = [], yticks = [])
createPlot.ax1 = plt.subplot (111 frameon = 거짓, ** axprops) # 더 틱
# createPlot.ax1 = plt.subplot (데모 111 frameon = 거짓) #ticks가 puropses
) plotTree.totalW = 플로트 (getNumLeafs (inTree)
plotTree.totalD = 플로트 (getTreeDepth (inTree을 ))
plotTree.xOff = -0.5 / plotTree.totalW;
plotTree.yOff = 1.0;
plotTree (inTree, (0.5, 1.0), '')
plt.show ()

나무의 뿌리와 잎 노드 그리기 (루트 모양 : 직사각형, 잎 노드 : 타원형)

데프 createPlot () :

도 plt.figure = (1, facecolor = '흰색')

fig.clf ()

createPlot.ax1 = plt.subplot 데모 puropses 대 (111 frameon = 거짓) #ticks

plotNode ( '결정 노드'(0.5, 0.1), (0.1, 0.5), decisionNode)

plotNode ( '리프 노드'(0.8, 0.1), (0.3, 0.8), leafnode의)

plt.show ()

DEF retrieveTree (I) :
listOfTrees의 = [{ '아니오 곡면'{0 : 1, '아니오'{ '오리발'{0 '아니오'1 '예'}}}},
{ "더 표면화되지 '{0'아니오 ', 1 : {'오리발 '{0 {'머리 ': {0', '1'아니오 '}} 1 : "아니오"}}}}
]
돌아 오지 listOfTrees [I]

thisTree = retrieveTree (0)

createPlot (thisTree)

createPlot ()

retrieveTree으로 myTree = (0)

numLeafs = getNumLeafs (으로 myTree)

treeDepth = getTreeDepth (으로 myTree)

인쇄 (U "잎 노드 수 : % d 개"%의 numLeafs)

인쇄 (U "트리 깊이 : % d 개"%의 treeDepth)

테스트 코드

- - 코딩 : UTF-8 - -

"" "
3 19시 52분 10초 2018 금 8월에서 만든

@author : weixw
"" "
후지산 등의 수입 Demo_1.myTrees
TP 등의 수입 Demo_1.treePlotter

테스트

데이터 집합 라벨 = mt.createDataSet ()

복사 기능 : 새로운 메모리를 개방하기 위해, 새로운 메모리의 개구부에 복사 모든 값의 다음 목록

labels1 labels.copy = ()

값 createTree 기능 변경 labels1되므로 테스트는 분류 labels1 사용할 수 없습니다

mt.createTree으로 myTree = (데이터 세트 labels1)

지역에 나무를 저장

mt.storeTree (으로 myTree, 'myTree.txt')

로컬 디스크에 나무를 가져옵니다

=으로 myTree ( 'myTree.txt')의 mt.grabTree
인쇄 (U "의사 결정 트리 구조 : % S"%으로 myTree)

의사 결정 트리를 그리기

인쇄 (u는 "의사 결정 트리를 그리기 :")
(으로 myTree의) tp.createPlot
numLeafs = tp.getNumLeafs (으로 myTree의)
treeDepth = tp.getTreeDepth (으로 myTree의)
인쇄 (U "잎 노드 수 : % D"numLeafs %)
인쇄 (U를 " 트리 깊이 : % d 개 "%의 treeDepth)

테스트 카테고리 3 개 간단한 샘플 데이터

= mt.classify labelResult (으로 myTree의 라벨 [1,1,1,0])
인쇄 (U "[1,1] 시험 결과 : %의 S"%의 labelResult)
labelResult = mt.classify (으로 myTree의 라벨 [ 1,0,0,0])
인쇄 (U "[1,0] 시험 결과 : % S"%의 labelResult)

추천

출처www.cnblogs.com/131415-520/p/11789727.html