0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用Dask最大化GPU加速

星星科技指導(dǎo)員 ? 來源:NVIDIA ? 作者:Jiaming Yuan ? 2022-04-24 17:51 ? 次閱讀

在 xgboost1.0 中,我們引入了 新的官方 Dask 接口 來支持高效的分布式訓(xùn)練。 快速轉(zhuǎn)發(fā)到 XGBoost1.4 ,接口現(xiàn)在功能齊全。如果您對 xgboostdask 接口還不熟悉,請參閱第一篇文章,以獲得一個溫和的介紹。在本文中,我們將看一些簡單的代碼示例,展示如何最大化GPU加速的好處。

我們的例子集中在希格斯數(shù)據(jù)集上,這是一個來自 機(jī)器學(xué)習(xí)庫 的中等規(guī)模的分類問題。 在下面的章節(jié)中,我們從基本數(shù)據(jù)加載和預(yù)處理開始,使用 GPU 加速的 Dask 和 Dask-ml 。然后,針對不同配置的返回數(shù)據(jù)訓(xùn)練 XGBoost 模型。同時,分享一些新特性。之后,我們將展示如何在 GPU 集群上計算 SHAP 值以及可以獲得的加速比。最后,我們分享了一些優(yōu)化技術(shù)與推理。

以下示例需要在至少有一個 NVIDIA GPU 的機(jī)器上運(yùn)行, GPU 可以是筆記本電腦或云實(shí)例。 Dask 的優(yōu)點(diǎn)之一是它的靈活性,用戶可以在筆記本電腦上測試他們的代碼。它們還可以將計算擴(kuò)展到具有最小代碼更改量的集群。 另外,要設(shè)置環(huán)境,我們需要 xgboost==1.4 、 dask 、 dask-ml 、 dask-cuda 和 達(dá)斯克 – cuDF python 包,可從 RAPIDS 康達(dá)頻道: 獲得

conda install -c rapidsai -c conda-forge dask dask-ml dask-cuda dask-cudf xgboost=1.4.2

在 GPU 集群上用 Dask 加載數(shù)據(jù)

首先,我們將數(shù)據(jù)集下載到 data 目錄中。

mkdir data
curl http://archive.ics.uci.edu/ml/machine-learning-databases/00280/HIGGS.csv.gz --output ./data/HIGGS.csv.gz

然后使用dask-cuda設(shè)置 GPU 集群:

import os
from time import time
from typing import Tuple

from dask import dataframe as dd
from dask_cuda import LocalCUDACluster
from distributed import Client, wait
import dask_cudf
from dask_ml.model_selection import train_test_split

import xgboost as xgb
from xgboost import dask as dxgb
import numpy as np
import argparse

# … main content to be inserted here in the following sections

if __name__ == "__main__":
   parser = argparse.ArgumentParser()
   parser.add_argument("--n_workers", type=int, required=True)
   args = parser.parse_args()
   with LocalCUDACluster(args.n_workers) as cluster:
       print("dashboard:", cluster.dashboard_link)
       with Client(cluster) as client:
           main(client)

給定一個集群,我們開始將數(shù)據(jù)加載到 gpu 中。 由于在參數(shù)調(diào)整期間多次加載數(shù)據(jù),因此我們將 CSV 文件轉(zhuǎn)換為 Parquet 格式以獲得更好的性能。 這可以使用dask_cudf輕松完成:

def to_parquet() -> str:
   """Convert the HIGGS.csv file to parquet files."""
   dirpath = "./data"
   parquet_path = os.path.join(dirpath, "HIGGS.parquet")
   if os.path.exists(parquet_path):
       return parquet_path
   csv_path = os.path.join(dirpath, "HIGGS.csv")
   colnames = ["label"] + ["feature-%02d" % i for i in range(1, 29)]
   df = dask_cudf.read_csv(csv_path, header=None, names=colnames, dtype=np.float32)
   df.to_parquet(parquet_path)
   return parquet_path

