
機器學習之決策樹(ID3)算法與Python實現(xiàn)
機器學習中,決策樹是一個預測模型;他代表的是對象屬性與對象值之間的一種映射關系。樹中每個節(jié)點表示某個對象,而每個分叉路徑則代表的某個可能的屬性值,而每個葉結點則對應從根節(jié)點到該葉節(jié)點所經歷的路徑所表示的對象的值。決策樹僅有單一輸出,若欲有復數輸出,可以建立獨立的決策樹以處理不同輸出。 數據挖掘中決策樹是一種經常要用到的技術,可以用于分析數據,同樣也可以用來作預測。
決策樹,其結構和樹非常相似,因此得其名決策樹。決策樹具有樹形的結構,其中每個內部節(jié)點表示一個屬性上的測試,每個分支代表一個測試輸出,每個葉節(jié)點代表一種類別。
例如:
按照豆腐腦的冷熱、甜咸和是否含有大蒜構建決策樹,對其屬性的測試,在最終的葉節(jié)點決定該豆腐腦吃還是不吃。
分類樹(決策樹)是一種十分常用的將決策樹應用于分類的機器學習方法。他是一種監(jiān)管學習,所謂監(jiān)管學習就是給定一堆樣本,每個樣本都有一組屬性(特征)和一個類別(分類信息/目標),這些類別是事先確定的,那么通過學習得到一個分類器,這個分類器能夠對新出現(xiàn)的對象給出正確的分類。
其原理在于,每個決策樹都表述了一種樹型結構,它由它的分支來對該類型的對象依靠屬性進行分類。每個決策樹可以依靠對源數據庫的分割進行數據測試。這個過程可以遞歸式的對樹進行修剪。 當不能再進行分割或一個單獨的類可以被應用于某一分支時,遞歸過程就完成了。
機器學習中,決策樹是一個預測模型;他代表的是對象屬性與對象值之間的一種映射關系。樹中每個節(jié)點表示某個對象,而每個分叉路徑則代表的某個可能的屬性值,而每個葉結點則對應從根節(jié)點到該葉節(jié)點所經歷的路徑所表示的對象的值。決策樹僅有單一輸出,若欲有復數輸出,可以建立獨立的決策樹以處理不同輸出。數據挖掘中決策樹是一種經常要用到的技術,可以用于分析數據,同樣也可以用來作預測。從數據產生決策樹的機器學習技術叫做決策樹學習, 通俗說就是決策樹。
目前常用的決策樹算法有ID3算法、改進的C4.5算法和CART算法。
決策樹的特點
1.多層次的決策樹形式易于理解;
2.只適用于標稱型數據,對連續(xù)性數據處理得不好;
2、ID3算法
ID3算法最早是由羅斯昆(J. Ross Quinlan)于1975年在悉尼大學提出的一種分類預測算法,算法以信息論為基礎,其核心是“信息熵”。ID3算法通過計算每個屬性的信息增益,認為信息增益高的是好屬性,每次劃分選取信息增益最高的屬性為劃分標準,重復這個過程,直至生成一個能完美分類訓練樣例的決策樹。
信息熵(Entropy):
,其中p(xi)是選擇i的概率。
熵越高,表示混合的數據越多。信息增益(Information Gain):
T是劃分之后的分支集合,p(t)是該分支集合在原本的父集合中出現(xiàn)的概率,H(t)是該子集合的信息熵。
3.ID3算法與決策樹的流程
(1)數據準備:需要對數值型數據進行離散化
(2)ID3算法構建決策樹:
如果數據集類別完全相同,則停止劃分
否則,繼續(xù)劃分決策樹:
計算信息熵和信息增益來選擇最好的數據集劃分方法;
劃分數據集
創(chuàng)建分支節(jié)點:
對每個分支進行判定是否類別相同,如果相同停止劃分,不同按照上述方法進行劃分。
二、Python算法實現(xiàn)
創(chuàng)建 trees.py文件,在其中創(chuàng)建構建決策樹的函數。
首先構建一組測試數據:
0. 構造函數createDataSet:
def createDataSet():
dataSet=[[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
labels=['no surfacing','flippers']
return dataSet,labels
在Python控制臺測試構造函數
#測試下構造的數據Out[5]: ['no surfacing', 'flippers']
2.1 計算信息熵
from math import log
def calcShannonEnt(dataSet):
numEntries = len(dataSet) #nrows
#為所有的分類類目創(chuàng)建字典
labelCounts ={}
for featVec in dataSet:
currentLable=featVec[-1] #取得最后一列數據
if currentLable not in labelCounts.keys():
labelCounts[currentLable]=0
labelCounts[currentLable]+=1
#計算香農熵
shannonEnt=0.0
for key in labelCounts:
prob = float(labelCounts[key]) / numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt
利用構造的數據測試calcShannonEnt:
#Python console
In [6]: trees.calcShannonEnt(myDat)
...:
Out[6]: 0.9709505944546686
2.2 按照最大信息增益劃分數據集
#定義按照某個特征進行劃分的函數splitDataSet在控制臺中測試這兩個函數:
#測試按照特征劃分數據集的函數Out[14]: 0
2.3 創(chuàng)建決策樹構造函數createTree
import operater以之前構造的測試數據為例,對決策樹構造函數進行測試,在python控制臺進行輸入:
#決策樹構造函數測試可以看到,最后生成的決策樹myTree是一個多層嵌套的字典。
2.4 決策樹運用于分類
#輸入三個變量(決策樹,屬性特征標簽,測試的數據)對決策樹分類函數進行測試:
In [29]: reload(trees)Out[35]: 'yes'
2.5 決策樹的存儲
如果每次都需要訓練樣本集來構建決策樹,費時費力,特別是數據很大的時候,每次重新構建決策樹浪費時間。因此可以將已經創(chuàng)建的決策樹(如字典形式)保存在硬盤上,需要使用的時候直接讀取就好。
(1)存儲函數
在工作目錄下存在一個名為’classifierStorage.txt’的txt文檔,該文檔 保存了myTree的決策樹信息,需要使用的時候直接調出使用。
三、使用Matplotlib繪制決策樹
import matplotlib.pyplot as plt
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei'] #否則中文無法正常顯示
decisionNode=dict(boxstyle='sawtooth',fc='0.8') #決策點樣式
leafNode=dict(boxstyle='round4',fc='0.8') #葉節(jié)點樣式
arrow_args=dict(arrowstyle='<-') #箭頭樣式
def plotNode(nodeTxt,centerPt,parentPt,nodeType):
createPlot.ax1.annotate(nodeTxt,xy=parentPt,xycoords='axes fraction',
xytext=centerPt,textcoords='axes fraction',
va='center',ha='center',bbox=nodeType,arrowprops=arrow_args)
def createPlot():
fig=plt.figure(1,facecolor='white')
fig.clf()
createPlot.ax1=plt.subplot(111,frameon=False)
plotNode('決策節(jié)點',(0.5,0.1),(0.1,0.5),decisionNode)
plotNode('葉節(jié)點',(0.8,0.1),(0.3,0.8),leafNode)
plt.show()
#測試
#獲取葉節(jié)點數量(廣度)
def getNumLeafs(myTree):
numLeafs=0
firstStr=list(myTree.keys())[0]#'dict_keys' object does not support indexing
secondDict=myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
numLeafs+=getNumLeafs(secondDict[key])
else:numLeafs+=1
return numLeafs
#獲取樹的深度的函數(深度)
def getTreeDepth(myTree):
maxDepth=0
firstStr=list(myTree.keys())[0]
secondDict=myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
thisDepth=1+getTreeDepth(secondDict[key])
else: thisDepth=1
if thisDepth > maxDepth:
maxDepth=thisDepth
return maxDepth
#定義一個預先創(chuàng)建樹的函數
def retrieveTree(i):
listOfTrees=[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},
{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head':{0:'no', 1: 'yes'}},1:'no'}}}}
]
return listOfTrees[i]
#定義在父子節(jié)點之間填充文本信息的函數
def plotMidText(cntrPt,parentPt,txtString):
xMid=(parentPt[0]-cntrPt[0])/2+cntrPt[0]
yMid=(parentPt[1]-cntrPt[1])/2+cntrPt[1]
createPlot.ax1.text(xMid,yMid,txtString)
#定義樹繪制的函數
def plotTree(myTree,parentPt,nodeTxt):
numLeafs=getNumLeafs(myTree)
depth=getTreeDepth(myTree)
firstStr=list(myTree.keys())[0]
cntrPt=(plotTree.xOff+(1.0+float(numLeafs))/2/plotTree.totalW,plotTree.yOff)
plotMidText(cntrPt,parentPt,nodeTxt)
plotNode(firstStr,cntrPt,parentPt,decisionNode)
secondDict=myTree[firstStr]
plotTree.yOff=plotTree.yOff -1/plotTree.totalD
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
plotTree(secondDict[key],cntrPt,str(key))
else:
plotTree.xOff=plotTree.xOff+1.0/plotTree.totalW
plotNode(secondDict[key],(plotTree.xOff,plotTree.yOff),cntrPt,leafNode)
plotMidText((plotTree.xOff,plotTree.yOff),cntrPt,str(key))
plotTree.yOff=plotTree.yOff+1/plotTree.totalD
#定義主函數,來調用其它函數
def createPlot(inTree):
fig=plt.figure(1,facecolor='white')
fig.clf()
axprops=dict(xticks=[],yticks=[])
createPlot.ax1=plt.subplot(111,frameon=False,**axprops)
plotTree.totalW=float(getNumLeafs(inTree))
plotTree.totalD=float(getTreeDepth(inTree))
plotTree.xOff=-0.5/plotTree.totalW;plotTree.yOff=1.0;
plotTree(inTree,(0.5,1.0),'')
plt.show()
對繪制決策樹圖的函數進行測試(控制臺):
In [26]: reload(treeplotter)
...:
Out[26]: <module 'treeplotter' from 'G:\\Workspaces\\MachineLearning\\treeplotter.py'>
In [27]: myTree=treeplotter.retrieveTree(0)
...:
In [28]: treeplotter.createPlot(myTree)
...:
得到決策樹圖:
隱形眼鏡的數據集包含了患者的四個屬性age,prescript,stigmatic,tearRate,利用這些數據構建決策樹,并通過Matplotlib繪制出決策樹的樹狀圖。
附lenses.txt數據:
得到圖
數據分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
SQL Server 中 CONVERT 函數的日期轉換:從基礎用法到實戰(zhàn)優(yōu)化 在 SQL Server 的數據處理中,日期格式轉換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關聯(lián)查詢效率:打破 “拆分必慢” 的認知誤區(qū) 在 MySQL 數據庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數據分析師:表結構數據 “獲取 - 加工 - 使用” 全流程的賦能者 表結構數據(如數據庫表、Excel 表、CSV 文件)是企業(yè)數字 ...
2025-09-18DSGE 模型中的 Et:理性預期算子的內涵、作用與應用解析 動態(tài)隨機一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數據分析師:解鎖表結構數據特征價值的專業(yè)核心 表結構數據(以 “行 - 列” 規(guī)范存儲的結構化數據,如數據庫表、Excel 表、 ...
2025-09-17Excel 導入數據含缺失值?詳解 dropna 函數的功能與實戰(zhàn)應用 在用 Python(如 pandas 庫)處理 Excel 數據時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應用 在數據分析與統(tǒng)計學領域,假設檢驗是驗證研究假設、判斷數據差異是否 “ ...
2025-09-16CDA 數據分析師:掌控表格結構數據全功能周期的專業(yè)操盤手 表格結構數據(以 “行 - 列” 存儲的結構化數據,如 Excel 表、數據 ...
2025-09-16MySQL 執(zhí)行計劃中 rows 數量的準確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調優(yōu)中,EXPLAIN執(zhí)行計劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對象的 text 與 content:區(qū)別、場景與實踐指南 在 Python 進行 HTTP 網絡請求開發(fā)時(如使用requests ...
2025-09-15CDA 數據分析師:激活表格結構數據價值的核心操盤手 表格結構數據(如 Excel 表格、數據庫表)是企業(yè)最基礎、最核心的數據形態(tài) ...
2025-09-15Python HTTP 請求工具對比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請求(如接口調用、數據爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點數據的科學計數法問題 為幫助 Python 數據從業(yè)者解決pd.read_csv讀取長浮點數據時的科學計數法問題 ...
2025-09-12CDA 數據分析師:業(yè)務數據分析步驟的落地者與價值優(yōu)化者 業(yè)務數據分析是企業(yè)解決日常運營問題、提升執(zhí)行效率的核心手段,其價值 ...
2025-09-12用 SQL 驗證業(yè)務邏輯:從規(guī)則拆解到數據把關的實戰(zhàn)指南 在業(yè)務系統(tǒng)落地過程中,“業(yè)務邏輯” 是連接 “需求設計” 與 “用戶體驗 ...
2025-09-11塔吉特百貨孕婦營銷案例:數據驅動下的精準零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當下,精準營銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數據分析師與戰(zhàn)略 / 業(yè)務數據分析:概念辨析與協(xié)同價值 在數據驅動決策的體系中,“戰(zhàn)略數據分析”“業(yè)務數據分析” 是企業(yè) ...
2025-09-11Excel 數據聚類分析:從操作實踐到業(yè)務價值挖掘 在數據分析場景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數據中挖 ...
2025-09-10統(tǒng)計模型的核心目的:從數據解讀到決策支撐的價值導向 統(tǒng)計模型作為數據分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10