樹系列(四)boosting_tree

  • 模型

    採用加法模型和前向分步算法,以決策樹爲基函數的提升方法被稱爲提升樹,由如下公式表示,

    fM(x)=m=1MT(x;θM)

    T(x;θM) 表示決策樹,θM 表示決策樹的參數,M爲樹的個數,
  • 迴歸核心思想

    上面公式採用前向分步算法的步驟如下,

    首先確定初始提升樹f0(x)=0 , 第m步的模型是,

    fm(x)=fm1(x)+T(x;θm)

    確定下一棵決策樹的參數的方法如下,

    θm^=argminθmi=1NL(yi,fm1(xi)+T(xi;θm))

    通過找到合適的參數,從而得到合適的提升樹模型,而採用何種損失函數便成爲提升樹學習算法的核心內容,

    對於迴歸問題的提升樹,某棵樹對於某個樣本xj 的預測值如下,J爲這棵樹的葉子節點的個數,具體如何理解,請見決策樹的解釋,

    T(x;θ)=j=1JcjI(xRj)

    每棵樹構建好之後對於前向分步算法的應用如下,

    f0(x)=0

    fm(x)=fm1(x)+T(x;θm)m=1,2,...,M

    fM(x)=m=1MT(x;θm)

    第m步中,給定fm1(x) ,需求解如下公式得到θm^ ,
    θm^=argminθmi=1NL(yi,fm1(xi)+T(xi;θm))

    如果採用平方差損失函數,

    L(y,f(x))=(yf(x))2

    其損失變爲

    L(y,fm1(x)+T(x;θm))

    =[yfm1(x)T(x;θm)]2

    =[rT(x;θm)]2

    這裏r=yfm1(x) ,表示模型擬合的是數據的殘差,


    輸入:訓練數據集T={(x1,y1),...,(xN,yN)} , xiXRn,yiYR ,

    輸出:提升樹fM(x)

    1. 初始化f0(x)=0
    2. 對於m=1,2,…,M
      1. 計算殘差rmi=yifm1(xi),i=1,2,...,N
      2. 擬合殘差學習迴歸樹,得到T(x;θm)
      3. 更新fm(x)=fm1(x)+T(x;θm)
    3. 得到提升樹

    fM(x)=m=1MT(x;θM)

  • 梯度提升

    上述算法求解的核心在於對於模型的損失函數是平方損失的,求解很簡單,但是對於一般的損失函數來說,每一步的優化並不是很容易,因而把損失函數的負梯度值作爲每個階段迴歸的目標去擬合一棵迴歸樹纔是一個比較理想的選擇,負梯度公式如下,

    rmi=[L(y,f(x))f(x)]f(x)=fm1(x)

    輸入: 輸入數據集T={(x1,y1),(x2,y2),...,(xN,yN)}xiXRn,yiYR , 損失函數L(y,f(x)) ,

    輸出: 迴歸樹f(x)^

    1. 初始化

    f0(x)=argminci=1NL(yi,c)
    1. 對於m=1,2,..,M,

      a.對於i=1,2,…,N,計算

      rmi=[L(y,f(x))f(x)]f(x)=fm1(x)

      使得

      fm(xi)=fm1(xi)+rmi

      值得注意的是從這個公式可以看出階段與階段之間傳遞的是方法,而不是數據,第m輪從第m-1輪得到的是fm1(x) ,而不是fm1(xi)

      1. 對於rmi , 擬合一個迴歸樹,得到第m棵樹的葉節點區域Rmj,j=1,2,...,J ,
      2. 對於j=1,2,..,J,計算

      cmj=argmincxiRmjL(yi,fm1(xi)+c)

      這裏等式最後的c表示的是所有落在第m棵數的第j個葉節點的數據都取同一個值c,找到這個c,使得整體的損失最小,這時用到的方法是線性搜索的方法得到最優值,
      1. 更新fm(x)=fm1(x)+j=1JcmjI(xRmj)
    2. 得到迴歸樹

    f(x)^=fM(x)=m=1Mj=1JcmjI(xRmj)

    上述算法計算梯度的過程叫做有一個問題,如果基學習器太少,容易導致跨越最優解的情況,在最速下降法中不可避免的會利用到學習率,這裏也可採用添加學習率的方法,增大提升樹中基學習器的數量來提升性能,

    fm(x)=fm1(x)+νhm(x),0<ν1

    上式的ν 即是上文提到的學習率,學習率越小,提升樹中基學習器的數量會變多,從而更加精細的逼近最優解,其缺點很明顯,收斂比較慢,但不會發生震盪,

    這裏舉一個比較通俗易懂的例子來加深理解,

    可以假設一個場景,如果你要走一條路,到達終點,但是你並不知道終點的具體方向在哪,首先你需要選擇一共要走多少步,確定走多少步的過程就是確定學習率的過程,而後開始走第一步,在走第一步的時候有個高人告訴你終點大概方向是什麼樣的,這即是梯度方向,且第一步走多大最合適,這是梯度的大小,這個時候你就根據這個高人的指點走出重要的一步而後再去詢問那個高人,高人又會指一條明路,而後一直重複上述過程,直到走到終點,

    還是上面的那個例子,如果每步走的太大,就有可能出現走過了的風險,那麼這個時候就看出來步子小的好處了,步子小不怕,多走幾步就是了,這樣就沒有上述提到的風險了,

  • 分類核心思想

    分類問題還不是很清楚,需要繼續查詢,更新文檔,

    • 二分類

      這裏需要說明的一點是我還不太清楚分類問題參數的初始化,暫且定義初始化爲0

      分類問題是迴歸問題的變形,與迴歸問題不同的一點是分類問題用到的損失函數是對數損失函數(logistic loss), 下面是對對數損失函數的解釋,


      對於二項分佈,y{0,1} , 定義預測概率爲p(x)=P(y=1) , 而損失函數可定義爲

      L(y,p(x))={log(p(x)),ify=1log(1p(x)),ify=0

      合併起來寫爲

      L(y,p(x))=ylog(p(x))(1y)log(1p(x))

      這就是所謂的對數損失函數,


      之後的算法和gbdt迴歸樹的思想大同小異,

    • 多分類

      在多分類問題中,假設有k個類別,那麼每一輪迭代實質是構建了k棵樹,對某個樣本x的預測值爲

      f1(x),f2(x),...,fk(x)

      在這裏我們仿照多分類的邏輯迴歸,使用softmax來產生概率,

      pc=exp(fc(x))/i=1kexp(fi(x))

      而後在計算損失時採用的依然是對數損失函數,並對f1...fk 都可以算出一個梯度,f1...fk 便可以計算出當前輪的殘差,供下一輪迭代學習。最終做預測時,輸入的x會得到k個輸出值,然後通過softmax獲得其屬於各類別的概率即可,

      每個階段對於k棵數,總共m個階段,樹的總數爲km,

  • 拓展之細節

    • 梯度提升 adaboost

      adaboost和GBDT的相同之處:gbdt計算殘差這一步相當於給每個樣本賦予權重,因爲一輪內計算的殘差絕對值越大,負梯度的方向會整體更偏向它的方向,相當於迴歸任務更偏向於它這一方,這樣才能讓這個殘差較大的預測結果和真實值更加正確,這樣才能夠保證整體的誤差最小,這樣間接的就給每個樣本賦予權重了,殘差越大,賦予的權重就越大,

    • 樣本選擇 subsample

      提升樹中每個基學習器的訓練樣本是整體訓練樣本的一部分,subsample參數決定了這個比例,這提高了模型的泛化能力,有效防止過擬合,

      注意這裏的子採樣和隨機森林不一樣,隨機森林使用的是放回抽樣,而這裏是不放回抽樣即一次從原始數據中取出一部分數據進行訓練。如果取值爲1,則全部樣本都使用,等於沒有使用子採樣。如果取值小於1,則只有一部分樣本會去做GBDT的基學習器擬合。選擇小於1的比例可以減少方差,即防止過擬合,但是會增加樣本擬合的偏差,因此取值不能太低。推薦在[0.5,0.8]之間,默認是1.0,即不使用子採樣,

    • 實際調參技巧

      先設定一個basemodel,評估basemodel的性能

      再去固定learning_rate, 找到最合適的樹的棵數,這個的前提是固定boosting參數,

      調節樹參數 (注意調參順序)

      max_depth + num_samples_split

      min_samples_leaf

      max_features

      調節子樣本比例來降低learning rate, 相應的提高樹的棵數,(樹的棵數增長倍數是learning_rate的降低倍數)

  • 拓展之與決策樹比較

    提升樹模型效果好的核心在於每棵樹都能夠找到當前全局最優解,且每棵樹的最優解都更加逼近真實解,而決策樹只又一次機會逼近全局最優解,那就是在根節點選擇特徵時,因而這樣建立的模型有過擬合的風險,下面的例子就能夠很好地解釋這一點,


    假設我們現在有一個訓練集,訓練集只有4個人,A,B,C,D,他們的年齡分別是14,16,24,26。其中A、B分別是高一和高三學生;C,D分別是應屆畢業生和工作兩年的員工。如果是用一棵傳統的迴歸決策樹來訓練,會得到如下圖所示,
    image

    現在我們使用GBDT來做這件事,由於數據太少,我們限定葉子節點做多有兩個,即每棵樹都只有一個分枝,並且限定只學兩棵樹。我們會得到如下圖所示結果,

    image

    在第一棵樹分枝和圖1一樣,由於A,B年齡較爲相近,C,D年齡較爲相近,他們被分爲兩撥,每撥用平均年齡作爲預測值。此時計算殘差,所以A的殘差就是14-15=-1(注意,A的預測值是指前面所有樹累加的和,這裏前面只有一棵樹所以直接是15,如果還有樹則需要都累加起來作爲A的預測值)。進而得到A,B,C,D的殘差分別爲-1,1,-1,1。然後我們拿殘差替代A,B,C,D的原值,到第二棵樹去學習,如果我們的預測值和它們的殘差相等,則只需把第二棵樹的結論累加到第一棵樹上就能得到真實年齡了。這裏的數據顯然是我可以做的,第二棵樹只有兩個值1和-1,直接分成兩個節點。此時所有人的殘差都是0,即每個人都得到了真實的預測值。

    最後GBDT的預測結果爲:

    A: 14歲高一學生,購物較少,經常問學長問題;預測年齡A = 15 – 1 = 14;

    B: 16歲高三學生;購物較少,經常被學弟問問題;預測年齡B = 15 + 1 = 16;

    C: 24歲應屆畢業生;購物較多,經常問師兄問題;預測年齡C = 25 – 1 = 24;

    D: 26歲工作兩年員工;購物較多,經常被師弟問問題;預測年齡D = 25 + 1 = 26。

    那麼哪裏體現了Gradient呢?其實回到第一棵樹結束時想一想,無論此時的cost function是什麼,是均方差還是均差,只要它以誤差作爲衡量標準,殘差向量(-1, 1, -1, 1)都是它的全局最優方向,這就是Gradient。

    注:上面兩圖最終效果相同,爲何還需要GBDT呢?答案是過擬合。只要允許一棵樹的葉子節點足夠多,訓練集總是能訓練到100%準確率的。在訓練精度和實際精度(或測試精度)之間,後者纔是我們想要真正得到的。我們發現圖1爲了達到100%精度使用了3個feature(上網時長、時段、網購金額),其中分枝“上網時長>1.1h” 很顯然已經過擬合了,這個數據集上A,B也許恰好A每天上網1.09h, B上網1.05小時,但用上網時間是不是>1.1小時來判斷所有人的年齡很顯然是有悖常識的;相對來說圖2的boosting雖然用了兩棵樹 ,但其實只用了2個feature就搞定了,後一個feature是問答比例,顯然圖2的依據更靠譜。
    可見,GBDT同隨機森林一樣,不容易陷入過擬合,而且能夠得到很高的精度。

    因而從上面例子可知,GBDT的每棵樹都在迴歸全局最優解,且隨着迭代次數的增加,需要回歸的全局最優解不斷地逼近0,即殘差不斷地逼近0,因而GBDT中所有的樹的訓練結果的加和不斷逼近真實解,


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