版權聲明:html
本文由LeftNotEasy發佈於http://leftnoteasy.cnblogs.com, 本文能夠被所有的轉載或者部分使用,但請註明出處,若是有問題,請聯繫wheeleast@gmail.com算法
前言:apache
決策樹這種算法有着不少良好的特性,好比說訓練時間複雜度較低,預測的過程比較快速,模型容易展現(容易將獲得的決策樹作成圖片展現出來)等。可是同時,單決策樹又有一些很差的地方,好比說容易over-fitting,雖然有一些方法,如剪枝能夠減小這種狀況,可是仍是不夠的。app
模型組合(好比說有Boosting,Bagging等)與決策樹相關的算法比較多,這些算法最終的結果是生成N(可能會有幾百棵以上)棵樹,這樣能夠大大的減小單決策樹帶來的毛病,有點相似於三個臭皮匠等於一個諸葛亮的作法,雖然這幾百棵決策樹中的每一棵都很簡單(相對於C4.5這種單決策樹來講),可是他們組合起來確是很強大。框架
在最近幾年的paper上,如iccv這種重量級的會議,iccv 09年的裏面有很多的文章都是與Boosting與隨機森林相關的。模型組合+決策樹相關的算法有兩種比較基本的形式 - 隨機森林與GBDT((Gradient Boost Decision Tree),其餘的比較新的模型組合+決策樹的算法都是來自這兩種算法的延伸。本文主要側重於GBDT,對於隨機森林只是大概提提,由於它相對比較簡單。dom
在看本文以前,建議先看看機器學習與數學(3)與其中引用的論文,本文中的GBDT主要基於此,而隨機森林相對比較獨立。機器學習
基礎內容:函數
這裏只是準備簡單談談基礎的內容,主要參考一下別人的文章,對於隨機森林與GBDT,有兩個地方比較重要,首先是information gain,其次是決策樹。這裏特別推薦Andrew Moore大牛的Decision Trees Tutorial,與Information Gain Tutorial。Moore的Data Mining Tutorial系列很是贊,看懂了上面說的兩個內容以後的文章才能繼續讀下去。學習
決策樹其實是將空間用超平面進行劃分的一種方法,每次分割的時候,都將當前的空間一分爲二,好比說下面的決策樹:spa
就是將空間劃分紅下面的樣子:
這樣使得每個葉子節點都是在空間中的一個不相交的區域,在進行決策的時候,會根據輸入樣本每一維feature的值,一步一步往下,最後使得樣本落入N個區域中的一個(假設有N個葉子節點)
隨機森林(Random Forest):
隨機森林是一個最近比較火的算法,它有不少的優勢:
隨機森林顧名思義,是用隨機的方式創建一個森林,森林裏面有不少的決策樹組成,隨機森林的每一棵決策樹之間是沒有關聯的。在獲得森林以後,當有一個新的輸入樣本進入的時候,就讓森林中的每一棵決策樹分別進行一下判斷,看看這個樣本應該屬於哪一類(對於分類算法),而後看看哪一類被選擇最多,就預測這個樣本爲那一類。
在創建每一棵決策樹的過程當中,有兩點須要注意 - 採樣與徹底分裂。首先是兩個隨機採樣的過程,random forest對輸入的數據要進行行、列的採樣。對於行採樣,採用有放回的方式,也就是在採樣獲得的樣本集合中,可能有重複的樣本。假設輸入樣本爲N個,那麼採樣的樣本也爲N個。這樣使得在訓練的時候,每一棵樹的輸入樣本都不是所有的樣本,使得相對不容易出現over-fitting。而後進行列採樣,從M個feature中,選擇m個(m << M)。以後就是對採樣以後的數據使用徹底分裂的方式創建出決策樹,這樣決策樹的某一個葉子節點要麼是沒法繼續分裂的,要麼裏面的全部樣本的都是指向的同一個分類。通常不少的決策樹算法都一個重要的步驟 - 剪枝,可是這裏不這樣幹,因爲以前的兩個隨機採樣的過程保證了隨機性,因此就算不剪枝,也不會出現over-fitting。
按這種算法獲得的隨機森林中的每一棵都是很弱的,可是你們組合起來就很厲害了。我以爲能夠這樣比喻隨機森林算法:每一棵決策樹就是一個精通於某一個窄領域的專家(由於咱們從M個feature中選擇m讓每一棵決策樹進行學習),這樣在隨機森林中就有了不少個精通不一樣領域的專家,對一個新的問題(新的輸入數據),能夠用不一樣的角度去看待它,最終由各個專家,投票獲得結果。
隨機森林的過程請參考Mahout的random forest 。這個頁面上寫的比較清楚了,其中可能不明白的就是Information Gain,能夠看看以前推薦過的Moore的頁面。
Gradient Boost Decision Tree:
GBDT是一個應用很普遍的算法,能夠用來作分類、迴歸。在不少的數據上都有不錯的效果。GBDT這個算法還有一些其餘的名字,好比說MART(Multiple Additive Regression Tree),GBRT(Gradient Boost Regression Tree),Tree Net等,其實它們都是一個東西(參考自wikipedia – Gradient Boosting),發明者是Friedman
Gradient Boost實際上是一個框架,裏面能夠套入不少不一樣的算法,能夠參考一下機器學習與數學(3)中的講解。Boost是"提高"的意思,通常Boosting算法都是一個迭代的過程,每一次新的訓練都是爲了改進上一次的結果。
原始的Boost算法是在算法開始的時候,爲每個樣本賦上一個權重值,初始的時候,你們都是同樣重要的。在每一步訓練中獲得的模型,會使得數據點的估計有對有錯,咱們就在每一步結束後,增長分錯的點的權重,減小分對的點的權重,這樣使得某些點若是總是被分錯,那麼就會被「嚴重關注」,也就被賦上一個很高的權重。而後等進行了N次迭代(由用戶指定),將會獲得N個簡單的分類器(basic learner),而後咱們將它們組合起來(好比說能夠對它們進行加權、或者讓它們進行投票等),獲得一個最終的模型。
而Gradient Boost與傳統的Boost的區別是,每一次的計算是爲了減小上一次的殘差(residual),而爲了消除殘差,咱們能夠在殘差減小的梯度(Gradient)方向上創建一個新的模型。因此說,在Gradient Boost中,每一個新的模型的簡歷是爲了使得以前模型的殘差往梯度方向減小,與傳統Boost對正確、錯誤的樣本進行加權有着很大的區別。
在分類問題中,有一個很重要的內容叫作Multi-Class Logistic,也就是多分類的Logistic問題,它適用於那些類別數>2的問題,而且在分類結果中,樣本x不是必定只屬於某一個類能夠獲得樣本x分別屬於多個類的機率(也能夠說樣本x的估計y符合某一個幾何分佈),這其實是屬於Generalized Linear Model中討論的內容,這裏就先不談了,之後有機會再用一個專門的章節去作吧。這裏就用一個結論:若是一個分類問題符合幾何分佈,那麼就能夠用Logistic變換來進行以後的運算。
假設對於一個樣本x,它可能屬於K個分類,其估計值分別爲F1(x)…FK(x),Logistic變換以下,logistic變換是一個平滑且將數據規範化(使得向量的長度爲1)的過程,結果爲屬於類別k的機率pk(x),
對於Logistic變換後的結果,損失函數爲:
其中,yk爲輸入的樣本數據的估計值,當一個樣本x屬於類別k時,yk = 1,不然yk = 0。
將Logistic變換的式子帶入損失函數,而且對其求導,能夠獲得損失函數的梯度:
假設輸入數據x可能屬於5個分類(分別爲1,2,3,4,5),訓練數據中,x屬於類別3,則y = (0, 0, 1, 0, 0),假設模型估計獲得的F(x) = (0, 0.3, 0.6, 0, 0),則通過Logistic變換後的數據p(x) = (0.16,0.21,0.29,0.16,0.16),y - p獲得梯度g:(-0.16, -0.21, 0.71, -0.16, -0.16)。觀察這裏能夠獲得一個比較有意思的結論:
假設gk爲樣本當某一維(某一個分類)上的梯度:
gk>0時,越大表示其在這一維上的機率p(x)越應該提升,好比說上面的第三維的機率爲0.29,就應該提升,屬於應該往「正確的方向」前進
越小表示這個估計越「準確」
gk<0時,越小,負得越多表示在這一維上的機率應該下降,好比說第二維0.21就應該獲得下降。屬於應該朝着「錯誤的反方向」前進
越大,負得越少表示這個估計越「不錯誤 」
總的來講,對於一個樣本,最理想的梯度是越接近0的梯度。因此,咱們要可以讓函數的估計值可以使得梯度往反方向移動(>0的維度上,往負方向移動,<0的維度上,往正方向移動)最終使得梯度儘可能=0),而且該算法在會嚴重關注那些梯度比較大的樣本,跟Boost的意思相似。
獲得梯度以後,就是如何讓梯度減小了。這裏是用的一個迭代+決策樹的方法,當初始化的時候,隨便給出一個估計函數F(x)(可讓F(x)是一個隨機的值,也可讓F(x)=0),而後以後每迭代一步就根據當前每個樣本的梯度的狀況,創建一棵決策樹。就讓函數往梯度的反方向前進,最終使得迭代N步後,梯度越小。
這裏創建的決策樹和普通的決策樹不太同樣,首先,這個決策樹是一個葉子節點數J固定的,當生成了J個節點後,就再也不生成新的節點了。
算法的流程以下:(參考自treeBoost論文)
0. 表示給定一個初始值
1. 表示創建M棵決策樹(迭代M次)
2. 表示對函數估計值F(x)進行Logistic變換
3. 表示對於K個分類進行下面的操做(其實這個for循環也能夠理解爲向量的操做,每個樣本點xi都對應了K種可能的分類yi,因此yi, F(xi), p(xi)都是一個K維的向量,這樣或許容易理解一點)
4. 表示求得殘差減小的梯度方向
5. 表示根據每個樣本點x,與其殘差減小的梯度方向,獲得一棵由J個葉子節點組成的決策樹
6. 爲當決策樹創建完成後,經過這個公式,能夠獲得每個葉子節點的增益(這個增益在預測的時候用的)
每一個增益的組成其實也是一個K維的向量,表示若是在決策樹預測的過程當中,若是某一個樣本點掉入了這個葉子節點,則其對應的K個分類的值是多少。好比說,GBDT獲得了三棵決策樹,一個樣本點在預測的時候,也會掉入3個葉子節點上,其增益分別爲(假設爲3分類的問題):
(0.5, 0.8, 0.1), (0.2, 0.6, 0.3), (0.4, 0.3, 0.3),那麼這樣最終獲得的分類爲第二個,由於選擇分類2的決策樹是最多的。
7. 的意思爲,將當前獲得的決策樹與以前的那些決策樹合併起來,做爲新的一個模型(跟6中所舉的例子差很少)
GBDT的算法大概就講到這裏了,但願可以彌補一下上一篇文章中沒有說清楚的部分:)
實現:
看明白了算法,就須要去實現一下,或者看看別人實現的代碼,這裏推薦一下wikipedia中的gradient boosting頁面,下面就有一些開源軟件中的一些實現,好比說下面這個:http://elf-project.sourceforge.net/
參考資料:
除了文章中的引用的內容(已經給出了連接)外,主要仍是參考Friedman大牛的文章:Greedy function approximation : A Gradient Boosting Machine