Python機(jī)器學(xué)習(xí)之決策樹
一、要求
二、原理
決策樹是一種類似于流程圖的結(jié)構(gòu),其中每個(gè)內(nèi)部節(jié)點(diǎn)代表一個(gè)屬性上的“測(cè)試”,每個(gè)分支代表測(cè)試的結(jié)果,每個(gè)葉節(jié)點(diǎn)代表一個(gè)測(cè)試結(jié)果。類標(biāo)簽(在計(jì)算所有屬性后做出的決定)。從根到葉的路徑代表分類規(guī)則。
決策樹學(xué)習(xí)的目的是為了產(chǎn)生一棵泛化能力強(qiáng),即處理未見示例能力強(qiáng)的決策樹。因此如何構(gòu)建決策樹,是后續(xù)預(yù)測(cè)的關(guān)鍵!而構(gòu)建決策樹,就需要確定類標(biāo)簽判斷的先后,其決定了構(gòu)建的決策樹的性能。決策樹的分支節(jié)點(diǎn)應(yīng)該盡可能的屬于同一類別,即節(jié)點(diǎn)的“純度”要越來越高,只有這樣,才能最佳決策。
經(jīng)典的屬性劃分方法:
- 信息增益
- 增益率
- 基尼指數(shù)
本次實(shí)驗(yàn)采用了信息增益,因此下面只對(duì)信息增益進(jìn)行介紹。
三、信息增益的計(jì)算方法
其中D為樣本集合,a為樣本集合中的屬性,Dv表示D樣本集合中a屬性為v的樣本集合。
Ent(x)函數(shù)是計(jì)算信息熵,表示的是樣本集合的純度信息,信息熵的計(jì)算方法如下:
其中pk表示樣本中最終結(jié)果種類中其中一個(gè)類別所占的比例,比如有10個(gè)樣本,其中5個(gè)好,5個(gè)不好,則其中p1 = 5/10, p2 = 5/10。
一般而言,信息增益越大,則意味著使用屬性α來進(jìn)行劃分所獲得的“純度提升”越大,因此在選擇屬性節(jié)點(diǎn)的時(shí)候優(yōu)先選擇信息增益高的屬性!
四、實(shí)現(xiàn)過程
本次設(shè)計(jì)用到了pandas和numpy庫,主要利用它們來對(duì)數(shù)據(jù)進(jìn)行快速的處理和使用。
首先將數(shù)據(jù)讀入:
可以看到數(shù)據(jù)集的標(biāo)簽是瓜的不同的屬性,而表格中的數(shù)據(jù)就是不同屬性下的不同的值等。
if(len(set(D.好瓜)) == 1): #標(biāo)記返回 return D.好瓜.iloc[0] elif((len(A) == 0) or Check(D, A[:-1])): #選擇D中結(jié)果最多的為標(biāo)記 cnt = D.groupby('好瓜').size() maxValue = cnt[cnt == cnt.max()].index[0] return maxValue else: A1 = copy.deepcopy(A) attr = Choose(D, A1[:-1]) tree = {attr:{}} for value in set(D[attr]): tree[attr][value] = TreeGen(D[D[attr] == value], A1) return tree
TreeGen函數(shù)是生成樹主函數(shù),通過對(duì)它的遞歸調(diào)用,返回下一級(jí)樹結(jié)構(gòu)(字典)來完成生成決策樹。
在生成樹過程中,有二個(gè)終止迭代的條件,第一個(gè)就是當(dāng)輸入數(shù)據(jù)源D的所有情況結(jié)果都相同,那么將這個(gè)結(jié)果作為葉節(jié)點(diǎn)返回;第二個(gè)就是當(dāng)沒有屬性可以再往下分,或者D中的樣本在A所有屬性下面的值都相同,那么就將D的所有情況中結(jié)果最多的作為葉節(jié)點(diǎn)返回。
其中Choose(D:pd.DataFrame, A:list)函數(shù)是選擇標(biāo)簽的函數(shù),其根據(jù)輸入數(shù)據(jù)源和剩下的屬性列表算出對(duì)應(yīng)標(biāo)簽信息增益,選擇能使信息增益最大的標(biāo)簽返回
def Choose(D:pd.DataFrame, A:list): result = 0.0 resultAttr = '' for attr in A: tmpVal = CalcZengYi(D, attr) if(tmpVal > result): resultAttr = attr result = tmpVal A.remove(resultAttr) return resultAttr
最后是結(jié)果:
{‘紋理': {‘稍糊': {‘觸感': {‘硬滑': ‘否', ‘軟粘': ‘是'}}, ‘清晰': {‘根蒂': {‘硬挺': ‘否', ‘蜷縮': ‘是', ‘稍蜷': {‘色澤': {‘青綠': ‘是', ‘烏黑': {‘觸感': {‘硬滑': ‘是', ‘軟粘': ‘否'}}}}}}, ‘模糊': ‘否'}}
繪圖如下:
五、程序
主程序
#!/usr/bin/python3 # -*- encoding: utf-8 -*- ''' @Description:決策樹: @Date :2021/04/25 15:57:14 @Author :willpower @version :1.0 ''' import pandas as pd import numpy as np import treeplot import copy import math """ @description :計(jì)算熵值 --------- @param :輸入為基本pandas類型dataFrame,其中輸入最后一行為實(shí)際結(jié)果 ------- @Returns :返回熵值,類型為浮點(diǎn)型 ------- """ def CalcShang(D:pd.DataFrame): setCnt = D.shape[0] result = 0.0 # for i in D.groupby(D.columns[-1]).size().index: #遍歷每一個(gè)值 for i in set(D[D.columns[-1]]): #獲取該屬性下的某個(gè)值的次數(shù) cnt = D.iloc[:,-1].value_counts()[i] result = result + (cnt/setCnt)*math.log(cnt/setCnt, 2) return (-1*result) """ @description :計(jì)算增益 --------- @param :輸入為DataFrame數(shù)據(jù)源,然后是需要計(jì)算增益的屬性值 ------- @Returns :返回增益值,浮點(diǎn)型 ------- """ def CalcZengYi(D:pd.DataFrame, attr:str): sumShang = CalcShang(D) setCnt = D.shape[0] result = 0.0 valus = D.groupby(attr).size() for subVal in valus.index: result = result + (valus[subVal]/setCnt)*CalcShang(D[D[attr] == subVal]) return sumShang - result """ @description :選擇最佳的屬性 --------- @param :輸入為數(shù)據(jù)源,以及還剩下的屬性列表 ------- @Returns :返回最佳屬性 ------- """ def Choose(D:pd.DataFrame, A:list): result = 0.0 resultAttr = '' for attr in A: tmpVal = CalcZengYi(D, attr) if(tmpVal > result): resultAttr = attr result = tmpVal A.remove(resultAttr) return resultAttr """ @description :檢查數(shù)據(jù)在每一個(gè)屬性下面的值是否相同 --------- @param :輸入為DataFrame以及剩下的屬性列表 ------- @Returns :返回bool值,相同返回1,不同返回0 ------- """ def Check(D:pd.DataFrame, A:list): for i in A: if(len(set(D[i])) != 1): return 0 return 1 """ @description :生成樹主函數(shù) --------- @param :數(shù)據(jù)源DataFrame以及所有類型 ------- @Returns :返回生成的字典樹 ------- """ def TreeGen(D:pd.DataFrame, A:list): if(len(set(D.好瓜)) == 1): #標(biāo)記返回 return D.好瓜.iloc[0] elif((len(A) == 0) or Check(D, A[:-1])): #選擇D中結(jié)果最多的為標(biāo)記 cnt = D.groupby('好瓜').size() #找到結(jié)果最多的結(jié)果 maxValue = cnt[cnt == cnt.max()].index[0] return maxValue else: A1 = copy.deepcopy(A) attr = Choose(D, A1[:-1]) tree = {attr:{}} for value in set(D[attr]): tree[attr][value] = TreeGen(D[D[attr] == value], A1) return tree """ @description :驗(yàn)證集 --------- @param :輸入為待驗(yàn)證的數(shù)據(jù)(最后一列為真實(shí)結(jié)果)以及決策樹模型 ------- @Returns :無 ------- """ def Test(D:pd.DataFrame, model:dict): for i in range(D.shape[0]): data = D.iloc[i] subModel = model while(1): attr = list(subModel)[0] subModel = subModel[attr][data[attr]] if(type(subModel).__name__ != 'dict'): print(subModel, end='') break print('') name = ['色澤', '根蒂', '敲聲', '紋理', '臍部', '觸感', '好瓜'] df = pd.read_csv('./savedata.txt', names=name) # CalcZengYi(df, '色澤') resultTree = TreeGen(df, name) print(resultTree) # print(df[name[:-1]]) Test(df[name[:-1]], resultTree) treeplot.plot_model(resultTree,"resultTree.gv")
繪圖程序
from graphviz import Digraph def plot_model(tree, name): g = Digraph("G", filename=name, format='png', strict=False) first_label = list(tree.keys())[0] g.node("0", first_label) _sub_plot(g, tree, "0") g.view() root = "0" def _sub_plot(g, tree, inc): global root first_label = list(tree.keys())[0] ts = tree[first_label] for i in ts.keys(): if isinstance(tree[first_label][i], dict): root = str(int(root) + 1) g.node(root, list(tree[first_label][i].keys())[0]) g.edge(inc, root, str(i)) _sub_plot(g, tree[first_label][i], root) else: root = str(int(root) + 1) g.node(root, tree[first_label][i]) g.edge(inc, root, str(i))
./savedata.txt
青綠,蜷縮,濁響,清晰,凹陷,硬滑,是
烏黑,蜷縮,沉悶,清晰,凹陷,硬滑,是
烏黑,蜷縮,濁響,清晰,凹陷,硬滑,是
青綠,蜷縮,沉悶,清晰,凹陷,硬滑,是
淺白,蜷縮,濁響,清晰,凹陷,硬滑,是
青綠,稍蜷,濁響,清晰,稍凹,軟粘,是
烏黑,稍蜷,濁響,稍糊,稍凹,軟粘,是
烏黑,稍蜷,濁響,清晰,稍凹,硬滑,是
烏黑,稍蜷,沉悶,稍糊,稍凹,硬滑,否
青綠,硬挺,清脆,清晰,平坦,軟粘,否
淺白,硬挺,清脆,模糊,平坦,硬滑,否
淺白,蜷縮,濁響,模糊,平坦,軟粘,否
青綠,稍蜷,濁響,稍糊,凹陷,硬滑,否
淺白,稍蜷,沉悶,稍糊,凹陷,硬滑,否
烏黑,稍蜷,濁響,清晰,稍凹,軟粘,否
淺白,蜷縮,濁響,模糊,平坦,硬滑,否
青綠,蜷縮,沉悶,稍糊,稍凹,硬滑,否
六、遇到的問題
graphviz Not a directory: ‘dot'
解決辦法
到此這篇關(guān)于Python機(jī)器學(xué)習(xí)之決策樹的文章就介紹到這了,更多相關(guān)Python決策樹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python機(jī)器學(xué)習(xí)算法之決策樹算法的實(shí)現(xiàn)與優(yōu)缺點(diǎn)
- python機(jī)器學(xué)習(xí)實(shí)現(xiàn)決策樹
- Python機(jī)器學(xué)習(xí)算法庫scikit-learn學(xué)習(xí)之決策樹實(shí)現(xiàn)方法詳解
- python機(jī)器學(xué)習(xí)理論與實(shí)戰(zhàn)(二)決策樹
- Python機(jī)器學(xué)習(xí)之決策樹算法
- python機(jī)器學(xué)習(xí)之決策樹分類詳解
- Python機(jī)器學(xué)習(xí)之決策樹算法實(shí)例詳解
- 機(jī)器學(xué)習(xí)python實(shí)戰(zhàn)之決策樹
- 分析機(jī)器學(xué)習(xí)之決策樹Python實(shí)現(xiàn)
相關(guān)文章
Python使用低通濾波器模糊圖像功能實(shí)現(xiàn)
這篇文章主要介紹了Python使用低通濾波器模糊圖像,我們介紹了多種不同類型的濾波器核與卷積操作,使用 scipy.ndimage 模塊中的濾波器模糊圖像,利用 scipy.fftpack 模塊的 fft2() 函數(shù)實(shí)現(xiàn)高斯模糊,介紹了scipy.signal模塊的彩色圖像頻域卷積,需要的朋友可以參考下2023-03-03關(guān)于對(duì)python中進(jìn)程的幾個(gè)概念理解
進(jìn)程由程序,數(shù)據(jù)和進(jìn)程控制塊組成,是正在執(zhí)行的程,程序的一次執(zhí)行過程,是資源調(diào)度的基本單位,下面這篇文章主要給大家介紹了關(guān)于對(duì)python中進(jìn)程的幾個(gè)概念理解,需要的朋友可以參考下2021-10-10python 信息同時(shí)輸出到控制臺(tái)與文件的實(shí)例講解
今天小編就為大家分享一篇python 信息同時(shí)輸出到控制臺(tái)與文件的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05