數(shù)據(jù)加載后,我們準(zhǔn)備培訓(xùn)/驗(yàn)證拆分:

def load_higgs(
    path,
) -> Tuple[
    dask_cudf.DataFrame, dask_cudf.Series, dask_cudf.DataFrame, dask_cudf.Series
]:
    df = dask_cudf.read_parquet(path)

    y = df["label"]
    X = df[df.columns.difference(["label"])]

    X_train, X_valid, y_train, y_valid = train_test_split(
        X, y, test_size=0.33, random_state=42
    )
    X_train, X_valid, y_train, y_valid = client.persist(
        [X_train, X_valid, y_train, y_valid]
    )
    wait([X_train, X_valid, y_train, y_valid])

    return X_train, X_valid, y_train, y_valid

在前面的示例中,我們使用 dask-cudf 從磁盤加載數(shù)據(jù),使用 dask-ml 中的 火車測試分裂了 函數(shù)拆分?jǐn)?shù)據(jù)集。 大多數(shù)時候, dask 的 GPU 后端與 dask-ml 中的實(shí)用程序無縫地工作,我們可以加速整個 ML 管道。

提前停止訓(xùn)練

最常請求的特性之一是提前停止對 Dask 接口的支持。 在 XGBoost1 。 4 版本中,我們不僅可以指定停止輪的數(shù)量,還可以開發(fā)定制的提前停止策略。 對于最簡單的情況,向 train 函數(shù)提供停止回合可以實(shí)現(xiàn)提前停止:

def fit_model_es(client, X, y, X_valid, y_valid) -> xgb.Booster:
   early_stopping_rounds = 5
   Xy = dxgb.DaskDeviceQuantileDMatrix(client, X, y)
   Xy_valid = dxgb.DaskDMatrix(client, X_valid, y_valid)
   # train the model
   booster = dxgb.train(
       client,
       {
           "objective": "binary:logistic",
           "eval_metric": "error",
           "tree_method": "gpu_hist",
       },
       Xy,
       evals=[(Xy_valid, "Valid")],
       num_boost_round=1000,
       early_stopping_rounds=early_stopping_rounds,
   )["booster"]
   return booster

在前面的片段中有兩件事需要注意。 首先,我們指定觸發(fā)提前停止訓(xùn)練的輪數(shù)。 XGBoost 將在連續(xù) X 輪驗(yàn)證指標(biāo)未能改善時停止培訓(xùn)過程,其中 X 是指定提前停止的輪數(shù)。 其次,我們使用名為 DaskDeviceQuantileDMatrix 的數(shù)據(jù)類型進(jìn)行訓(xùn)練,但使用 DaskDMatrix 進(jìn)行驗(yàn)證。 DaskDeviceQuantileDMatrix 是 DaskDMatrix 的替代品,用于基于 GPU 的訓(xùn)練輸入,避免了額外的數(shù)據(jù)拷貝。

與 gpu_hist 一起使用時, DaskDeviceQuantileDMatrix 可以節(jié)省大量內(nèi)存,并且輸入數(shù)據(jù)已經(jīng)在 GPU 上。圖 1 描述了 DaskDeviceQuantileDMatrix. 的結(jié)構(gòu) 數(shù)據(jù)分區(qū)不再需要復(fù)制和連接,取而代之的是,由草圖算法生成的摘要被用作真實(shí)數(shù)據(jù)的代理。

圖 1 : DaskDeviceQuantileDMatrix 的構(gòu)造 。

在 XGBoost 中,提前停止作為回調(diào)函數(shù)實(shí)現(xiàn)。 新的回調(diào)接口可以用來實(shí)現(xiàn)更高級的提前停止策略。下面的代碼顯示了提前停止的另一種實(shí)現(xiàn),其中有一個附加參數(shù)要求 XGBoost 僅返回最佳模型,而不是完整模型:

  def fit_model_customized_es(client, X, y, X_valid, y_valid):
