Win10 平臺下, LightGBM GPU 版本的安裝

AragornJIA發表於2019-02-07

1. Light GBM 簡介

在資料探勘和傳統機器學習領域,提起大名鼎鼎的 XGBoost,相信很多人都聽說過,尤其是在 Kaggle 賽場上,XGBoost 更是風光無限,不過今天的主角卻不是 XGBoost,而是 LightGBM (Light Gradient Boost Machine),這是由微軟開發並且開源的、一個類似於 XGBoost 的梯度提升框架。

在 Github上,LightGBM 是這樣自我介紹的,LightGBM 是一種快速、分散式、高效能梯度提升框架,該框架基於決策樹演算法,可用於分類、迴歸、排序等多種機器學習任務。詳細介紹可以前往 LightGBM 在 Github 的主頁,及官方主頁

另外,LightGBM 的原理,及其與 XGBoost 的對比分析,可以前往:LightGBM大戰XGBoost,誰將奪得桂冠?

這幾天在使用 LightGBM 訓練資料,由於資料量太大,所耗時間比較長,就思考能不能使用GPU 進行計算,並於今天上午成功完成了環境的搭建。這篇部落格主要來源於官方手冊和 Stack Overflow 上相關問題的提問及回答,並結合自己在安裝的過程中所遇到的問題。我自己在搭建環境、搜尋相關的教程的過程中,發現 LightGBM 相關主題的文章比較張,尤其使用 GPU 進行計算的就更少了,所以才總結出了這篇文章,與大家分享,期待我們一起學習,一起進步。好了,以下內容言歸正傳。


2. LightGBM CPU 版本的安裝

LightGBM CPU 版本的安裝和 Python 其他 Package 的安裝一樣,基本有三種方法:

  1. 通過 pip 命令安裝,這是 Python 社群推薦的安裝方式,安裝命令:pip install lightgbm

  2. 通過 Anaconda 進行安裝,安裝命令:conda install lightgbm

  3. 通過 Github 進行安裝,在命令列中輸入 git clone ttps://github.com/Microsoft/LightGBM,等LightGBM包下載完成之後,通過命令列進入到 .\LightGBM\python-package 資料夾,輸入 python setup.py install ,即可完成安裝。

以上三種安裝方式在使用上沒有差異,但是package管理和更新上有些不同。

  • pip 安裝是 Python官方社群的推薦方式。優點是各個 package 會首先通過該方式更新,下載速度比較快,package的種類比較多,而且都是經過社群稽核的。缺點在於無法批量更新 package,需要手動進行各個 package 的更新;無法對python的不同版本環境進行管理,需要使用 virtualenv 等工具進行管理。

  • Anaconda是使用 Python 進行科學計算方面最常用的管理工具,整合的 conda 不但可以管理各個 package,並解決其依賴關係,還能管理不同 Python 版本的各自環境,此外,Anaconda 不僅僅是Python的包管理工具,還可以對 Julia 等其他語言的包和環境進行統一管理。此外,可以使用 “conda update --all” 命令批量升級 package。缺點是:package 下載速度比較慢,這一點可以通過下載國內的映象檔案進行彌補,此外就是部分 pip 可以安裝的 package 無法通過 conda 安裝,比如 conda 版本的 XGBoost 只提供了 Linux 和 Mac OS 版本,沒有 Win 版本。

  • 以上兩種方式都是使用已經編譯好的二進位制檔案進行安裝,而 github 的安裝則是使用原始碼進行安裝。待會安裝 GPU 版本時,就需要對原始碼進行重新編譯和構建 (compile and build),採用的就是這種安裝方式。


3. LightGBM GPU 版本的安裝

安裝 GPU 版本的主要思路就是從 Github 上下載原始碼,然後對其進行重新編譯 (re-compile),對編譯好的檔案,使用 CMake 對其進行構造 (Build),最後使用 python setup.py install --gpu 命令進行安裝。在win平臺,對其原始碼進行編譯構造,主要有兩種方式:一種是使用 CMake 和 VS Build Tools (或者 Visual Studio),另一種是使用 CMake 和 MinGW。

