LightGBM——提升機(jī)器算法(圖解+理論+安裝方法+python代碼)
https://blog.csdn.net/huacha__/article/details/81057150
前言
LightGBM是個(gè)快速的,分布式的,高性能的基于決策樹算法的梯度提升框架。可用于排序,分類,回歸以及很多其他的機(jī)器學(xué)習(xí)任務(wù)中。
在競(jìng)賽題中,我們知道XGBoost算法非常熱門,它是一種優(yōu)秀的拉動(dòng)框架,但是在使用過(guò)程中,其訓(xùn)練耗時(shí)很長(zhǎng),內(nèi)存占用比較大。在2017年年1月微軟在GitHub的上開源了一個(gè)新的升壓工具--LightGBM。在不降低準(zhǔn)確率的前提下,速度提升了10倍左右,占用內(nèi)存下降了3倍左右。因?yàn)樗腔跊Q策樹算法的,它采用最優(yōu)的葉明智策略分裂葉子節(jié)點(diǎn),然而其它的提升算法分裂樹一般采用的是深度方向或者水平明智而不是葉,明智的。因此,在LightGBM算法中,當(dāng)增長(zhǎng)到相同的葉子節(jié)點(diǎn),葉明智算法比水平-wise算法減少更多的損失。因此導(dǎo)致更高的精度,而其他的任何已存在的提升算法都不能夠達(dá)。與此同時(shí),它的速度也讓人感到震驚,這就是該算法名字 燈 的原因。
-
2014年3月,XGBOOST最早作為研究項(xiàng)目,由陳天奇提出 (XGBOOST的部分在我的另一篇博客里: -
2017年1月,微軟發(fā)布首個(gè)穩(wěn)定版LightGBM 在微軟亞洲研究院AI頭條分享中的「LightGBM簡(jiǎn)介」中,機(jī)器學(xué)習(xí)組的主管研究員王太峰提到:微軟DMTK團(tuán)隊(duì)在github上開源了性能超越其它推動(dòng)決策樹工具LightGBM后,三天之內(nèi)星了1000+次,叉了超過(guò)200次。知乎上有近千人關(guān)注“如何看待微軟開源的LightGBM?”問(wèn)題,被評(píng)價(jià)為“速度驚人”,“非常有啟發(fā)”,“支持分布式” “代碼清晰易懂”,“占用內(nèi)存小”等。以下是微軟官方提到的LightGBM的各種優(yōu)點(diǎn),以及該項(xiàng)目的開源地址。
**科普鏈接:**如何玩轉(zhuǎn)LightGBM https://v.qq.com/x/page/k0362z6lqix.html
目錄
一、"What We Do in LightGBM?"
下面這個(gè)表格給出了XGBoost和LightGBM之間更加細(xì)致的性能對(duì)比,包括了樹的生長(zhǎng)方式,LightGBM是直接去選擇獲得最大收益的結(jié)點(diǎn)來(lái)展開,而XGBoost是通過(guò)按層增長(zhǎng)的方式來(lái)做,這樣呢LightGBM能夠在更小的計(jì)算代價(jià)上建立我們需要的決策樹。當(dāng)然在這樣的算法中我們也需要控制樹的深度和每個(gè)葉子結(jié)點(diǎn)的最小數(shù)據(jù)量,從而減少過(guò)擬合。
小小翻譯一下,有問(wèn)題還望指出
**XGBoost****LightGBM** 樹木生長(zhǎng)算法 **按層生長(zhǎng)的方式** 有利于工程優(yōu)化,但對(duì)學(xué)習(xí)模型效率不高 直接**選擇最大收益的節(jié)點(diǎn)**來(lái)展開,在更小的計(jì)算代價(jià)上去選擇我們需要的決策樹 控制樹的深度和每個(gè)葉子節(jié)點(diǎn)的數(shù)據(jù)量,能減少過(guò)擬合有利于工程優(yōu)化,但對(duì)學(xué)習(xí)模型效率不高
控制樹的深度和每個(gè)葉子節(jié)點(diǎn)的數(shù)據(jù)量,能減少過(guò)擬合
劃分點(diǎn)搜索算 法對(duì)特征預(yù)排序的方法直方圖算法:將特征值分成許多小筒,進(jìn)而在筒上搜索分裂點(diǎn),減少了計(jì)算代價(jià)和存儲(chǔ)代價(jià),得到更好的性能。另外數(shù)據(jù)結(jié)構(gòu)的變化使得在細(xì)節(jié)處的變化理上效率會(huì)不同 內(nèi)存開銷8個(gè)字節(jié)1個(gè)字節(jié) 劃分的計(jì)算增益數(shù)據(jù)特征容器特征 高速緩存優(yōu)化無(wú)在Higgs數(shù)據(jù)集上加速40% 類別特征處理無(wú)在Expo數(shù)據(jù)集上速度快了8倍二、在不同數(shù)據(jù)集上的對(duì)比
higgs和expo都是分類數(shù)據(jù),yahoo ltr和msltr都是排序數(shù)據(jù),在這些數(shù)據(jù)中,LightGBM都有更好的準(zhǔn)確率和更強(qiáng)的內(nèi)存使用量。
準(zhǔn)確率
內(nèi)存使用情況
計(jì)算速度的對(duì)比,完成相同的訓(xùn)練量XGBoost通常耗費(fèi)的時(shí)間是LightGBM的數(shù)倍之上,在higgs數(shù)據(jù)集上,它們的差距更是達(dá)到了15倍以上。
三、LightGBM的細(xì)節(jié)技術(shù)
1、直方圖優(yōu)化
XGBoost中采用預(yù)排序的方法,計(jì)算過(guò)程當(dāng)中是按照value的排序,逐個(gè)數(shù)據(jù)樣本來(lái)計(jì)算劃分收益,這樣的算法能夠精確的找到最佳劃分值,但是代價(jià)比較大同時(shí)也沒(méi)有較好的推廣性。
在LightGBM中沒(méi)有使用傳統(tǒng)的預(yù)排序的思路,而是將這些精確的連續(xù)的每一個(gè)value劃分到一系列離散的域中,也就是筒子里。以浮點(diǎn)型數(shù)據(jù)來(lái)舉例,一個(gè)區(qū)間的值會(huì)被作為一個(gè)筒,然后以這些筒為精度單位的直方圖來(lái)做。這樣一來(lái),數(shù)據(jù)的表達(dá)變得更加簡(jiǎn)化,減少了內(nèi)存的使用,而且直方圖帶來(lái)了一定的正則化的效果,能夠使我們做出來(lái)的模型避免過(guò)擬合且具有更好的推廣性。
看下直方圖優(yōu)化的細(xì)節(jié)處理
可以看到,這是按照bin來(lái)索引“直方圖”,所以不用按照每個(gè)“特征”來(lái)排序,也不用一一去對(duì)比不同“特征”的值,大大的減少了運(yùn)算量。
2、存儲(chǔ)記憶優(yōu)化
當(dāng)我們用數(shù)據(jù)的bin描述數(shù)據(jù)特征的時(shí)候帶來(lái)的變化:首先是不需要像預(yù)排序算法那樣去存儲(chǔ)每一個(gè)排序后數(shù)據(jù)的序列,也就是下圖灰色的表,在LightGBM中,這部分的計(jì)算代價(jià)是0;第二個(gè),一般bin會(huì)控制在一個(gè)比較小的范圍,所以我們可以用更小的內(nèi)存來(lái)存儲(chǔ)
3、深度限制的節(jié)點(diǎn)展開方法
LightGBM使用了帶有深度限制的節(jié)點(diǎn)展開方法(Leaf-wise)來(lái)提高模型精度,這是比XGBoost中Level-wise更高效的方法。它可以降低訓(xùn)練誤差得到更好的精度。但是單純的使用Leaf-wise可能會(huì)生長(zhǎng)出比較深的樹,在小數(shù)據(jù)集上可能會(huì)造成過(guò)擬合,因此在Leaf-wise之上多加一個(gè)深度限制
4、直方圖做差優(yōu)化
直方圖做差優(yōu)化可以達(dá)到兩倍的加速,可以觀察到一個(gè)葉子節(jié)點(diǎn)上的直方圖,可以由它的父親節(jié)點(diǎn)直方圖減去它兄弟節(jié)點(diǎn)的直方圖來(lái)得到。根據(jù)這一點(diǎn)我們可以構(gòu)造出來(lái)數(shù)據(jù)量比較小的葉子節(jié)點(diǎn)上的直方圖,然后用直方圖做差來(lái)得到數(shù)據(jù)量比較大的葉子節(jié)點(diǎn)上的直方圖,從而達(dá)到加速的效果。
5、順序訪問(wèn)梯度
預(yù)排序算法中有兩個(gè)頻繁的操作會(huì)導(dǎo)致cache-miss,也就是緩存消失(對(duì)速度的影響很大,特別是數(shù)據(jù)量很大的時(shí)候,順序訪問(wèn)比隨機(jī)訪問(wèn)的速度快4倍以上 )。
-
對(duì)梯度的訪問(wèn):在計(jì)算增益的時(shí)候需要利用梯度,對(duì)于不同的特征,訪問(wèn)梯度的順序是不一樣的,并且是隨機(jī)的- 對(duì)于索引表的訪問(wèn):預(yù)排序算法使用了行號(hào)和葉子節(jié)點(diǎn)號(hào)的索引表,防止數(shù)據(jù)切分的時(shí)候?qū)λ械奶卣鬟M(jìn)行切分。同訪問(wèn)梯度一樣,所有的特征都要通過(guò)訪問(wèn)這個(gè)索引表來(lái)索引。這兩個(gè)操作都是隨機(jī)的訪問(wèn),會(huì)給系統(tǒng)性能帶來(lái)非常大的下降。
LightGBM使用的直方圖算法能很好的解決這類問(wèn)題。首先。對(duì)梯度的訪問(wèn),因?yàn)椴挥脤?duì)特征進(jìn)行排序,同時(shí),所有的特征都用同樣的方式來(lái)訪問(wèn),所以只需要對(duì)梯度訪問(wèn)的順序進(jìn)行重新排序,所有的特征都能連續(xù)的訪問(wèn)梯度。并且直方圖算法不需要把數(shù)據(jù)id到葉子節(jié)點(diǎn)號(hào)上(不需要這個(gè)索引表,沒(méi)有這個(gè)緩存消失問(wèn)題)
6、支持類別特征
傳統(tǒng)的機(jī)器學(xué)習(xí)一般不能支持直接輸入類別特征,需要先轉(zhuǎn)化成多維的0-1特征,這樣無(wú)論在空間上還是時(shí)間上效率都不高。LightGBM通過(guò)更改決策樹算法的決策規(guī)則,直接原生支持類別特征,不需要轉(zhuǎn)化,提高了近8倍的速度。
7、支持并行學(xué)習(xí)
LightGBM原生支持并行學(xué)習(xí),目前支持特征并行(Featrue Parallelization)和數(shù)據(jù)并行(Data Parallelization)兩種,還有一種是基于投票的數(shù)據(jù)并行(Voting Parallelization)
-
特征并行的主要思想是在不同機(jī)器、在不同的特征集合上分別尋找最優(yōu)的分割點(diǎn),然后在機(jī)器間同步最優(yōu)的分割點(diǎn)。- 數(shù)據(jù)并行則是讓不同的機(jī)器先在本地構(gòu)造直方圖,然后進(jìn)行全局的合并,最后在合并的直方圖上面尋找最優(yōu)分割點(diǎn)。LightGBM針對(duì)這兩種并行方法都做了優(yōu)化。 -
特征并行算法中,通過(guò)在本地保存全部數(shù)據(jù)避免對(duì)數(shù)據(jù)切分結(jié)果的通信。- 數(shù)據(jù)并行中使用分散規(guī)約 (Reduce scatter) 把直方圖合并的任務(wù)分?jǐn)偟讲煌臋C(jī)器,降低通信和計(jì)算,并利用直方圖做差,進(jìn)一步減少了一半的通信量。- **基于投票的數(shù)據(jù)并行(Voting Parallelization)**則進(jìn)一步優(yōu)化數(shù)據(jù)并行中的通信代價(jià),使通信代價(jià)變成常數(shù)級(jí)別。在數(shù)據(jù)量很大的時(shí)候,使用投票并行可以得到非常好的加速效果。下圖更好的說(shuō)明了以上這三種并行學(xué)習(xí)的整體流程:
在直方圖合并的時(shí)候,通信代價(jià)比較大,基于投票的數(shù)據(jù)并行能夠很好的解決這一點(diǎn)。
四、MacOS安裝LightGBM
#先安裝cmake和gcc,安裝過(guò)的直接跳過(guò)前兩步
brew install cmake
brew install gcc
git clone --recursive https://github.com/Microsoft/LightGBM
cd LightGBM
#在cmake之前有一步添加環(huán)境變量
export CXX=g++-7 CC=gcc-7
mkdir build ; cd build
cmake ..
make -j4
cd ../python-package
sudo python setup.py install
來(lái)測(cè)試一下:
大功告成!
值得注意的是:pip list里面沒(méi)有l(wèi)ightgbm,以后使用lightgbm需要到特定的文件夾中運(yùn)行。我的地址是:
/Users/ fengxianhe / LightGBM /python-package
五,用python實(shí)現(xiàn)LightGBM算法
為了演示LightGBM在蟒蛇中的用法,本代碼以sklearn包中自帶的鳶尾花數(shù)據(jù)集為例,用lightgbm算法實(shí)現(xiàn)鳶尾花種類的分類任務(wù)。
# coding: utf-8
# pylint: disable = invalid-name, C0111
# 函數(shù)的更多使用方法參見(jiàn)LightGBM官方文檔:http://lightgbm.readthedocs.io/en/latest/Python-Intro.html
import json
import lightgbm as lgb
import pandas as pd
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
iris = load_iris() # 載入鳶尾花數(shù)據(jù)集
data=iris.data
target = iris.target
X_train,X_test,y_train,y_test =train_test_split(data,target,test_size=0.2)
# 加載你的數(shù)據(jù)
# print('Load data...')
# df_train = pd.read_csv('../regression/regression.train', header=None, sep='\t')
# df_test = pd.read_csv('../regression/regression.test', header=None, sep='\t')
#
# y_train = df_train[0].values
# y_test = df_test[0].values
# X_train = df_train.drop(0, axis=1).values
# X_test = df_test.drop(0, axis=1).values
# 創(chuàng)建成lgb特征的數(shù)據(jù)集格式
lgb_train = lgb.Dataset(X_train, y_train) # 將數(shù)據(jù)保存到LightGBM二進(jìn)制文件將使加載更快
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train) # 創(chuàng)建驗(yàn)證數(shù)據(jù)
# 將參數(shù)寫成字典下形式
params = {
'task': 'train',
'boosting_type': 'gbdt', # 設(shè)置提升類型
'objective': 'regression', # 目標(biāo)函數(shù)
'metric': {'l2', 'auc'}, # 評(píng)估函數(shù)
'num_leaves': 31, # 葉子節(jié)點(diǎn)數(shù)
'learning_rate': 0.05, # 學(xué)習(xí)速率
'feature_fraction': 0.9, # 建樹的特征選擇比例
'bagging_fraction': 0.8, # 建樹的樣本采樣比例
'bagging_freq': 5, # k 意味著每 k 次迭代執(zhí)行bagging
'verbose': 1 # <0 顯示致命的, =0 顯示錯(cuò)誤 (警告), >0 顯示信息
}
print('Start training...')
# 訓(xùn)練 cv and train
gbm = lgb.train(params,lgb_train,num_boost_round=20,valid_sets=lgb_eval,early_stopping_rounds=5) # 訓(xùn)練數(shù)據(jù)需要參數(shù)列表和數(shù)據(jù)集
print('Save model...')
gbm.save_model('model.txt') # 訓(xùn)練后保存模型到文件
print('Start predicting...')
# 預(yù)測(cè)數(shù)據(jù)集
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration) #如果在訓(xùn)練期間啟用了早期停止,可以通過(guò)best_iteration方式從最佳迭代中獲得預(yù)測(cè)
# 評(píng)估模型
print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5) # 計(jì)算真實(shí)值和預(yù)測(cè)值之間的均方根誤差
輸出結(jié)果:
可以看到預(yù)測(cè)值和真實(shí)值之間的均方根誤差為0.722972。


Python“寶藏級(jí)”公眾號(hào)【Python之王】專注于Python領(lǐng)域,會(huì)爬蟲,數(shù)分,C++,tensorflow和Pytorch等等。
近 2年共原創(chuàng) 100+ 篇技術(shù)文章。創(chuàng)作的精品文章系列有:
日常收集整理了一批不錯(cuò)的 Python 學(xué)習(xí)資料,有需要的小伙可以自行免費(fèi)領(lǐng)取。