early_stopping_rounds = 5
es = xgb.callback.EarlyStopping(rounds=early_stopping_rounds, save_best=True)
Xy = dxgb.DaskDeviceQuantileDMatrix(client, X, y)
Xy_valid = dxgb.DaskDMatrix(client, X_valid, y_valid)
# train the model
booster = xgb.dask.train(
client,
{
"objective": "binary:logistic",
"eval_metric": "error",
"tree_method": "gpu_hist",
},
Xy,
evals=[(Xy_valid, "Valid")],
num_boost_round=1000,
callbacks=[es],
)["booster"]
return booster

在前面的示例中, EarlyStopping 回調(diào)作為參數(shù)提供給 train ,而不是使用 early_stopping_rounds 參數(shù)。為了提供一個定制的提前停止策略,探索 EarlyStopping 的其他參數(shù)或子類化這個回調(diào)是一個很好的起點(diǎn)。

定制目標(biāo)和評估指標(biāo)

XGBoost 被設(shè)計成可以通過定制的目標(biāo)函數(shù)和度量進(jìn)行擴(kuò)展。在 1 。 4 中,這個特性被引入 dask 接口。要求與單節(jié)點(diǎn)接口完全相同:

def fit_model_customized_objective(client, X, y, X_valid, y_valid) -> dxgb.Booster:
    def logit(predt: np.ndarray, Xy: xgb.DMatrix) -> Tuple[np.ndarray, np.ndarray]:
        predt = 1.0 / (1.0 + np.exp(-predt))
        labels = Xy.get_label()
        grad = predt - labels
        hess = predt * (1.0 - predt)
        return grad, hess

    def error(predt: np.ndarray, Xy: xgb.DMatrix) -> Tuple[str, float]:
        label = Xy.get_label()
        r = np.zeros(predt.shape)
        predt = 1.0 / (1.0 + np.exp(-predt))
        gt = predt > 0.5
        r[gt] = 1 - label[gt]
        le = predt <= 0.5
        r[le] = label[le]
        return "CustomErr", float(np.average(r))

    # Use early stopping with custom objective and metric.
    early_stopping_rounds = 5
    # Specify the metric we want to use for early stopping.
    es = xgb.callback.EarlyStopping(
    rounds=early_stopping_rounds, save_best=True, metric_name="CustomErr"
    )

    Xy = dxgb.DaskDeviceQuantileDMatrix(client, X, y)
    Xy_valid = dxgb.DaskDMatrix(client, X_valid, y_valid)
    booster = dxgb.train(
        client,
        {"eval_metric": "error", "tree_method": "gpu_hist"},
        Xy,
        evals=[(Xy_valid, "Valid")],
        num_boost_round=1000,
        obj=logit,  # pass the custom objective
        feval=error,  # pass the custom metric
        callbacks=[es],
    )["booster"]
    return booster

在前面的函數(shù)中,我們使用定制的目標(biāo)函數(shù)和度量來實(shí)現(xiàn)一個 logistic 回歸模型以及提前停止。請注意,該函數(shù)同時返回 gradient 和 hessian , XGBoost 使用它們來優(yōu)化模型。 另外,需要在回調(diào)中指定名為 metric_name 的參數(shù)。它用于通知 XGBoost 應(yīng)該使用自定義錯誤函數(shù)來評估早期停止標(biāo)準(zhǔn)。

解釋模型

在得到我們的第一個模型之后,我們 MIG ht 想用 SHAP 來解釋預(yù)測。 SHapley 加法解釋( SHapley Additive explainstructions , SHapley Additive explainstructions )是一種基于 SHapley 值解釋機(jī)器學(xué)習(xí)模型輸出的博弈論方法。 有關(guān)算法的詳細(xì)信息,請參閱 papers 。 由于 XGBoost 現(xiàn)在支持 GPU 加速的 Shapley 值,因此我們將此功能擴(kuò)展到 Dask 接口?,F(xiàn)在,用戶可以在分布式 GPU 集群上計算 shap 值。這是由顯著改進(jìn)的預(yù)測函數(shù)和 GPUTreeShap 庫 實(shí)現(xiàn)的:

