前一章介紹了線性回歸有很多強大的方法,但是缺點是創(chuàng)建的模型需要擬合所有的樣本點(局部加權線性回歸除外),當數據擁有很多特征并且特征之間關系復雜那就很麻煩了,況且生活中很多問題不是線性的,無法用線性模型擬合出來。
本章介紹CART(分類回歸樹),該算法既可以用于分類又可以用于回歸。回歸樹是在每個葉節(jié)點上使用各自的均值做預測,更高級的模型樹是在每個葉節(jié)點上都構建出一個線性模型。此外,在回歸樹中介紹了樹剪枝技術,目的是防止樹的過擬合。
9.1? 復雜數據的局部性建模
第3章使用ID3方法構建樹,做法是每次選取當前最佳特征來分割數據,并按照特征所有可能值來切分。這里的方法是二元切分法,即每次把數據集分成兩份。根據特征值大小進入左右兩個子樹。
9.2連續(xù)和離散型特征的樹的構建
在樹的構建過程中,需要解決多種類型數據的存儲問題,這里用字典來存儲樹的數據結構,字典里有四個元素:切分特征,待切分特征值,左子樹,右子樹。
本章構建兩個樹:回歸樹,其每個葉節(jié)點包含單個值。模型樹,其每個葉節(jié)點包含一個線性方程。
9.3將CART用于回歸
構建回歸樹思路:遍歷所有特征的所有特征值,對每一個特征值都進行一次數據集的劃分,然后算劃分后的兩個子集總方差之和,找到能使總方差之和最小的劃分特征值,然后進行一次劃分,得到兩個樹,對兩個樹遞歸進行相同操作。
約束條件:劃分的兩個數據集必須都大于多少行(如4行),防止劃分的一邊太大一邊太小,如果不滿足就不對這個特征值劃分。如果劃分后兩個子集的總方差之和與原總方差相差不大也不劃分,直接返回葉節(jié)點,表示不能再劃分了。如果目標變量都是一樣的,那肯定就不用劃分了,直接返回葉節(jié)點。
總結:劃分后葉節(jié)點的大小是葉節(jié)點數據集目標變量的均值,所以說,上面的做法就是把一團一團的數據分開來,總方差就是分開他們的依據,均值就是各數據集的一種表示。
下圖是兩個示例:
圖一圖二是不同的數據集畫出來的(這句是廢話)。很明顯,圖一肯定會被劃成2個子集,也就是2個葉節(jié)點,圖二會被劃成5個子集,也就是5個葉節(jié)點。如下:
所以,創(chuàng)建回歸樹有點像把抱團的子數據集劃分開,均值是他們各自中心點的體現,總方差是他們之間的遠近。
9.4? 樹剪枝
通過降低決策樹的復雜程度來避免過擬合的過程就是剪枝。剪枝可以分為預剪枝和后剪枝。前面提到的約束條件其實就是預剪枝,比如劃分的子集少于4行就不劃分,還有劃分后的總方差之和與原方差相差不大就不劃分,說白了就是不要劃分的太細,劃分太細可不就是過擬合了嗎~后剪枝需要使用測試集和訓練集。
9.4.1預剪枝
說說預剪枝的缺點,上面的簡單實驗用到了預剪枝,效果還可以,但是其實是有問題的。因為上面的算法對參數tolS和tolN很敏感。比如tolS=0,表示劃分后方差只要有減少就對數據集進行劃分。tolN=1,表示劃分后兩個子集哪怕只有一行也要劃分子集,也就是說每個樣本都成了一個葉節(jié)點。
可以看到這個散點圖和ex00.txt的散點圖相似,但是這個圖y軸的數量級是ex00.txt圖的100倍,這意味這什么?意味著創(chuàng)建樹時對誤差的選擇很重要,之前的tolS=1完全不行,這樣會創(chuàng)建很多葉節(jié)點,創(chuàng)建的樹十分臃腫,當tolS=10000時才會得到只有兩個葉節(jié)點的樹。
所以,通過不斷修改停止條件來得到合理的結果并不是一個很好的做法,況且很多時候我們也不知道我們想要的結果是什么。而這正是機器學習需要做的:給出數據的總體樣貌。
9.4.2? 后剪枝
使用后剪枝方法需要將數據集分成測試集和訓練集。首先指定參數,使構建的樹足夠大,足夠復雜,便于剪枝。接下來從上而下找到葉節(jié)點,用測試集來判斷將這些葉節(jié)點合并能否降低測試誤差,如果能就合并。
代碼運行結果就不放了,巨多,放了也沒有什么直觀的可比性。代碼思路:先用訓練數據訓練出一棵樹,然后用訓練好的樹和測試數據作為輸入進行自上而下的遞歸剪枝。
過程:首先測試數據集根據訓練好的樹來劃分子集,然后剪枝。遞歸到最后,就是比較最底層兩個葉節(jié)點合并后的總方差和不合并的各自總方差之和哪個更大,如果合并了方差變小了就剪枝,而剪枝就是把兩個葉節(jié)點的數值相加除以2,表示兩個子集合并,均值就是兩個子集均值的平均值。(書中說是自上而下剪枝,但其實是自下而上合并,最后合并到不需要合并結束,最后遍歷完整個測試數據集。它所說的自上而下估計是因為遞歸是自上而下,也有可能是我算法沒學好,不理解這四個字的含義(@_@))
最后,結果是大量節(jié)點被剪枝掉了,但是沒有像預期那樣剪成兩個部分,這說明后剪枝不如預剪枝有效。一般的, 為了尋求最佳模型可以同時使用兩種剪枝技術。
9.5? 模型樹
模型樹比回歸樹好的地方在于:模型樹可解釋,有更高的預測準確度。它與回歸樹的不同在于葉節(jié)點不是只用一個數值表示,而是一個線性函數。
模型樹和回歸樹算法的不同點主要有兩個:一是葉節(jié)點,模型樹會將葉節(jié)點數據集的回歸系數作為葉節(jié)點的表示。二是誤差,回歸樹是計算總方差,模型樹是計算預測結果與真實結果的平方差。所以創(chuàng)建樹的函數以及選擇最優(yōu)劃分特征的函數可以通用,只要改變葉節(jié)點表達函數和誤差計算函數即可。
下面是示例:
很明顯exp2.txt用模型樹來擬合會有很好的效果,結果如下:
可以看到,建立的模型樹以0.285477為界創(chuàng)建了兩個模型。兩個模型是線性函數,與真實模型十分接近。
9.6? 示例:樹回歸與標準回歸的比較
模型樹、回歸樹以及前一章的普通線性回歸,哪一種模型更好?有一個客觀的方法,就是計算他們預測結果與真實結果的相關系數。本示例就是分別計算三種模型的預測結果并將他們與真實結果的相關系數做一下比較。
用樹回歸進行預測的代碼思路:首先用訓練數據訓練出一棵樹,然后對測試數據進行遞歸,根據劃分特征與測試數據對應特征值大小找到測試數據所在葉節(jié)點,然后根據葉節(jié)點返回預測值,即為此測試數據的預測值。在回歸樹中,此預測值就是葉節(jié)點數據集目標變量的均值。在模型樹中,此預測值就是測試數據與葉節(jié)點回歸系數乘積得到的預測值。
下面給出測試數據的圖:
總結:很明顯,樹回歸在預測復雜數據時會比簡單的線性模型更有效。而對于這個數據集,模型樹方法比回歸樹方法效果更好一些。個人認為,模型樹方法有點像是普通線性回歸的變種,或者說是分段的線性回歸。對于有這種特征的數據,顯然模型樹會比回歸樹表現的更好,因為我感覺回歸樹更適用于一個個抱團的子數據集組成的大數據集,而每個子數據集都是一個葉節(jié)點。
總的來說,回歸樹更擅長將數據集中一個個抱團的子數據集分開,每個子數據集就是一個葉節(jié)點,葉節(jié)點通過子數據集目標變量的均值來表達。而模型樹更擅長將數據集中一段段線性的子數據集分開,每一段子數據集就是一個葉節(jié)點,葉節(jié)點用線性回歸的方法來表達。
9.7? 使用Python的Tkinter庫創(chuàng)建GUI
本節(jié)內容:
首先介紹如何利用一個現有模塊Tkinter來構建GUI
之后介紹如何在Tkinter和繪圖庫之間交互
最后通過創(chuàng)建GUI使人們能夠自己探索模型樹和回歸樹的奧秘。
本章我只是概覽了一下,沒有詳細研究代碼,以后有需要再回頭研究。主要工作就是用Tkinter創(chuàng)建GUI,然后集成Matplotlib和Tkinter,就可以得到一個圖形用戶界面,更方便直觀地展示數據的分析結果。以下是對數據創(chuàng)建回歸樹和模型樹的兩幅圖:
PS:費了老鼻子勁才搞出這兩張圖,中間一直報錯也很難找到結果,代碼明明就是和書上一毛一樣。最終百度了無數,好不容易找到了類似的問題,又從別人一句微不足道的評論里找到了答案,試一試,出來了。真真是謝謝他八輩兒祖宗了~問題出在畫點時括號里的數據集參數得是數組,聲明一下即可。心累額......
9.8本章小結
在小結中看到一種說法,也是有道理的,即回歸樹和模型樹都是對預測值分段的樹,主要論述如下:數據集中經常包含一些復雜的關系,使得輸入數據和目標變量之間呈現非線性關系。對復雜關系建模,可以使用樹來對預測值分段,包括分段常數或分段直線。相應的,若葉節(jié)點使用的模型是分段常數則稱為回歸樹,若葉節(jié)點使用的模型是線性回歸方程則稱為模型樹。使用不同的誤差準則,就可以通過CART算法構建回歸樹和模型樹。
CART算法構建的樹傾向于對數據過擬合,一棵過擬合的樹常常十分復雜,所以剪枝技術就出現了。兩種剪枝方法分別是預剪枝(在樹的構建中就進行剪枝)和后剪枝(當樹構建完畢再剪枝),預剪枝更有效但需要用戶定義一些參數。
書中寫道:
本章是回歸的最后一章!
接下來我們將離開監(jiān)督學習的島嶼!
駛向無監(jiān)督學習的未知港灣!
啊!星辰大海!