Как я могу использовать xgboost.dask с графическим процессором для моделирования очень большого набора данных как распределенным, так и пакетным способом?

Я хотел бы использовать несколько графических процессоров, распределенных по множеству узлов, для обучения модели XGBoost на очень большом наборе данных в рамках машинного обучения Azure с использованием 3 вычислительные узлы NC12s_v3. Размер набора данных превышает размер как VRAM, так и RAM при сохранении в Dask, но удобно помещается на диске. Однако модуль dask сохраняет все данные при обучении. (по крайней мере, по умолчанию).

Вся предварительная обработка данных была обработана (одна горячая кодировка с типом данных np.bool), и можно предположить, что у меня есть наиболее эффективные типы данных в другом месте (например, изменение np.float64 на np.float32 для десятичных функций, изменение на int8 для порядковые данные и т. д.).

В настоящее время я пытаюсь получить простую игрушечную модель, работающую только с обучающим набором. Мой код выглядит следующим образом:

from dask_cuda import LocalCUDACluster
import dask
import xgboost as xgb
import pandas as pd
import numpy as np
import distributed
from dask.distributed import Client, wait, LocalCluster

# Start cluster and client. This is currently local, although I would like to make this distributed across many nodes.
cluster = LocalCUDACluster(n_workers=2, device_memory_limit='16 GiB')
client = distributed.Client(cluster)

# Read in training data.
train_dd = dask.dataframe.read_parquet("folder_of_training_data/*.parquet", chunksize="128 MiB")

# Split into features and target, all other preprocessing including one hot encoding has been completed.
X = train_dd[train_dd.columns.difference(['label'])]
y = train_dd['label']

# Delete dask dataframe to free up memory.
del train_dd

# Create DaskDMatrix from X, y inputs.
dtrain = xgb.dask.DaskDMatrix(client, X, y)

# Delete X and y to free up memory.
del X
del y

# Create watchlist for input into xgb train method.
watchlist = [(dtrain, 'train')]

# Train toy booster on 10 rounds with subsampling and gradient based sampling to reduce memory requirements.
bst = xgb.dask.train(
    client,
    {
        'predictor': 'gpu_predictor', 
        'tree_method': 'gpu_hist', 
        'verbosity': 2, 
        'objective': 'binary:logistic',
        'sampling_method': 'gradient_based',
        'subsample': 0.1
    }, 
    dtrain,
    num_boost_round=10,
    evals=watchlist
)
    
del dtrain

print("History:", str(bst['history']))

С указанным выше на одном узле, содержащем 2 графических процессора, я могу загружать только до 32 ГБ за раз (ограничения VRAM).

Из моего текущего кода у меня есть несколько вопросов:

  1. Есть ли способ остановить XGBoost от сохранения всех данных в памяти, вместо этого, возможно, работая через разделы в пакетах?

  2. Есть ли способ заставить Dask обрабатывать пакетный процесс изначально, а не вручную выполнять, например, инкрементное обучение?

  3. В документации они упоминают, что вы можете использовать режим внешней памяти вместе с их распределенным режимом. Предполагая, что у меня есть файлы libsvm, как мне это сделать с несколькими узлами и несколькими графическими процессорами?

  4. Как я могу изменить приведенный выше код, чтобы я мог работать более чем с одним узлом?

  5. Дополнительный вопрос: предполагая, что существует способ пакетной обработки с помощью xgboost.dask, как я могу интегрировать это с RAPIDS для обработки исключительно на графических процессорах?


person HowdyEarth    schedule 02.07.2020    source источник
comment
привет @HowdyEarth, ты решил эту проблему?   -  person colin-zhou    schedule 10.04.2021


Ответы (1)


В настоящее время Dask-XGBoost ожидает, что ваши данные будут резидентно в памяти графического процессора. В настоящее время ведутся экспериментальные работы как по выделению ресурсов вне ядра в память хоста, так и по инкрементной загрузке данных, но, вероятно, еще слишком рано развертывать один из них.

Какую версию XGBoost вы используете? XGBoost 1.1 во многих случаях значительно снижает использование памяти графического процессора, так что, возможно, стоит попробовать.

Однако, поскольку вы пользуетесь услугами облачного провайдера, развертывание большего количества графических процессоров, вероятно, является самым простым вариантом (и если это ускоряет ваше обучение, вы можете быстрее закрыть эти экземпляры и сохранить стабильные расходы).

По сути, вы запускаете планировщик dask на своем главном узле, а затем запускаете рабочих Dask GPU на каждом из рабочих узлов. (Например, запустив программу командной строки dask-cuda-worker для каждого рабочего.)

Есть несколько старых руководств по настройке кластера Dask в Azure, но это новое обучающее видео от Тома Драбаса и команды AzureML может быть лучшей отправной точкой: https://www.youtube.com/watch? Он использует облачного провайдера Dask для упрощения настройки кластера.

person JZeta    schedule 02.07.2020