def explain(client, model, X):
   # Use array instead of dataframe in case of output dim is greater than 2.
   X_array = X.values
   contribs = dxgb.predict(
       client, model, X_array, pred_contribs=True, validate_features=False
   )
   # Use the result for further analysis
   return contribs

XGBoost 使用多個 GPU 計算 shap 值的性能如圖 2 所示。

圖 2 : Shap 推斷時間。

基準(zhǔn)測試是在一臺 NVIDIA DGX-1 服務(wù)器上進(jìn)行的,該服務(wù)器有 8 個 V100 gpu 和兩個 20 核的 Xeon E5-2698 v4 cpu ,并進(jìn)行了一輪訓(xùn)練、 shap 值計算和推理。

得到的 SHAP 值可用于可視化、使用特征權(quán)重調(diào)整列采樣或用于其他數(shù)據(jù)工程目的。

運(yùn)行推理

經(jīng)過一些調(diào)整,我們得到了對新數(shù)據(jù)進(jìn)行推理的最終模型。 XGBoost Dask 接口的預(yù)測沒有舊版本那么有效,而且內(nèi)存不足。在 1 。 4 中,我們修改了預(yù)測函數(shù)并增加了對就地預(yù)測的支持。 對于正態(tài)預(yù)測,它使用與 shap 值計算相同的接口:

def predict(client, model, X):
    predt = dxgb.predict(client, model, X)
    assert isinstance(predt, dd.Series)
    return predt


標(biāo)準(zhǔn)的 predict 函數(shù)提供了一個通用接口,可同時接受DaskDMatrix和 dask 集合(數(shù)據(jù)幀或數(shù)組),但沒有針對內(nèi)存使用進(jìn)行優(yōu)化。在這里,我們將其替換為就地預(yù)測,它支持基本的推理任務(wù),并且不需要將數(shù)據(jù)復(fù)制到 XGBoost 的內(nèi)部數(shù)據(jù)結(jié)構(gòu)中:

def inplace_predict(client, model, X):
    # Use inplace_predict instead of standard predict.
    predt = dxgb.inplace_predict(client, model, X)
    assert isinstance(predt, dd.Series)
    return predt

內(nèi)存節(jié)省取決于每個塊的大小和輸入類型。當(dāng)使用同一模型多次運(yùn)行推理時,另一個潛在的優(yōu)化是對模型進(jìn)行預(yù)格式化。默認(rèn)情況下,每次調(diào)用predict時, XGBoost 都會將模型傳輸給 worker ,從而產(chǎn)生大量開銷。好消息是 Dask 函數(shù)接受 future 對象作為完成模型的代理。然后我們可以傳輸數(shù)據(jù),這些數(shù)據(jù)可以與其他計算和持久化數(shù)據(jù)重疊。

 def inplace_predict_multi_parts(client, model, X_train, X_valid):
    """Simulate the scenario that we need to run prediction on multiple datasets using train
	and valid. In real world the number of datasets is unlimited

    """
    # prescatter the model onto workers
    model_f = client.scatter(model)
    predictions = []
    for X in [X_train, X_valid]:
        # Use inplace_predict instead of standard predict.
        predt = dxgb.inplace_predict(client, model_f, X)
        assert isinstance(predt, dd.Series)
        predictions.append(predt)
        return predictions

在前面的代碼片段中,我們將未來的模型傳遞給 XGBoost ,而不是真正的模型。 這樣我們就避免了在預(yù)測過程中的重復(fù)傳輸,或者我們可以將模型傳輸與其他操作(如加載數(shù)據(jù))并行,如注釋中所建議的那樣。

把它們放在一起

在前面的部分中,我們將演示早期停止、形狀值計算、自定義目標(biāo)以及最終推斷。下表顯示了具有不同工作線程數(shù)的 GPU 集群的端到端加速。

圖 3 : GPU 集群端到端時間。