這裡是已經使用 CMake 和 Visual Studio 編譯和構造好的檔案,可以直接下載,然後在命令列中進入 “.\LightGBM\python-package” 資料夾,輸入 “python setup.py install --gpu”,即可完成安裝。如果你使用這樣方式安裝,那麼你可以直接跳到 4. 引數設定部分了。

如果你希望嘗試自己對原始碼進行構建和編譯,可以按下面的步驟一步一步來。

3.1 使用 Visual Studio 進行編譯和構建

Win平臺的 Python 是用 Visual Studio 進行構造和編譯,所以如果使用 Visual Studio 對 LightGBM 進行編譯和構造的話,可以省去很多麻煩;相反,如果使用
MinGW 對其進行編譯和構造,則可能會遇到很多意想不到的麻煩,因此推薦使用 VS Build Tools (或者 Visual Studio) 對其進行構造和編譯。

具體步驟為:

1). 下載並安裝 Git for Win

詳細步驟可以參考這篇文章 Git安裝教程(Windows安裝超詳細教程)

2). 下載並安裝 CMake

這個安裝過程比較簡單,不過有兩點需要注意。

根據系統是32位還是64位下載相應的“.msi”檔案

image

勾選中間那一項,對所有使用者都新增到系統 path 路徑中, 其他方面就一路 next 就可以了。這是啟動之後的介面:

3). 下載並安裝 VS Build Tools。

VS Build Tools 現在整合在 Visual Studio 之中,沒有提供單獨下載。Visual Studio 作為商業軟,自然是收費的,但是微軟提供了一個 Visual Studio Community 版本,可以免費使用,最新版為 Visual Studio Community 2017

點選下載的 “.exe”, 會出現一個安裝選擇皮膚,你可以勾選希望安裝的功能,如果只是用於這次的編譯和構造,只需要按下圖進行勾選即可,然後安裝即可。

4). 下載安裝相應的OpenCL

OpenCL 可以簡單地理解為顯示卡的驅動,所以Intel、Nvidia和AMD需要安裝不同的OpenCL。

5). 下載安裝 Boost Binaries

選擇和 visual studio 版本對應的版本:

Visual Studio 2015:msvc-14.0-64.exe
Visual Studio 2017:msvc-14.1-64.exe

安裝完成之後,會在C盤根目錄下,出現 “C:\local\” 這個資料夾,把 "C:\local\boost_1_64_0\"和"C:\local\boost_1_64_0\lib64-msvc-14.1"新增到系統環境變數 (Note: 根據安裝的Boost Binaries 版本不同,路徑名稱會有稍微不同)

6). 編譯並構造原始檔

  1. 在命令列中,輸入:
Set BOOST_ROOT=C:\local\boost_1_64_0\
Set BOOST_LIBRARYDIR=C:\local\boost_1_64_0\lib64-msvc-14.1
git clone --recursive https://github.com/Microsoft/LightGBM
  1. 等 LightGBM的原始檔下載完成之後,開啟剛才安裝的 CMake GUI

最上面的Brower Source 選擇下載的 LightGBM 檔案的路徑,然後在其中新建 Build 資料夾,Brower Build 選擇新建的 Build 資料夾,並且勾選 “USE_GPU” 和 “USE_OPENMP

  1. Warning:如果你的電腦同時裝有多個顯示卡(包括整合顯示卡),建議進行以下設定,如果只有一個顯示卡,可以跳過該步驟。

點選 “Add Entry”, 並進行以下設定

根據剛才安裝的 Visual Studio版本進行選擇

點選,左下角的 “Config”,會出現

記得勾選 “USE_GPU” 和 “USE_OPENMP”,再點選左下角的 “Config”,沒有再出現紅顏色之後,點選旁邊的 “Genarate”。

