長文詳解自然語言處理演算法xgboost和python實戰
|小修很早就想總結一下xgboost的內容,但是每次看到一大堆公式就頭大,而且網上很多資料很多都不全,下文第一部分是根據xgboost的官方中文文檔編寫的。純粹是總結學習,如有侵權還請告知。
xgboost是大規模並行boosted tree的工具,它是目前最快最好的開源boosted tree工具包,比常見的工具包快10倍以上。在數據科學方面,有大量的kaggle選手選用它進行數據挖掘比賽,它也是大家常用的一種處理自然語言的演算法,在有些情況下,xgboost甚至能夠比神經網路的結果要好(小修之前測試過各種模型對一特定文本語言分類的性能)。在工業界規模方面,xgboost的分散式版本有廣泛的可移植性,支持很多平台運行,並且保留了單機並行版本的各種優化,使得它可以很好地解決於工業界規模的問題。
1
Boosted Trees 介紹
XGBoost是「Extreme Gradient Boosting」的縮寫,這裡使用監督學習的元素以獨立和有原則的方式解釋boosted trees (增強樹)。
監督學習的要素
這裡先從XGBoost用於監督學習問題開始, 假設訓練數據xi,目標變數為yi。這裡先回顧一下監督學習的重要組成部分。
模型和參數
監督學習中的模型通常是指給定輸入xi如何去預測輸出yi的數學結構,例如一個常見的模型是線性回歸,其中的預測是由yi= sum(wjxij)的方式給出,這是加權輸入特徵的線性組合疊加的方式。其實這裡的預測y可以有不同的解釋,取決於做的任務。線性回歸中,係數w為該模型的參數,一般是需要從數據中學習的未確定的部分。
目標函數:訓練損失+正則
基於對yi的不同理解,我們可以得到不同的問題,比如回歸,分類,排序等,我們需要找到一種方法來找到訓練數據的最佳參數,為了做到這一點,需要定義一個目標函數,以給定一組數據來衡量模型的性能。對於目標函數,一般包含訓練損失函數以及正則化項,。一般目標函數如下式所示:
其中L是訓練損失函數,後面一項為正則化項,目標函數和各項都是參數的函數,訓練損失衡量的是數據對訓練數據的預測性,比如常用的訓練損失函數就是預測結果和目標結果的均方誤差,另一個常用的損失函數是logistic回歸的損失函數:
正則化項是使用者通常忘記添加的部分,正則化項控制模型的複雜度,有助於避免過擬合,比如下面一圖對於在不同的損失函數和正則化項下,對數據點的擬合結果。
對於線性模型常見的正則化有L2正則和L1正則,這樣的目標函數的設計來自於統計學習中的一個重要概念,就是偏差-方差的權衡(bias-variance tradeoff),其中偏差可以理解為假設我們有無限多數據的時候,可以訓練出最好的模型所拿到的誤差,而方差是因為只有有限數據的隨機性帶來的誤差,目標中的誤差函數是為了讓模型儘可能去擬合訓練數據,這樣可以得到一個比較小偏差的模型,而正則化項則鼓勵更加簡單的模型,因為模型簡單之後,有限數據擬合出來的結果隨機性比較小,不易過擬合,使得最後模型的預測更加穩定。
Tree ensembles (樹集成)
上文介紹的都是監督學習的基本內容,下面來介紹關於xgboost的模型部分:樹集成。樹集成模型是一組classification and regression trees (CART)(分類回歸樹)。下面是一個簡單的例子,它可以分類是否有人喜歡電腦。
把一個家庭的成員分成不同的葉子,並把他們分配到相應的葉子節點上,CART與決策樹有些不同,就是葉子包含決策值,在CART中,每個葉子都有一個真實的分數,這樣就超越了簡單的分類。通常情況下,單顆樹由於過於簡單而不夠強大到可以支持在實踐中使用,實際使用的是所謂的樹集成模型,它將多棵樹的預測加到一起。
上圖示兩個樹集成的例子,將每棵樹的預測分數加起來得到最終的分數,如果你看一下這個例子,一個重要的事實就是兩棵樹互相補充,在數學上表示,可以表示為下式所描述的模型:
其中K是樹的數量,f是函數空間F的函數,F是所有可能的CARTs的集合,所以我們的優化目標可以寫成下式所示:
這裡需要點出的是隨機森林(random forests)的模型就是樹集成,所以隨機森林和增強樹(boosted trees)在模型沒有什麼不同。不同之處只是在於我們如何訓練它們,這意味著如果寫一個樹集成的預測服務,你只需要編寫它們中的一個,它們應該直接為隨機森林和增強樹工作,這也是監督學習基石元素的一個例子。
Tree Boosting
在介紹完模型之後,這裡介紹如何去訓練學習樹,按照一般監督學習模型的處理思路,需要定義一個合理的目標函數,然後嘗試去優化這一目標函數。
這裡假設有如下所示的目標函數,當然它是需要飽含訓練損失和正則化的:
另外還有一個問題,為了每一步選擇一個好的樹,就需要添加一個優化目標的方法:
如果使用均方誤差作為損失函數,它將是下面的形式:
均方誤差的形式比較友好,具有一階項(通常稱為殘差)和二次項,對於其他形式的損失,獲得這麼好的形式並不是那麼容易,所以在一般情況下,我們把損失函數的泰勒展開到二階
其中gi和hi的定義為:
我們刪除了所有的常量之後,t步驟中的具體目標就變成了:
這成為了新樹的優化目標,這個定義的一個重要優點是它只依賴於gi和hi,這就是xgboost如何支持自定義損失函數,我們可以使用完全相同的i和hi作為輸入的求解器來對每個損失函數進行優化,包括邏輯回歸(logistic regression),權重邏輯回歸(weight logistic regression)。
模型複雜度
我們已經介紹了訓練步驟,但是我們還需要定義樹的複雜度,這裡首先改進一棵樹的定義f(x) 如下:
這裡w是樹葉上的分數向量,q是將每個數據點分配給葉子的函數,T是樹葉的數量,在XGBoost中,我們將複雜度定義為:
當然有不止一種方法來定義複雜度,但是這個具體的方法在實踐中運行良好,正則化是大多樹的包容易忽略的一部分,這是因為傳統的樹學習演算法的只強調提高不純性(impurity),而複雜度控制則是啟發式的。
The structure score (結構分數)
這是derivation的神奇部分,在對樹模型進行重新格式化之後,我們可以用第t棵樹來編寫目標值:
其中Ii= 是分配給第j個葉子的數據點的索引集合,需要注意的是,在第二行中,我們改變了總和的索引,因為同一葉子上的所有數據點都得到了相同的分數,我們可以通過定義Gj和Hj來近一步壓縮表達式:
在這個等式中wj是相互獨立的,形式Gjwj+1/2(Hj + lamda)wj*wj是二次的,對於給定的結構q(x)的最好的wj,我們可以得到最好的客觀規約:
最後一個方程度量一個結構q(x)到底有多好
這一切看起來有些複雜,可以看一下上面的圖片,看看分數是如何計算的,基本上,對於一個給定的樹結構,我們把統計gi和hi推到它們所屬的葉子上,統計數據加和到一起,然後使用公式計算樹是多好,除了考慮到模型的複雜度,這個分數就像決策樹中的雜質測量一樣(例如:熵和Gini係數)。
學習樹結構
既然有來一個方法來衡量一棵樹有多好,理想情況下我們會列舉所有可能的樹並挑選出最好的樹,在實踐中,這種方法是比較棘手的,所以我們會盡量一次優化樹的一個層次,具體來說,我們試圖將一片葉子分成兩片,並得到分數(這裡使用Gini係數):
這個公式可以分解為1)新左葉上的得分,2)新右葉上得分,3)原始葉子上的得分,4)附加葉子上的正則化,我們可以在這裡看到一個重要的事實:如果增益小於gamma,我們最好不要添加那個分支,這正是基於樹模型的剪枝技術。對於真實有價值的數據,通常需要尋找一個最佳的分割,為了有效地做到這一點,我們把所有的實例按照排序順序排列,如下圖所示:
從左到右的掃描就足以計算所有可能的拆分解決方案的結構得分,我們可以有效找到最佳的拆分。
2
xgboost的安裝
1.xgboost的安裝有一些依賴包,所以在安裝xgboost之前需要安裝這些依賴包,為了方便安裝,這裡推薦直接安裝anaconda,這裡面集成了絕大多數的第三方庫.
2.xgboost可以在官網上下載,下載下來
3: 這裡以liunix系統安裝過程為例子介紹安裝過程:
首先需要檢查linux系統是不是安裝了gcc-c++,檢查命令為:
rpm -qa grep gcc
如果發現沒有安裝可以使用如下命令安裝:
yum install gcc-c++
確認gcc-c++已經安裝之後,可以開始編譯和安裝工作了,然後進入到下載的xgboost的文件夾中使用下面的命令進行:
make
cd python-package
python setup.py install --user
最後驗證,在終端中輸入python,進入python編譯器,輸入import xgboost,如果沒有報錯,則按裝成功。
3
python實踐xgboost:對文本進行分類
這裡我只給出xgboost_model的核心代碼,如下所示,至於xgboost_model的參數可以根據之前小修介紹的jieba分詞和Tfidf獲取每條文本去獲取訓練文本和測試文本的weight:
在頭文件中需要包含: import xgboost as xgb.
這裡介紹xgboost中的一些參數,當然一些參數可以對照第一部分的內容進行理解:
xgboost所有的參數可以分為三類: 1. 通用參數:宏觀函數控制,2. Booster參數: 控制每一步的booster, 3. 學習目標參數:控制訓練目的的表現。
1: 通用參數:
booster [默認是gbtree]:gbtree基於樹的模型,gbliner為基於線性模型
silent[默認為0]:值為1時,靜默模式開啟,不會輸出任何信息
nthread[默認值為最大可能的線程數]:這個參數用來進行多線程式控制制,應當輸入系統的核數,
2: booster參數
這裡只介紹tree booster的,因為它的表現遠勝於linear booster,所以linear booster一般很少用
eta[默認0.3]:類似於learning rate參數,通過減少每一步的權重,可以提高模型的魯棒性,常用的值為0.2,0.3
max_depth[默認6]:這個值為樹的最大深度,max_depth越大,模型會學到更具體更局部的樣本,常用的為6.
gamma[默認為0]: gamma為指定了節點分裂所需要的最小損失函數下降值,這個參數的值越大,演算法越保守,這個參數的值和損失函數息息相關。
subsample[默認為1]:這個參數控制對於每棵樹,隨機採樣的比例,減少這個參數的值,演算法會更加保守,避免過擬合,但是如果這個值設置的過小,它可能會導致前擬合,常用的值為0.7-1
colsample_bytree[默認1]:用來控制每棵樹隨機採用列數的佔比,常用是0.7-1。
3: 學習目標參數
objective[默認reg:linear]:這個參數定義需要被最小化的損失函數,binary:logistic 而分類的邏輯回歸,返回預測的概率,multi:softmax使用softmax的多分類器,返回預測的類別,這種情況下,還需要多設一個參數: num_class(類別數目)。multi: softprob 和multi: softmax參數一樣,但是返回的是每個數據屬於各個類別的概率。
eval_metric[默認取決於objective參數的取值]:對於有效數據的度量方法,對於回歸問題,默認是rmse,對於分類問題,默認值是error,其他的值:rmse均方根誤差,mae平均絕對誤差,logloss負對數似然函數值,error二分類錯誤率,merror為多分類錯誤率,auc為曲線下面積。
seed[默認0]:隨機樹的種子,設置可以復現隨機數據的結果。
參考內容:
[1] http://xgboost.apachecn.org/cn/latest/model.html
自然語言處理技術
關注微信號每天收聽我們的消息
自然語言處理技術為您推送精品閱讀
每天一個知識點,健康生活每一天
歡迎關注公眾號學習交流
※自然語言處理之中文分詞器-jieba分詞器詳解及python實戰
TAG:自然語言處理技術 |