與之前一樣,基準(zhǔn)測試是在一臺 NVIDIA DGX-1 服務(wù)器上執(zhí)行的,該服務(wù)器有 8 個 V100 gpu 和兩個 20 核的 Xeon E5 – 2698 v4 cpu ,并進(jìn)行一輪訓(xùn)練、 shap 值計算和推理。此外,我們還共享了兩種內(nèi)存使用優(yōu)化,圖 4 描述了總體內(nèi)存使用比較。

圖 4 :內(nèi)存使用情況。

左兩列是 64 位數(shù)據(jù)類型訓(xùn)練的內(nèi)存使用情況,右兩列是 32 位數(shù)據(jù)類型訓(xùn)練的內(nèi)存使用情況。標(biāo)準(zhǔn)是指使用正常的數(shù)據(jù)矩陣和預(yù)測函數(shù)進(jìn)行訓(xùn)練。有效的方法是使用 DaskDeviceQuantileDMatrix 和 inplace_predict.

Scikit 學(xué)習(xí)包裝器

前面的章節(jié)考慮了“功能”接口的基本模型訓(xùn)練,但是,還有一個類似 scikit 學(xué)習(xí)估計器的接口。它更容易使用,但有更多的限制。在 XGBoost1 。 4 中,此接口與單節(jié)點(diǎn)實(shí)現(xiàn)具有相同的特性。用戶可以選擇不同的估計器,如 DaskXGBClassifier 用于分類,而 DaskXGBRanker 用于排名。查看參考資料以獲得可用估算器的完整列表: https://xgboost.readthedocs.io/en/latest/python/python_api.html#module-xgboost.dask 。

概括

我們已經(jīng)介紹了一個在 GPU 集群上使用 RAPIDS 庫加速 XGBoost 的示例,它顯示了使 XGBoost 代碼現(xiàn)代化可以幫助最大限度地提高培訓(xùn)效率。通過 XGBoost Dask 接口和 RAPIDS ,用戶可以通過一個易于使用的 API 實(shí)現(xiàn)顯著的加速。盡管 XGBoost-Dask 接口已經(jīng)達(dá)到了與單節(jié)點(diǎn) API 的功能對等,但仍在繼續(xù)開發(fā),以便更好地與其他庫集成,實(shí)現(xiàn)超參數(shù)調(diào)優(yōu)等新功能。對于與 dask 接口相關(guān)的新功能請求,您可以在 XGBoost 的 GitHub 存儲庫 上打開一個問題。

關(guān)于作者

Jiaming Yuan 是 NVIDIA 的軟件工程師。

審核編輯:郭婷

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 筆記本電腦
    +關(guān)注

    關(guān)注

    9

    文章

    1385

    瀏覽量

    47363
  • NVIDIA
    +關(guān)注

    關(guān)注

    14

    文章

    4793

    瀏覽量

    102427
  • gpu
    gpu
    +關(guān)注

    關(guān)注

    27

    文章

    4591

    瀏覽量

    128144
