機器學習實戰ch03

3.1.1

>>>a="qwe"

>>> a[-1]

'e'

列表的最後一位是-1.

>>>import trees

之後在Python的console中就可以使用trees.py中的函數了。

>>> lc={}

>>>lc["no"]=0

>>>lc['yes']=3

>>> lc

{'yes': 3, 'no':0}

>>>lc.keys()

['yes', 'no']

>>>lc.values()

[3, 0]

一個簡單的例子,字典lc由key和value組成。這裏,key是'no'和'yes',value分別是0和3。

>>> 'yes'in lc.keys()

True

>>> 'mo'in lc.keys()

False

可以用keys()函數檢測字典中有什麼樣的key。

>>>float(lc['no'])

0.0

>>>float(lc['yes'])

3.0

根據 key得到相應的value,並且將value轉化成float形式。

>>>mydata

[[1, 1, 'yes'],[1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]

>>>trees.calcShannonEnt(mydata)

0.9709505944546686

在這個函數中會新建一個字典labelCounts = {},輸入mydata經過計算後,該字典中的key是’'yes'和'no',相應的value是2和3.求出每種key發生的頻率,求對數後,可以得到相應的熵。

3.1.2

>>>a=[0,1,2,3,4,5]

>>>b=a[:2]

>>> b

[0, 1]

b包含的列表的前面兩個數。

>>>c=a[3:]

>>> c

[3, 4, 5]

c包含了列表的從第3個數開始到最後一個數(開頭的是第0個數)。

>>>b.extend(c)

>>> b

[0, 1, 3, 4, 5]

把c中的元素加到b中,b比a少了第2個數。

>>>d=b.extend(c)

>>> d

錯誤用法,d顯示爲空。

>>>b.append(c)

>>> b

[0, 1, 3, 4, 5,[3, 4, 5]]

跟上面對比可以看出,extend是把列表中的元素一個個加進去,append是將列表整個加進去。

>>>mydata

[[1, 1, 'yes'],[1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]

>>>d=[a[0] for a in mydata]

>>> d

[1, 1, 1, 0, 0]

>>>set(d)

set([0, 1])

>>>e=set(d)

>>> e

set([0, 1])

>>> y=[ vfor v in e]

>>> y

[0, 1]

可以用這些函數將mydata中5條數據中的第0個元素提取出來,然後看第0個元素有多少種類,組成一個集合。

>>>trees.chooseBestFeatureToSplit(mydata)

0

這個函數先將mydata根據每條數據中的第0個元素的分類(第0個元素是1)形成一個新的子集[[1, 'yes'], [1, 'yes'], [ 0, 'no']],根據'yes'和'no'計算該子集的熵,乘以3/5的比例後加到newEntropy中,然後再根據第0個元素的分類(第0個元素是0)形成一個新的子集[ [1, 'no'], [1, 'no']], 根據'yes'和'no'計算該子集的熵,乘以2/5的比例後加到newEntropy中。同樣原理可以將mydata根據每條數據中的第1個元素的分類得到相應的newEntropy。該函數等效於比較newEntropy的大小,根據第i個元素得到的newEntropy小,就把bestFeature改成i。

3.13

>>>mytree=trees.createTree(mydata,label)

>>>mytree

{'no surfacing':{0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

這個函數的輸入是mydata和label,返回的是包含了很多代表樹結構信息的嵌套字典。當進入函數,但還沒有進入 for value in uniqueVals:循環前,mytree={'no surfacing': {}}。 uniqueVals是一個有0和1的set,由數據集中的第0個元素得到。

>>>mytree['no surfacing']

{}

mytree['nosurfacing']是一個空的字典

mytree['nosurfacing'][0]

這相當於在空字典中新建一個名稱爲0的key,而創建與該key對應的value則需要再一次進入 createTree()函數。這次輸入的數據集是:[[1, 'no'], [1, 'no']]

>>>trees.splitDataSet(mydata,0,0)

[[1, 'no'], [1,'no']]

由於輸入數據集的兩個數據最後一個元素類別完全相同,都是'no',所以,直接返回'no'。這時mytree={'no surfacing': {0: 'no'}}。

      然後運行mytree['no surfacing'][1],相當於在嵌套的字典中再新建一個名稱爲1的key,與前面那個名稱爲0的key並列。而創建與該key對應的value則需要再一次進入 createTree()函數。這次輸入的數據集是:[[1, 'yes'], [1, 'yes'], [0, 'no']]

>>>trees.splitDataSet(mydata,0,1)

[[1, 'yes'], [1,'yes'], [0, 'no']]

      接下來又會新建一個字典,假設是 mytree2={'flippers': {}}。

      然後進入for value in uniqueVals:循環, uniqueVals是一個有0和1的set,由數據集中的第1個元素得到。在空字典中新建一個名稱爲0的key,而創建與該key對應的value則需要再一次進入 createTree()函數。這次輸入的數據集是:[['no']]

>>>b=trees.splitDataSet(mydata,0,1)

>>> b

[[1, 'yes'], [1,'yes'], [0, 'no']]

>>>trees.splitDataSet(b,0,0)

[['no']]

所以返回的是'no'。這時mytree2={'flippers': {0:'no'}}

      接下去在字典中新建一個名稱爲1的key,而創建與該key對應的value則需要再一次進入 createTree()函數。這次輸入的數據集是:[['yes'], ['yes']]

>>>trees.splitDataSet(b,0,1)

[['yes'], ['yes']]

所以返回的是'yes'。這時mytree2={'flippers': {0: 'no', 1: 'yes'}}.

      跳出for value in uniqueVals:循環,返還mytree2。這時mytree={'no surfacing': {0: 'no', 1: {'flippers':{0: 'no', 1: 'yes'}}}}

      最後跳出前面一個for value in uniqueVals:循環,返還mytree。

3.2.1

      Linux系統中沒有自己安裝matplotlib。所以要在linux命令行中輸入:

sudo apt-getinstall python-matplotlib

>>>dict(p='pig',d='dog')

{'p': 'pig', 'd':'dog'}

>>>dict(p="pig",d="dog")

{'p': 'pig', 'd': 'dog'}

dict函數用於構造字典,雙引號和單引號效果一樣。

在官方給的例程中有兩個createPlot(),但是把3.2.1中的createPlot()函數用#號屏蔽掉了,把多個#號刪除,並且把那個createPlot()改成createPlot2()。輸入下面命令:

>>>reload(treePlotter)

<module'treePlotter' from 'treePlotter.py'>

>>>treePlotter.createPlot2()

可以得到書中圖3-5的圖像。

      plotNode()函數中nodeTxt指的是要在圖中打印的文字,xy是箭頭起始的座標,xytext是文字的位置。axes fraction指的是座標的值是從0到1的。arrowstyle="<-"指的是箭頭是指向文字的,bbox是包裝文字的盒子,有圓潤的和鋸齒形兩種。

      createPlot()函數中的createPlot.ax1是全局變量,所以該函數中調用的plotNode函數也可以對createPlot.ax1進行修改。

      getNumLeafs()函數中myTree.keys()[0]指的是myTree字典中第0個key,也就是'no surfacing'。secondDict是{0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}。然後進入循環for key in secondDict.keys():。secondDict裏面有兩個key,當key等於0時,所對應的secondDict[key]不是字典,所以進入else語句,此時numLeafs==1。當key==1時,所對應的secondDict[key]不是字典,所以又進入getNumLeafs函數中(爲了與前面的區分,假設爲getNumLeafs2),輸入的字典爲{'flippers': {0: 'no', 1: 'yes'}},輸入字典的value中沒有字典了,返還numLeafs(爲了與前面的區分,假設爲NumLeafs2),numLeafs2=2。跳出getNumLeafs2函數,此時numLeafs==3,返還numLeafs,跳出getNumLeafs函數。

      getTreeDepth()函數與前面一個函數大致一樣,不一樣的是在if type(secondDict[key]).__name__=='dict':語句後thisDepth至少是1,如果不是字典,那麼thisDepth就是1。

      plotTree()函數的輸入是myTree,parentPt,nodeText。當createPlot函數調用該函數時,myTree=={'no surfacing': {0: 'no', 1: {'flippers': {0:'no', 1: 'yes'}}}},parentPt==(0.5,1.0),nodeText==‘ ’。進入函數後firstStr='no surfacing',plotTree()函數中的cntrPt是用來計算當前決策節點的位置。假設現在的 plotTree.xOff記爲x(也就是上一個葉節點的x軸位置),總的葉節點plotTree.totalW爲N,輸入myTree的葉節點numLeafs爲n。那麼當前決策節點下面的葉節點x軸就是(x+1/N, x+2/N.............x+n/N),那麼決策節點的x軸位置應該是 x+1/N和 x+n/N的中間,也就是[2x+(1+n)/N]/2,y軸位置不變。cntrPt==(0.5,1.0),接下來的兩個函數plotNode()和plotMidText()就畫了一個位於(0.5,1)的決策節點。接下來plotTree.yOff=0.5。secondDict=={0: 'no', 1: {'flippers': {0: 'no', 1:'yes'}}}。接下去的for循環。首先key==0,進入else語句,plotTree.xOff變成了0.5/3,於是plotNode()在(plotTree.xOff,plotTree.yOff)即(0.5/3,0.5)畫了一個no的葉節點,plotMidText()在cntrPt和(plotTree.xOff,plotTree.yOff)中間寫上key的名稱0。接着key==1,進入if語句,進入循環(假設是plotTree2()),輸入是myTree== {'flippers': {0: 'no', 1: 'yes'}},parentPt==(0.5,1.0),nodeText==‘ 1’。接下來,cntrPt變成了(2/3,0.5),然後從 parentPt到cntrPt畫了一個箭頭到決策節點,中間標上 nodeText,secondDict 變成{0: 'no', 1: 'yes'},plotTree.yOff變成0。接下來進入for循環,由於 secondDict中沒有字典,所以循環的兩次都有進入else語句。當key==0時,從cntrPt到(plotTree.xOff,plotTree.yOff)==(1.5/3,0)處畫箭頭到葉節點,中間表上str(key)。當key==1時,從cntrPt到(plotTree.xOff,plotTree.yOff)==(2.5/3,0)處畫箭頭到葉節點,中間表上str(key)。跳出plotTree2(),接着再跳出plotTree()。

3.4

>>>ar=open('lenses.txt')

>>>a=ar.readlines()

>>> a

['young\tmyope\tno\treduced\tnolenses\r\n', 'young\tmyope\tno\tnormal\tsoft\r\n','young\tmyope\tyes\treduced\tno lenses\r\n', 'young\tmyope\tyes\tnormal\thard\r\n','young\thyper\tno\treduced\tno lenses\r\n','young\thyper\tno\tnormal\tsoft\r\n', 'young\thyper\tyes\treduced\tnolenses\r\n', 'young\thyper\tyes\tnormal\thard\r\n','pre\tmyope\tno\treduced\tno lenses\r\n', 'pre\tmyope\tno\tnormal\tsoft\r\n','pre\tmyope\tyes\treduced\tno lenses\r\n', 'pre\tmyope\tyes\tnormal\thard\r\n','pre\thyper\tno\treduced\tno lenses\r\n', 'pre\thyper\tno\tnormal\tsoft\r\n','pre\thyper\tyes\treduced\tno lenses\r\n', 'pre\thyper\tyes\tnormal\tnolenses\r\n', 'presbyopic\tmyope\tno\treduced\tno lenses\r\n','presbyopic\tmyope\tno\tnormal\tno lenses\r\n','presbyopic\tmyope\tyes\treduced\tno lenses\r\n','presbyopic\tmyope\tyes\tnormal\thard\r\n', 'presbyopic\thyper\tno\treduced\tnolenses\r\n', 'presbyopic\thyper\tno\tnormal\tsoft\r\n','presbyopic\thyper\tyes\treduced\tno lenses\r\n','presbyopic\thyper\tyes\tnormal\tno lenses\r\n']

>>> a[0]

'young\tmyope\tno\treduced\tnolenses\r\n'

>>>a[0].strip()

'young\tmyope\tno\treduced\tnolenses'

>>>a[0].strip().split('\t')

['young', 'myope','no', 'reduced', 'no lenses']

 

 

>>>fr=open('lenses.txt')

>>> fr

<open file'lenses.txt', mode 'r' at 0x7f5600bf6660>

>>>lenses=[inst.strip().split('\t') for inst in fr.readlines()]

>>>lenses

[['young','myope', 'no', 'reduced', 'no lenses'], ['young', 'myope', 'no', 'normal','soft'], ['young', 'myope', 'yes', 'reduced', 'no lenses'], ['young', 'myope','yes', 'normal', 'hard'], ['young', 'hyper', 'no', 'reduced', 'no lenses'],['young', 'hyper', 'no', 'normal', 'soft'], ['young', 'hyper', 'yes','reduced', 'no lenses'], ['young', 'hyper', 'yes', 'normal', 'hard'], ['pre','myope', 'no', 'reduced', 'no lenses'], ['pre', 'myope', 'no', 'normal','soft'], ['pre', 'myope', 'yes', 'reduced', 'no lenses'], ['pre', 'myope','yes', 'normal', 'hard'], ['pre', 'hyper', 'no', 'reduced', 'no lenses'],['pre', 'hyper', 'no', 'normal', 'soft'], ['pre', 'hyper', 'yes', 'reduced','no lenses'], ['pre', 'hyper', 'yes', 'normal', 'no lenses'], ['presbyopic','myope', 'no', 'reduced', 'no lenses'], ['presbyopic', 'myope', 'no', 'normal','no lenses'], ['presbyopic', 'myope', 'yes', 'reduced', 'no lenses'],['presbyopic', 'myope', 'yes', 'normal', 'hard'], ['presbyopic', 'hyper', 'no','reduced', 'no lenses'], ['presbyopic', 'hyper', 'no', 'normal', 'soft'],['presbyopic', 'hyper', 'yes', 'reduced', 'no lenses'], ['presbyopic', 'hyper','yes', 'normal', 'no lenses']]

>>>lensesTree=trees.createTree(lenses,lensesLabels)

>>>treePlotter.createPlot(lensesTree)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章