之後,使用命令列進入 “.\LightGBM\build”, 然後在命令列輸入:

cmake --build . --target ALL_BUILD --config Release

這時候,你會發現,LightGBM 資料夾裡多了一個Release 資料夾。

然後通過命令列進入 “.\LightGBM\python-package\”,並輸入:

python setup.py install --gpu

到這裡就完成了使用Visual Studio 對 LightGBM 原始碼進行重新編譯、構造和安裝。

3.2 使用 MinGW 進行編譯和構造

Win 平臺的 Python 是用 Visual Studio 進行構造和編譯,如果使用 VS Build Tools 對LightGBM 進行構造和編譯的話,可以省去很多麻煩;相反,如果使用 MinGW 對其進行編譯和構造,則可能會遇到很多意想不到的麻煩。但是 Stack Overflow 上有人反映說,用 MinGW 編譯會比用 VS Studio 更快,並且編譯出的檔案,安裝之後, CPU,GPU 和記憶體的利用會稍微好一些。

具體步驟和使用 VS 編譯差不多:

1)下載並安裝 MinGW

如果你的系統是32位的,建議下載安裝MinGW
如果你的系統是64位的,建議下載安裝MinGW-w64

最好按著這個配置安裝。

安裝路徑使用預設的,安裝成功之後,把 “C:\Program Files\mingw-w64\mingw64\bin”(你的路徑可能不太一樣)新增到系統環境變數中。

為了測試安裝是否成功,可以在命令列中輸入:"gcc -v",如果安裝成功,會出現類似下圖的情況

2)下載並安裝 Git for Win

詳細步驟可以參考這篇 Git安裝教程(Windows安裝超詳細教程)

3)下載並安裝 CMake

這個安裝過程比較簡單,不過有兩點需要注意。

根據系統是32位還是64位下載相應的“.msi”檔案

勾選中間那一項,對所有使用者都新增到系統 path 路徑中. 其他方面就一路 next 就可以了。這是啟動之後的介面:

4)下載安裝相應的OpenCL

OpenCL 可以簡單地理解為顯示卡的驅動,所以Intel、Nvidia和AMD需要安裝不同的OpenCL。

5)下載安裝 Boost Binaries

安裝完成之後,會在C盤根目錄下,出現 “C:\local” 這個資料夾,把 "C:\local\boost_1_64_0\“和”C:\local\boost_1_64_0\lib64-msvc-14.1"新增到系統環境變數中。(Note: 根據安裝的Boost Binaries 版本不同,路徑名稱會有稍微不同)

在命令列輸入:

cd C:\local\boost_1_64_0\tools\build
bootstrap.bat gcc
b2 install --prefix="C:\local\boost-build" toolset=gcc cd C:\boost\boost_1_64_0

為了構造 Boost 庫,如果你的電腦是單核的,你可以在命令列輸入:

b2 install --build_dir="C:\boost\boost-build" --prefix="C:\boost\boost-build" toolset=gcc --with=filesystem,system threading=multi --layout=system release

如果你的電腦是單核的,你可以在命令列輸入:

b2 install --build_dir="C:\boost\boost-build" --prefix="C:\boost\boost-build" toolset=gcc --with=filesystem,system threading=multi --layout=system release -j 2

在編譯結束之後,你可以看到類似的情況:

Note:如果出現了問題,你可以嘗試從頭再試一次。

6)構造並編譯原始檔

在命令列中,輸入:

Set BOOST_ROOT=C:\local\boost_1_64_0\ 
Set BOOST_LIBRARYDIR=C:\local\boost_1_64_0\lib64-msvc-14.1 
git clone --recursive https://github.com/Microsoft/LightGBM

等 LightGBM 的原始檔下載完成之後,開啟剛才安裝的 CMake GUI

最上面的Brower Source 選擇你下載的LightGBM檔案的路徑,然後在其中新建Build資料夾,Brower Build選擇新建的Build資料夾,並且勾選"USE_GPU" 和 “USE_OPENMP”

