1、基本知識
1.1、名詞解釋
Boosting (提升)是一種將弱分類器組合起來形成強分類器的算法框架。
**參數估計:**在參數空間內進行數值優化(以參數作爲變量)
**函數估計:**在函數空間內進行數值優化(以函數作爲變量)
模型的含義:
假設我們的模型可以用下面的函數來表示,表示參數,可能有多個參數組成,,表示以P爲參數的x的函數。我們的模型是由多個模型疊加起來的,表示每個模型的權重,表示單個模型內部的參數。即
式中表示弱分類器,表示其他對應的權重。
我們的目標是:
,式中->表示趨近於,表示從屬性到目標函數的最優映射,最佳體現在滿足樣本集的分佈。
我們用表示P的likelihood(似然函數),似然函數與損失函數一樣都可作爲目標函數(這裏是以參數優化而非函數優化爲例)。
總體目標抽象爲似然函數期望最小化:
上面包含了boosting算法的三個要素
1)函數模型
Boosting的函數模型是疊加型的,
2)目標函數
選定某種損失函數作爲優化目標;$ \phi §]$
3)優化算法
貪婪地逐步優化,
1.2、數值優化在參數空間的基本流程(用梯度下降的思維來求解)
選擇一個參數化的模型(就是固定函數,來尋找參數使模型最優?),就將模型優化變成參數優化問題。
既然模型是可疊加的,對於參數P,我們也可以得到下面的式子:
這樣優化P的過程就可以是一個梯度下降的過程了。假如當前已經得到了個模型,想要得到第m個模型的時候,我們首先對前個模型求梯度,得到最快下降的方向。假如就是最快下降方向。
這裏有一個很重要的假設,對於求出的前個模型,我們認爲是已知的了,不要去改變它。我們的目標是放在之前模型的建立上。
我們得到的新模型就是,它在P似然函數的梯度方向。是在梯度方向上下降的距離。
我們最終可以通過優化下面的式子來得到最優的:
1.3、數值優化在函數空間的基本流程(用梯度下降的思維來求解)
上面通過參數P的可加性,得到了參數P似然函數梯度下降的方法。我們可以將參數P的可加性推廣到函數空間,得到下面的函數。此處的是上面的另一種表示。
同樣我們可以得到的梯度下降方向
最終可以得到第m個模型的表達式:
1.4、幾個關鍵點的解釋
1.爲什麼總體目標是求損失函數的期望?
損失函數,反映了模型與實際值之間的差距,其總和越小,表示模型對數據的擬合度越高,也反映了模型對數據分佈的擬合越好。
期望,是某變量的總體均值,是評估整體的一個有效指標。
2.爲什麼需要線性搜索?
線性搜索,可以保證下降方向上移動最大,是下降步幅的控制。
3.有限樣本與無限樣本
無限樣本下的期望是真實的反映;有限樣本則是近似;
4.F的理解
F 作爲模型函數,一直處於概念化的狀態。
其中在參數空間內優化的過程中,沒有明顯地體現,只是在參數P上體現了不斷累計的思想。
在函數空間內優化的過程中,則是表現爲最好的模型函數是由一點點的增量函數累計起來的。
5.模型評估策略的選擇
根據不同問題類型,可以有多重評估策略
迴歸問題:
可以選擇最小均方誤差策略[yi−F(xi)]2;
求導爲:gm(xi)=−[yi−Fm−1(xi)]
也可以選擇Least-squares|yi−F(xi)|;
求導得:gm(xi)=−sign[yi−Fm−1(xi)]
也可以選擇其他的策略等等。
分類問題:
logistic likelihood crit
1.5、boosting算法實例
將上述框架中的選爲決策樹,選爲指數損失函數,就可以得到adaboost,根據不同的loss function還可以有其他算法,比如L2Boosting, logitboost…
針對於這種提升方法而言,需要回答兩個問題,一是在每一輪如何改變訓練樣本的權值或概率分佈;二是如何將弱分類器組合成一個強分類器。Adaboost屬於Boosting一種,它可以很好的解決上述兩個問題,針對第一個問題,Adaboost的做法是提高那些被前一輪弱分類器錯誤分類樣本的權值,而降低那些被正確分類的樣本的權重。從而使得那些被錯誤分類的樣本由於其權值被加大而受到後一輪弱分類器的更多的關照(關注)。而針對第二個問題,Adaboost採取加權多數表決的方法,加大分類誤差率小的弱分類器的權重,使其在最終的分類器表決中起較大作用,減小分類誤差率大的弱分類器的權重,使其在表決中起較小的作用。總結起來,有兩個權重的概念,一個是增大錯誤分類樣本的權重,一個增大分類誤差率小的弱分類器的權重。
1.6、Gradient Boosting
來源
Gradient Boosting是一種Boosting方法的具體實現,其基本思想是每一次建立模型是在之前建立的模型梯度下降的方向。損失函數描述的是模型的不靠譜程度,損失函數值越大,說明模型的越容易出錯(其實這裏有一個方差、偏差的問題,但這裏假設,損失函數值越大越容易出錯)。如果我們的模型能夠讓損失函數持續的下降,那說明我們的模型在不斷地改進,其中的一種方式就是讓損失函數在梯度方向上下降。這一點還是比較好理解,我們在單一的算法中,如邏輯迴歸尋找模型最優參數的時候也是採用損失函數或似然值梯度下降的方向來不斷逼近最優模型參數。
對於模型的參數,我們可以用下面的式子來表示。這個式子的意思是,對於N個樣本點,,計算其在模型下的損失函數,最優的就是能使這個損失函數最小的。表示兩個m維的參數:
寫成梯度下降的方式就是下面的形式,也就是我們將要得到的模型的參數,能夠使得的方向是之前得到的模型的損失函數下降最快的方向:
對於每一個數據點都可以得到一個,最終我們可以得到一個完整梯度下降方向。
爲了使得能夠在的方向上,我們可以優化下面的式子得到,可以使用最小二乘法:
得到的基礎上可以得到。
最終合併到模型中:
算法的流程圖如下:
####1.6.1、Gradient Boosting 算法實現
https://blog.csdn.net/qq_36510261/article/details/78875278
https://www.kaggle.com/grroverpr/gradient-boosting-simplified/
http://bbs.pinggu.org/thread-3716235-1-1.html
下面是網上的一段代碼,初步探索了梯度下降提升算法的實現方向(代碼寫的比較差,最終梯度下降提升的功能也沒實現,但有這麼點意思在裏面)。
# -*- coding: utf-8 -*-
__author__ = 'mike-bowles'
import numpy
import matplotlib.pyplot as plot
from sklearn import tree
from sklearn.tree import DecisionTreeRegressor
from math import floor
import random
# Build a simple data set with y = x + random
nPoints = 1000
# x values for plotting
xPlot = [(float(i) / float(nPoints) - 0.5) for i in range(nPoints + 1)]
# x needs to be list of lists.
x = [[s] for s in xPlot]
# y (labels) has random noise added to x-value
# set seed
numpy.random.seed(1)
y = [s + numpy.random.normal(scale=0.1) for s in xPlot]
# take fixed test set 30% of sample
nSample = int(nPoints * 0.30)
idxTest = random.sample(range(nPoints), nSample)
idxTest.sort()
idxTrain = [idx for idx in range(nPoints) if not (idx in idxTest)]
# Define test and training attribute and label sets
xTrain = [x[r] for r in idxTrain]
xTest = [x[r] for r in idxTest]
yTrain = [y[r] for r in idxTrain]
yTest = [y[r] for r in idxTest]
# train a series of models on random subsets of the training data
# collect the models in a list and check error of composite as list grows
# maximum number of models to generate
numTreesMax = 30
# tree depth - typically at the high end
treeDepth = 5
# initialize a list to hold models
modelList = []
predList = []
eps = 0.3
# initialize residuals to be the labels y
residuals = list(yTrain)
for iTrees in range(numTreesMax):
modelList.append(DecisionTreeRegressor(max_depth=treeDepth))
modelList[-1].fit(xTrain, residuals)
# make prediction with latest model and add to list of predictions
latestInSamplePrediction = modelList[-1].predict(xTrain)
# use new predictions to update residuals
residuals = [residuals[i] - eps * latestInSamplePrediction[i] for i in range(len(residuals))]#各維度的誤差,後面並沒有使用到
latestOutSamplePrediction = modelList[-1].predict(xTest)
predList.append(list(latestOutSamplePrediction))#獲得各樹的預測結果。
# build cumulative prediction from first "n" models
mse = []
allPredictions = []
for iModels in range(len(modelList)):
# add the first "iModels" of the predictions and multiply by eps
prediction = []
for iPred in range(len(xTest)):
prediction.append(sum([predList[i][iPred] for i in range(iModels + 1)]) * eps)#第n次的預測值是其前n-1次預測值的之和再乘以eps
allPredictions.append(prediction)
errors = [(yTest[i] - prediction[i]) for i in range(len(yTest))]#某一次的預測誤差
mse.append(sum([e * e for e in errors]) / len(yTest))#利用均方根誤差整個預測的誤差。
nModels = [i + 1 for i in range(len(modelList))]
plot.plot(nModels, mse)
plot.axis('tight')
plot.xlabel('Number of Models in Ensemble')
plot.ylabel('Mean Squared Error')
plot.ylim((0.0, max(mse)))
plot.show()
plotList = [0, 14, 29]
lineType = [':', '-.', '--']
plot.figure()
for i in range(len(plotList)):
iPlot = plotList[i]
textLegend = 'Prediction with ' + str(iPlot) + ' Trees'
plot.plot(xTest, allPredictions[iPlot], label=textLegend,
linestyle=lineType[i])
plot.plot(xTest, yTest, label='True y Value', alpha=0.25)
plot.legend(bbox_to_anchor=(1, 0.3))
plot.axis('tight')
plot.xlabel('x value')
plot.ylabel('Predictions')
plot.show()
結果如下所示:
上面的代碼展示了對不同決策進行線性組合得到的新的預測結果與真實值之間的誤差可能會減小,也可能會增加。
那麼我們應該怎麼利用梯度下降來提升算法準確度呢?
觀察上面的誤差曲線能發現,當有些模型加進組合的時候,綜合誤差得到下降,但有些模型加進組合時,綜合誤差反而上升。我們應該選擇使誤差下降的模型。通過求誤差曲線的梯度(導數),在梯度爲負的地方,該模型我們應該選擇。
但是上面代碼簡單地將前n-1個模型的預測結果相加再乘以一個係數的做法是錯誤的。我們可以這樣考慮這個問題,假設各模型預測結果都不錯,接近真實值,組合預測值爲y_n,eps=0.3,那麼第一次組合預測的時候,預測結果爲,其值誤差自然就比較大;第二次組合預測時,預測結果爲,其誤差很可能減小,這樣我們就分不清是後面模型更好帶來的優化,還是組合值在接近真實值而帶來的優化;同樣可以想象,當模型增多,遠大於3個時,組合預測值必然會遠遠大於真實值而使誤差變大(圖中雖然不明顯,應該是數據特殊的問題)。
爲了對各模型公平,我認爲在組合計算時,應該使用各模型的加權平均值作爲預測值,並計算誤差,各誤差曲線的梯度。在梯度下降(導數爲負)處的模型做爲優質模型或權重得到加強,梯度上升處的模型應被削弱或剔除。
當然後續還可以進行其他的一些操作。
下次再來改寫這個程序。
1.6.2、Gradient Boosting 調參
https://blog.csdn.net/han_xiaoyang/article/details/52663170