加法模型,就是經過訓練集不斷的獲得不一樣的分類器(迴歸),而後將這些分類器組合成一個新的分類器的過程。算法
假設有\(N\)個樣本,且咱們的加法模型以下:
\[f(x)=\sum_{m=1}^M\beta_mb(x;\cal Y_m)\]
其中\(x\)爲自變量,即樣本;\(\cal Y_m\)爲第\(m\)個分類器的參數;\(b(x;\cal Y_m)\)爲分類器,也就是基函數;\(\beta_m\)爲該分類器的係數。app
能夠看出,在給定這樣一個加法模型的思路以及固定的訓練集後,咱們要作的就是最小化該模型的損失,即:
\[\min_{\beta_m,\cal Y_m}\sum_{i=1}^N\left(y_i,\sum_{m=1}^M\beta_mb(x_i;\cal Y_m)\right)\]
對於這樣一個模型,訓練的思路是:由於是個加法模型,因此能夠從前向後,每一步只學習一個分類器(即基函數)和係數,讓它逐步的逼近目標函數,直到達到咱們可以接受的偏差爲止。該方法也叫作前向分步算法。函數
前向分佈算法過程以下:
假設目前訓練集\(T={(x_1,y_1),(x_2,y_2),...(x_N,y_N)}\);損失函數\(L(y,f(x))\);分類器\({b(x;\cal Y)}\)。目標是獲得最後的加法模型\(f(x)\)。性能
1)獲得第一個分類器\(f_0(x)=0\)
2)對於\(m=1,2,...M\)學習
i)如數學概括法同樣,假設目前已經獲得了前\(m-1\)個分類器:
\[f(x)=f_{m-1}(x)=\sum_i^{m-1}\beta_ib(x;\cal Y_i)\]
那麼,對於第\(m\)個分類器的參數及係數求法:
\[(\beta_m,\cal Y_m)=arg\min_{\beta,\cal Y}\sum_{i=1}^NL\left(y_i,f_{m-1}(x_i)+\beta b(x_i;\cal Y)\right)\]
這樣就獲得了第\(m\)個分類器的參數和係數;
ii)而後更新舊加法模型,獲得新的加法模型:
\[f(x)=f_M(x)=\sum_{m=1}^M\beta_mb(x;\cal Y_m)\]
這樣,就是將整個模型轉換成了一步求得一個模型的參數和係數的優化問題上。優化
adaboost是加法模型的一個特例。假設目前有訓練集\(T=\{(x_1,y_1),(x_2,y_2),...,(x_N,y_N)\}\), 其中樣本都爲\(n\)維向量\(x_i\in\bf R^n\), 標籤\(y_i\in\{-1,+1\}\)spa
1)先設定初始時的訓練樣本的權值:
\[D_1 = (w_{11},...,w_{1i},...,w_{1N}),w_{1i}=\frac{1}{N},i=1,2,...N\]code
2)對\(m=1,2,...,M\),即有\(M\)個分類器,則:blog
i)使用具備權值分佈\(D_m\)的訓練集學習,獲得第\(m\)個基本分類器:
\[G_m(x):\rightarrow\{-1,+1\}\]ip
ii)而後計算基於當前分類器\(G_m(x)\)在訓練集上的分類偏差率:
\[e_m= P(G_m(x_i)\neq y_i)=\sum_{i=1}^Nw_{mi}I(G_m(x_i)\neq y_i)\]
ps:固然是選擇當前權值基礎上分類偏差率最低的那個分類器做爲當前分類器。因此實際上是經過ii)來肯定i)的分類器
iii)計算該分類器\(G_m(x)\)的係數:
\[\alpha_m=\frac{1}{2}log\frac{1-e_m}{e_m}\]
這裏對數是天然對數。
ps:能夠發現,當\(e_m\leq\frac{1}{2}\)時,\(\alpha_m\geq0\),而且\(\alpha_m\)隨着\(e_m\)的減少而增大,也就是分類偏差率越小的基本分類器在最終分類器中做用越大。
iv)更新訓練集的權值爲下一個分類器作準備:
ps:權值更新的式子能夠寫成以下形式:
\[w_{m+1,i}= \begin{cases} \frac{w_{mi}}{Z_m}e^{-\alpha_m},& G_m(x_i)=y_i\\ \frac{w_{mi}}{Z_m}e^{\alpha_m},& G_m(x_i)\neq y_i \end{cases}\]
能夠看出,當樣本分類正確時,其權值在變小,而當樣本分類錯誤時,其權值被放大,由此,誤分類樣本在下一輪學習中會起更大做用,也就是下一個分類器會更關注那些誤分類的樣本。
3)構建基本分類器的線性組合:
\[f(x)=\sum_{m=1}^M\alpha_mG_m(x)\]
獲得最終分類器:
\[G(x)=sign(f(x))=sign\left(\sum_{m=1}^M\alpha_mG_m(x)\right)\]
假設分類器是一個閾值分類器,即\(x>v,y=1\)和\(x<v,y=-1\),訓練集爲簡單的一維數據:
d1 = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] '''g1分類器,這裏是劃分點爲2.5''' def g1(x): return 1 if x < 2.5 else -1 y_prd = [g1(i) for i in x] # [1, 1, 1, -1, -1, -1, -1, -1, -1, -1] e = sum([d1i*(0 if y1 == y2 else 1) for y1,y2,d1i in zip(y,y_prd,d1)] ) # 0.3
i)由於當2.5時,錯誤率最低,則第一個分類器:
\[G_1(x)=\begin{cases} \quad1,&x<2.5\\ -1,&x>2.5 \end{cases}\]
ii)當前偏差率爲0.3
iii)計算第一個分類器係數:
\[\alpha_1=\frac{1}{2}log\frac{1-e_1}{e_1}=0.4236\]
iv)更新訓練集的權值分佈:
\(D_2=(w_{21},...,w_{2i},...w_{210})\)
\(w_{2i}=\frac{w_{1i}}{Z_1}exp(-\alpha_iy_iG_1(x_i)),i=1,2,...10\)
\(D_2=(0.0715,0.0715,0.0715,0.0715,0.0715,0.0715,0.1666,0.1666,0.1666,0.0715)\)
d1 = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] y = [1,1,1,-1,-1,-1,1,1,1,-1] z = [] '''g1分類器,這裏是劃分點爲2.5''' def g1(x): return 1 if x < 2.5 else -1 for ind,(d1Item,yItem) in enumerate(zip(d1,y)): w = d1Item*np.exp(-0.4236*yItem*g1(ind)) z.append(w) d2 = [ zItem/sum(z) for zItem in z ]
\(f_1(x)=0.4236G_1(x)\)
此時分類器\(sign[f_1(x)]\)當前誤分類3個\(\{7,8,9\}\);
d1 = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] '''g1分類器,這裏是劃分點爲2.5''' def g1(x): return 1 if x < 2.5 else -1 def f1(x): return 1 if 0.4236*g1(x) >0 else -1 y_prd = [ f1(i) for i in x] # [1, 1, 1, -1, -1, -1, -1, -1, -1, -1]
3)接着處理\(m=2\)時。
同上述方法計算每一個閾值\(v=\{1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5\}\)下分類偏差率
\(e_{0.5}=0.6428,錯分類樣本\{2,3,7,8,9\}\)
\(e_{1.5}=0.5713,錯分類樣本\{3,7,8,9\}\)
\(e_{2.5}=0.4998,錯分類樣本\{7,8,9\}\)
\(e_{3.5}=0.5713,錯分類樣本\{4,7,8,9\}\)
\(e_{4.5}=0.6428,錯分類樣本\{4,5,7,8,9\}\)
\(e_{5.5}=0.7143,錯分類樣本\{4,5,6,7,8,9\}\)
\(e_{6.5}=0.5477,錯分類樣本\{4,5,6,8,9\}\)
\(e_{7.5}=0.3811,錯分類樣本\{4,5,6,9\}\)
\(e_{8.5}=0.2145,錯分類樣本\{4,5,6\}\)
最低的分類器:
\[G_2(x)=\begin{cases} \quad1,&x<8.5\\ -1,&x>8.5 \end{cases}\]
i)此時偏差率爲0.2145
# 能夠看出當前樣本的權重值,其中通過第一次分類以後錯誤分類的權重變大 d2 = [0.0715,0.0715,0.0715,0.0715,0.0715,0.0715,0.1666,0.1666,0.1666,0.0715] x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] '''g2分類器,這裏是劃分點爲8.5''' def g2(x): return 1 if x < 8.5 else -1 y_prd = [ g2(i) for i in x] # [1, 1, 1, -1, -1, -1, -1, -1, -1, -1] # 計算預測值與實際值不相等的,即爲誤分類,將其乘以樣本權重,獲得偏差率 e = sum([d1i*(0 if y1 == y2 else 1) for y1,y2,d1i in zip(y,y_prd,d2)] ) # 0.2145
ii)係數爲0.6496
iii)訓練集權值分佈:
\(D_3=\{0.0455,0.0455,0.0455,0.1667,0.1667,0.1667,0.1060,0.1060,0.1060,0.0455\}\)
\(f_2(x)=0.4236G_1(x)+0.6496G_2(x)\)
iv)此時分類器\(sign[f_2(x)]\)訓練集上錯分類樣本仍是3個\(\{4,5,6\}\)
x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] d3 = [0.0455,0.0455,0.0455,0.1667,0.1667,0.1667,0.1060,0.1060,0.1060,0.0455] def g1(x): return 1 if x<2.5 else -1 def g2(x): return 1 if x<8.5 else -1 def f2(x): return 1 if (0.4236*g1(x) + 0.6496*g2(x)) > 0 else -1 y_prd = [ f2(i) for i in x] # [1, 1, 1, 1, 1, 1, 1, 1, 1, -1] isEqual = [1 if ypred == ygt else 0 for ypred,ygt in zip(y_prd, y)] # [1, 1, 1, 0, 0, 0, 1, 1, 1, 1]
4)如上述計算過程,第三輪獲得的分類器:
\[G_3(x)=\begin{cases} \quad -1,&x<5.5\\ 1,&x>5.5 \end{cases}\]
i)此時偏差率爲0.1820
d3 = [0.0455,0.0455,0.0455,0.1667,0.1667,0.1667,0.1060,0.1060,0.1060,0.0455] x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] '''g3分類器,這裏是劃分點爲5.5''' def g3(x): return -1 if x < 5.5 else 1 y_prd = [ g3(i) for i in x] # [-1, -1, -1, -1, -1, -1, 1, 1, 1, 1] # 計算預測值與實際值不相等的,即爲誤分類,將其乘以樣本權重,獲得偏差率 e = sum([d1i*(0 if y1 == y2 else 1) for y1,y2,d1i in zip(y,y_prd,d3)] ) # 0.182
ii)係數爲0.6496
iii)訓練集權值分佈:
\(D_4=\{0.125,0.125,0.125,0.102,0.102,0.102,0.065,0.065,0.065,0.125\}\)
\[f_3(x)=0.4236G_1(x)+0.6496G_2(x)+0.7514G_3(x)\]
x = [0,1,2,3,4,5,6,7,8,9] y = [1,1,1,-1,-1,-1,1,1,1,-1] def g1(x): return 1 if x<2.5 else -1 def g2(x): return 1 if x<8.5 else -1 def g3(x): return -1 if x<5.5 else 1 def f3(x): return 1 if (0.4236*g1(x) + 0.6496*g2(x) + 0.7514*g3(x)) > 0 else -1 y_prd = [ f3(i) for i in x] # [1, 1, 1, -1, -1, -1, 1, 1, 1, -1] isEqual = [1 if ypred == ygt else 0 for ypred,ygt in zip(y_prd, y)] # [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
4)如上述計算過程,第三輪獲得的分類器:
此時誤分類樣本爲0個,因此無需訓練所謂第四個基分類器。
最終分類器爲:
\[G(x)=sign[f_3(x)]=sign[0.4236G_1(x)+0.6496G_2(x)+0.7514G_3(x)]\]
提高樹是以迴歸樹或者分類樹做爲基本分類器的模型,被認爲統計學習中性能最好的方法之一(固然還有svm了)。
該類方法是採用了加法模型(基函數的線性組合)和前向分佈算法,用決策樹爲基函數的提高方法叫提高樹,分類問題 時,可採用二叉分類樹,迴歸問題時,可採用二叉迴歸樹。提高樹模型能夠表示爲決策樹的加法模型:
\[f_M(x)=\sum_{m=1}^MT(x;\Theta_m)\]
其中,\(T(x;\Theta_m)\)表示一棵決策樹;\(\Theta_m\)表示第\(m\)棵決策樹的參數;\(M\)爲樹的個數。
對於整個過程,如上面的加法模型同樣,先肯定初始提高樹\(f_0(x)=0\),而後第\(m\)輪以後,整個的模型:
\[f_m(x)=f_{m-1}(x)+T(x;\Theta_m)\]
其中\(f_{m-1}(x)\)是當前求得的模型,而後經過經驗風險最小化肯定下一棵決策樹的參數\(\Theta_m\):
\[\hat \Theta_m=arg\min_{\Theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_I)+T(x_i;\theta_m))\]
ps:由於樹的線性組合能夠很好的擬合訓練數據,即便數據中的輸入與輸出的關係很複雜也如此。因此提高樹是一個高功能的學習算法
一般來講,不一樣的提高樹學習算法,主要區別在於使用的損失函數:1)平方偏差損失函數的迴歸問題;2)指數損失函數的分類問題;3)通常損失函數的通常決策問題。
對於二類分類問題,即將adaboost中的基本分類器限制爲二類分類樹(即樹樁:一個根節點,兩個葉子節點)。這裏主要介紹迴歸問題的提高樹。
假設訓練集\(T=\{(x_1,y_1),(x_2,y_2),...,(x_N,y_N)\}\),且\(x_i\in \cal X \subseteq \bf R^n\),\(y_i\in \cal Y \subseteq \bf R\).對於一棵迴歸樹,若是將輸入空間劃分紅\(J\)個互不相交的區域\(R_1,R_2,...R_J\)而且在每一個區域上肯定輸出常量\(c_j\),那麼樹可表示爲:
\[T(x:\Theta)=\sum_{j=1}^Jc_jI(x\in R_j)\]
其中參數\(\Theta=\{(R_1,c_1),(R_2,c_2),...,(R_J,c_J)\}\)表示樹的區域劃分和各個區域上的常量輸出\(J\)表示迴歸樹的複雜度,即最終葉節點個數。
前向分步步驟:
假設訓練集\(T=\{(x_1,y_1),(x_2,y_2),...,(x_N,y_N)\}\),且\(x_i\in \cal X \subseteq \bf R^n\),\(y_i\in \cal Y \subseteq \bf R\)
1)初始化\(f_0(x)=0\)
2)對於輪數\(m=1,2,...,M\)
i)當第\(m\)步時,已知前\(m-1\)輪結果,須要求解:
\[\hat\Theta_m=arg\min_{\Theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\Theta_m))\]
獲得的\(\hat\Theta_m\)即爲第\(m\)棵樹的參數。當採用平方偏差損失函數時,:
\[L(y,f(x))=(y-f(x))^2\]
代入得:
\[\begin{eqnarray} L(y,f_{m-1}(x)+T(x:\Theta_m)) &=&[y-f_{m-1}(x)-T(x;\Theta_m)]^2\\ &=&[r-T(x;\Theta_m)]^2 \end{eqnarray}\]
其中\(r=y-f_{m-1}(x)\)是前\(m-1\)輪後獲得的模型擬合數據的殘差,因此對於迴歸問題的提高樹來講,就是擬合當前模型的殘差。
ii)對於每一個樣本\(i=1,...N\)
求得他們的殘差:
\[r_{mi}=y_i-f{m-1}(x_i),i=1,2,...N\]
iii)擬合這輪獲得的殘差\(r_{mi}\),基於整個訓練集學習一棵新的迴歸樹,獲得\(T(x;\Theta_m)\)
iv)更新\(f_m(x)=f_{m-1}(x)+T(x; \Theta_m)\)
3)獲得最後結果模型:
\[f_M(x)=\sum_{m=1}^MT(x;\Theta_m)\]
以下表數據:
X = [1,2,3,4,5,6,7,8,9,10] Y0 = [5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05] X_splits = [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5] def cost_split_point(ind,xs,YT): R1 = YT[:ind+1] R2 = YT[ind+1:] c1 = round(mean(R1),3) c2 = round(mean(R2),3) ans0 = [(x-c1)*(x-c1) for x in R1] ans1 = [(x-c2)*(x-c2) for x in R2] return [sum(ans0+ans1), c1, c2] cost = [[xs]+cost_split_point(ind,xs,Y0) for ind,xs in enumerate(X_splits)] #[[1.5, 15.723, 5.559, 7.501], # [2.5, 12.083, 5.629, 7.726], # [3.5, 8.365, 5.723, 7.985], # [4.5, 5.775, 5.892, 8.25], # [5.5, 3.911, 6.073, 8.540], # [6.5, 1.930, 6.236, 8.912], # [7.5, 8.009, 6.617, 8.916], # [8.5, 11.735, 6.877, 9.025], # [9.5, 15.738, 7.113, 9.050]]
2)計算\(f_1(x)\)擬合訓練集的殘差計算公式\(r_{2i}=y_i-f_1(x_i),i=1,2,...,10\)
r_2i = [-0.68, -0.54, -0.33, -0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14] r_2i = np.array(r_2i) loss = (r_2i*r_2i).sum()#1.9301
3)在計算新的迴歸樹時,選擇的訓練集是圖3.1.3 而不是原來的3.1.1,便是基於上一輪模型結果以後的殘差。從而獲得這一輪的迴歸樹:
\[T_2(x)=\begin{cases} -0.52,& x<3.5\\ 0.22,&x\geq3.5 \end{cases}\]
Y1 = [-0.68, -0.54, -0.33, 0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14] cost = [[xs]+cost_split_point(ind,xs,Y1) for ind,xs in enumerate(X_splits)] #[[1.5, 1.417, -0.680, 0.073], # [2.5, 1.002, -0.609, 0.151], # [3.5, 0.790, -0.517, 0.22], # [4.5, 1.129, -0.347, 0.230], # [5.5, 1.657, -0.166, 0.164], # [6.5, 1.930, -0.003, 0.003], # [7.5, 1.929, -0.004, 0.007], # [8.5, 1.896, -0.029, 0.115], # [9.5, 1.908, -0.017, 0.140]]
在獲得這一輪的迴歸樹以後,將前面獲得的模型與當前模型相加,且重合區域須要注意相加減,如當\(x<3.5\)時,\(f_2(x)=-0.52+6.24=5.72\):
\[f_2(x)=f_1(x)+T_2(x)=\begin{cases} 5.72,& x<3.5\\ 6.46,& 3.5\leq x<6.5\\ 9.13,& x\geq 6.5 \end{cases}\]
用\(f_2(x)\)擬合訓練集損失爲\(L(y,f_2(x))=\sum_{i=1}^{10}(y_i-f_2(x_i))^2=0.79\)
如此獲得最後結果:
\[f_6(x)=f_5(x)+T_6(x)=\begin{cases} 5.63,& x<2.5\\ 5.82,& 2.5\leq x<3.5\\ 6.56,& 3.5\leq x<4.5\\ 6.83,& 4.5\leq x <6.5\\ 8.95,&x \geq6.5 \end{cases}\]
當前模型擬合訓練集平方損失爲0.17.假設此時偏差已經知足要求,那麼就能夠將\(f_6(x)\)做爲整個訓練集的提高樹
當提高樹中選取的損失函數是平方損失和指數損失函數時,訓練過程如上述所屬,但是當通常損失函數而言,優化相對就較爲麻煩了,這時候能夠用freidma提出的gradient boosting算法,這是與最速降低法類似的方法,使用了損失函數的負梯度:
\[r_{mi}=-\left[\frac{\rm dL(y,f(x_i))}{\rm df(x_i)}\right]_{f(x)=f_{m-1}(x)}\]
將其做爲3.1中每一輪計算的平方損失殘差值,即這一輪所謂的"訓練集"
其餘部分的計算不變。
參考資料:
[] 李航,統計學習方法
2017/04/07 第一次修改!