Warning:如果你的電腦同時裝有多個顯示卡(包括整合顯示卡),建議進行以下設定,如果只有一個顯示卡,可以跳過該步驟。

點選 “Add Entry”, 並進行以下設定

根據剛才安裝的 MinGW

點選,左下角的 “Config”,可能會出現

記得勾選"USE_GPU" 和 “USE_OPENMP”,再點選左下角的 “Config”,沒有再出現紅顏色之後,點選旁邊的 “Genarate”。

之後,使用命令列進入 “.\LightGBM\build”, 然後再命令列輸入:

cmake --build . --target ALL_BUILD --config Release

這時候,你會發現,LightGBM 資料夾裡多了一個Release 資料夾。
然後通過命令列進入 “.\LightGBM\python-package\”,並輸入:

python setup.py install --gpu

到這裡就完成了使用 MinGW-64 對 LightGBM 原始碼進行重新編譯、構造和安裝。


4. 引數設定

通過上面的步驟,我們已經完成了 LightGBM GPU 版本的安裝,接下來我們就要測試一下,安裝是否成功了。

使用 GPU 進行計算的程式碼基本和使用 CPU 進行計算一樣,只不過需要設定一個引數 device='gpu', 如果你的電腦只有一個 GPU,這樣設定就可以了。但是如果你的電腦有多個 GPU,就需要多設定一些引數。

gpu_platform_id:表示要使用的GPU平臺,比如 Intel,Nvidia,AMD
gpu_device_id:表示在這個平臺下,要使用哪個GPU

比如我的筆記本有 Intel 的整合顯示卡和 Nvidia 的獨立顯示卡,如果設定為;

device = 'gpu' 表示使用預設顯示卡,一般為整合顯示卡
device='gpu', gpu_platform_id=1, gpu_device_id=0:表示使用第二個GPU平臺(我的是Nvidia),第一個顯示卡,因為我的筆記本上Nvidia的顯示卡只有一個。

你可以在任意一段使用 LightGBM 的程式碼中,新增以上一個或者三個引數,如果能順利執行,就證明安裝成功了。如果失敗,可以根據提示,到 CSDN 論壇 或者 Stack Overflow 上搜尋相關問題。

微軟這樣的設定可能會讓很多人覺得很腦殘,確實有那麼一點,那麼其他可以使用 GPU 進行計算的框架是如何處理的呢?

安裝 XGBoost GPU 版本之後,可以通過設定引數 “tree_method” 選擇使用 CPU 或 GPU及哪種演算法,它的可選引數有 “hist”, “exact” (表示使用 CPU), “gpu_hist”, “gpu_exact” (表示使用 GPU)。此外還可以通過設定引數 ”n_gpus=1"(表示使用一個 GPU, “n_gpus= -1” (表示使用所有的 GPU). Google 的深度學習框架 TensorFlow 也有 CPU 和 GPU 兩個版本, 在只安裝 CPU 版本的時候, 電腦只能使用 CPU 進行計算, 但是 如果同時安裝了 CPU 和 GPU 兩個版本時, TensorFlow 會首先檢測 GPU 是否可用, 如果可用, 就預設使用 GPU 進行加速計算, 否則還是使用 CPU.

相比於 XGBoost 和 TensorFlow, LightGBM 呼叫 GPU 的方式確實不怎樣方便, 但是 XGBoost 和 TensorFlow 只能使用 Nvidia 的獨顯進行加速計算, 而 LightGBM 卻可以使用 Intel, Nvidia 和 AMD 三個平臺的顯示卡進行加速計算, 這對於只有 Intel 集顯的電腦是非常友好的.

結合這幾個計算框架在呼叫 GPU 時各自的優缺點, 建議 LightGBM 使用Tensor Flow 那樣的呼叫方式, 在 GPU 可用的情況下, 預設使用 GPU, 同時具有集顯和獨顯的時候, 優先呼叫獨顯. 這樣更能發揮出 GPU 比較強悍的計算平行計算能力, 也能符合使用者的使用習慣.