收藏 人收藏

    評論

    相關(guān)推薦

    打開我的電腦網(wǎng)頁不是最大化新窗口

    網(wǎng)頁打開不是最大化方法一:先把所有的IE窗口關(guān)了;只打開一個IE窗口;最大化這個窗口;關(guān)了它;OK,以后的默認(rèn)都是最大化的了 方法二:先關(guān)閉所有的IE瀏覽器窗口,用鼠標(biāo)右鍵點(diǎn)擊快速啟動欄的IE瀏覽器
    發(fā)表于 11-10 12:26

    [轉(zhuǎn)]LabVIEW實(shí)現(xiàn)窗口最大化和最小化

    分享VI程序 代碼名稱:LabVIEW實(shí)現(xiàn)窗口最大化和最小化 適用平臺:LabVIEW8.2.x LabVIEW8.5代碼作者:LaRisa_S 版權(quán)所有:LaRisa_S 原創(chuàng)/轉(zhuǎn)載:轉(zhuǎn)載代碼
    發(fā)表于 03-08 14:56

    labview能不能在運(yùn)行的時候讓波形圖最大化

    希望運(yùn)行時讓波形圖最大化顯示,而不是讓整個窗口最大化,最好是能用鼠標(biāo)控制,比如鼠標(biāo)雙擊波形圖就使他放大到全屏顯示,求助啊,大神們啊
    發(fā)表于 08-28 09:28

    動態(tài)調(diào)用子程序窗口最大化問題

    使用動態(tài)調(diào)用實(shí)現(xiàn)多重界面之間的轉(zhuǎn)換,在顯示調(diào)用程序的前面板時,可以使其窗口在出現(xiàn)的時候就最大化嗎?
    發(fā)表于 11-06 22:08

    如何使應(yīng)用程序開機(jī)運(yùn)行最大化

    我現(xiàn)在生成一個應(yīng)用程序并開機(jī)啟動了,但是如何啊能讓他啟動是最大化顯示呢現(xiàn)在一開機(jī)啟動不是最大化啊。。。。。。很苦惱啊,希望大家指點(diǎn)
    發(fā)表于 05-11 20:57

    labview 編寫的應(yīng)用程序,怎么設(shè)置最大化后居中顯示

    本帖最后由 961349487 于 2017-8-14 12:38 編輯 labview 編寫的應(yīng)用程序,怎么設(shè)置最大化最大化后居中顯示,我再VI屬性中已經(jīng)調(diào)過運(yùn)行時的為止選擇最大化了,但是不管用,每次
    發(fā)表于 08-14 11:18

    新的充電器拓?fù)?b class='flag-5'>最大化電池充電速度

    DN194- 新的充電器拓?fù)?b class='flag-5'>最大化電池充電速度
    發(fā)表于 07-17 17:17

    如何在34970A上最大化測量速度?

    如何在34970A上最大化測量速度? 以上來自于谷歌翻譯 以下為原文How can I maximize the measurement speed on my 34970A?
    發(fā)表于 08-06 12:50

    Altium右上角沒有關(guān)閉和最大化的解決辦法

    新手在使用AD時,有時一些失誤的操作:比如不小心按到快捷鍵;會發(fā)現(xiàn)右上角沒有關(guān)閉,最大化等圖標(biāo),即使點(diǎn)擊ESC發(fā)現(xiàn)也沒有辦法恢復(fù)出最大化、關(guān)閉等圖標(biāo)。 這個因?yàn)榘袮D軟件的全屏模式打開了,解決方法
    發(fā)表于 11-07 14:30

    最大化內(nèi)存使用率且保證波形細(xì)節(jié)分析

    最大化內(nèi)存使用率且保證波形細(xì)節(jié)
    發(fā)表于 12-08 06:23

    如何實(shí)現(xiàn)能源效率最大化?

    如何設(shè)計智能燃?xì)獗砗退韺?shí)現(xiàn)能源效率最大化?
    發(fā)表于 05-13 07:18

    最大化電池操作時間

    最大化電池操作時間配備了 Intel Pentium® III 處理器的 Presario 1700 支持 SpeedStep™ 技術(shù)。這種技術(shù)支持兩種不同的操作模式。默認(rèn)設(shè)置為:• 性能模式 (Performance Mod
    發(fā)表于 11-03 14:39 ?9次下載

    最大化自動化測試系統(tǒng)的精度

    最大化自動化測試系統(tǒng)的精度 引言 在設(shè)計自動化測試系統(tǒng)時,精度的最大化通常是關(guān)鍵的考慮因素。確定如何最大化精度總是很困難
    發(fā)表于 06-13 15:02 ?698次閱讀
    <b class='flag-5'>最大化</b>自動化測試系統(tǒng)的精度

    社交網(wǎng)絡(luò)影響力最大化算法及研究綜述

    社交網(wǎng)絡(luò)影響力最大化算法及研究綜述
    發(fā)表于 06-02 14:36 ?6次下載

    基于互信息最大化的Raptor碼優(yōu)化設(shè)計方法

    基于互信息最大化的Raptor碼優(yōu)化設(shè)計方法
    發(fā)表于 07-02 11:47 ?8次下載