5. 效能提升

安裝 GPU 版本是為了提高計算速度,那麼使用 GPU 相對與使用 CPU,速度到底提到了多少呢?接下來,我們會用一段程式進行試驗。

import lightgbm as lgb
import xgboost as xgb
import time

dtrain = lgb.Dataset('higgs.csv')

params = {'max_bin': 63,
          'num_leaves': 255,
          'learning_rate': 0.1,
          'tree_learner': 'serial',
          'task': 'train',
          'is_training_metric': 'false',
          'min_data_in_leaf': 1,
          'min_sum_hessian_in_leaf': 100,
          'ndcg_eval_at': [1, 3, 5, 10],
          'sparse_threshold': 1.0,
          'device': 'cpu'
          }
print("*****************************")
t0 = time.time()
gbm = lgb.train(params, train_set=dtrain, num_boost_round=10,
                valid_sets=None, valid_names=None,
                fobj=None, feval=None, init_model=None,
                feature_name='auto', categorical_feature='auto',
                early_stopping_rounds=None, evals_result=None,
                verbose_eval=True,
                keep_training_booster=False, callbacks=None)
t1 = time.time()

print('cpu version elapse time: {}'.format(t1-t0))
time.sleep(20)
print("*****************************")

params = {'max_bin': 63,
          'num_leaves': 255,
          'learning_rate': 0.1,
          'tree_learner': 'serial',
          'task': 'train',
          'is_training_metric': 'false',
          'min_data_in_leaf': 1,
          'min_sum_hessian_in_leaf': 100,
          'ndcg_eval_at': [1, 3, 5, 10],
          'sparse_threshold': 1.0,
          'device': 'gpu',
          'gpu_platform_id': 1,
          'gpu_device_id': 0
          }

t0 = time.time()
gbm = lgb.train(params, train_set=dtrain, num_boost_round=10,
                valid_sets=None, valid_names=None,
                fobj=None, feval=None, init_model=None,
                feature_name='auto', categorical_feature='auto',
                early_stopping_rounds=None, evals_result=None,
                verbose_eval=True,
                keep_training_booster=False, callbacks=None)
t1 = time.time()

print('gpu version elapse time: {}'.format(t1-t0))
time.sleep(20)
print("*****************************")


params = {'max_bin': 63,
          'num_leaves': 255,
          'learning_rate': 0.1,
          'tree_learner': 'serial',
          'task': 'train',
          'is_training_metric': 'false',
          'min_data_in_leaf': 1,
          'min_sum_hessian_in_leaf': 100,
          'ndcg_eval_at': [1, 3, 5, 10],
          'sparse_threshold': 1.0,
          'device': 'gpu'
          }


t0 = time.time()
gbm = lgb.train(params, train_set=dtrain, num_boost_round=10,
                valid_sets=None, valid_names=None,
                fobj=None, feval=None, init_model=None,
                feature_name='auto', categorical_feature='auto',
                early_stopping_rounds=None, evals_result=None,
                verbose_eval=True,
                keep_training_booster=False, callbacks=None)
t1 = time.time()

print('gpu version elapse time: {}'.format(t1-t0))

使用的資料集是微軟官方對比 LightGBM 和 XGBoost 效能時,所使用的資料集。

筆記本的配置是:
CPU:Intel Core i7-8550U
GPU:Intel UHD Graphics 620, NVIDIA GeForce®MX150

這是在我的筆記本上的執行的結果,從計算時間上來看,使用 GPU 計算對速度提升還是挺大的。不過出乎我的意料的是,Intel 的集顯和 Nvidia 的獨顯所用時間差不多,可能是我的獨顯太垃圾了吧。

我本人是用 VS 編譯的,所以 MinGW 部分寫的有些省略,請大家見諒。

PS:這是我第一次寫部落格,文章中肯定有很多錯誤的地方,請大家多多包涵,也歡迎大家指出。

相關文章